- Timestamp:
- 07/04/11 15:21:50 (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/EventBenchCore/src/de/ugoe/cs/eventbench/models/FirstOrderMarkovModel.java
r86 r101 14 14 import Jama.Matrix; 15 15 16 public class FirstOrderMarkovModel extends HighOrderMarkovModel implements IDotCompatible { 17 18 /** 16 /** 17 * <p> 18 * Implements first-order Markov models. The implementation is based on 19 * {@link HighOrderMarkovModel} and restricts the Markov order to 1. In 20 * comparison to {@link HighOrderMarkovModel}, more calculations are possible 21 * with first-order models, e.g., the calculation of the entropy ( 22 * {@link #calcEntropy()}). 23 * </p> 24 * 25 * @author Steffen Herbold 26 * @version 1.0 27 */ 28 public class FirstOrderMarkovModel extends HighOrderMarkovModel implements 29 IDotCompatible { 30 31 /** 32 * <p> 19 33 * Id for object serialization. 34 * </p> 20 35 */ 21 36 private static final long serialVersionUID = 1L; 22 37 38 /** 39 * <p> 40 * Maximum number of iterations when calculating the stationary distribution 41 * as the limit of multiplying the transmission matrix with itself. 42 * </p> 43 */ 23 44 final static int MAX_STATDIST_ITERATIONS = 1000; 24 45 46 /** 47 * <p> 48 * Constructor. Creates a new FirstOrderMarkovModel. 49 * </p> 50 * 51 * @param r 52 * random number generator used by probabilistic methods of the 53 * class 54 */ 25 55 public FirstOrderMarkovModel(Random r) { 26 56 super(1, r); 27 57 } 28 58 59 /** 60 * <p> 61 * Generates the transmission matrix of the Markov model. 62 * </p> 63 * 64 * @return transmission matrix 65 */ 29 66 private Matrix getTransmissionMatrix() { 30 List<Event<?>> knownSymbols = new ArrayList<Event<?>>(trie.getKnownSymbols()); 67 List<Event<?>> knownSymbols = new ArrayList<Event<?>>( 68 trie.getKnownSymbols()); 31 69 int numStates = knownSymbols.size(); 32 70 Matrix transmissionMatrix = new Matrix(numStates, numStates); 33 34 for ( int i=0 ; i<numStates ; i++) {71 72 for (int i = 0; i < numStates; i++) { 35 73 Event<?> currentSymbol = knownSymbols.get(i); 36 74 List<Event<?>> context = new ArrayList<Event<?>>(); 37 75 context.add(currentSymbol); 38 for ( int j=0 ; j<numStates ; j++) {76 for (int j = 0; j < numStates; j++) { 39 77 Event<?> follower = knownSymbols.get(j); 40 78 double prob = getProbability(context, follower); … … 44 82 return transmissionMatrix; 45 83 } 46 84 85 /** 86 * <p> 87 * Calculates the entropy of the model. To make it possible that the model 88 * is stationary, a transition from {@link Event#ENDEVENT} to 89 * {@link Event#STARTEVENT} is added. 90 * </p> 91 * 92 * @return entropy of the model or NaN if it could not be calculated 93 */ 94 public double calcEntropy() { 95 Matrix transmissionMatrix = getTransmissionMatrix(); 96 List<Event<?>> knownSymbols = new ArrayList<Event<?>>( 97 trie.getKnownSymbols()); 98 int numStates = knownSymbols.size(); 99 100 int startStateIndex = knownSymbols.indexOf(Event.STARTEVENT); 101 int endStateIndex = knownSymbols.indexOf(Event.ENDEVENT); 102 if (startStateIndex == -1) { 103 Console.printerrln("Error calculating entropy. Initial state of markov chain not found."); 104 return Double.NaN; 105 } 106 if (endStateIndex == -1) { 107 Console.printerrln("Error calculating entropy. End state of markov chain not found."); 108 return Double.NaN; 109 } 110 transmissionMatrix.set(endStateIndex, startStateIndex, 1); 111 112 // Calculate stationary distribution by raising the power of the 113 // transmission matrix. 114 // The rank of the matrix should fall to 1 and each two should be the 115 // vector of the stationory distribution. 116 int iter = 0; 117 int rank = transmissionMatrix.rank(); 118 Matrix stationaryMatrix = (Matrix) transmissionMatrix.clone(); 119 while (iter < MAX_STATDIST_ITERATIONS && rank > 1) { 120 stationaryMatrix = stationaryMatrix.times(stationaryMatrix); 121 rank = stationaryMatrix.rank(); 122 iter++; 123 } 124 125 if (rank != 1) { 126 Console.traceln("rank: " + rank); 127 Console.printerrln("Unable to calculate stationary distribution."); 128 return Double.NaN; 129 } 130 131 double entropy = 0.0; 132 for (int i = 0; i < numStates; i++) { 133 for (int j = 0; j < numStates; j++) { 134 if (transmissionMatrix.get(i, j) != 0) { 135 double tmp = stationaryMatrix.get(i, 0); 136 tmp *= transmissionMatrix.get(i, j); 137 tmp *= Math.log(transmissionMatrix.get(i, j)) / Math.log(2); 138 entropy -= tmp; 139 } 140 } 141 } 142 return entropy; 143 } 144 145 /** 146 * <p> 147 * The dot represenation of {@link FirstOrderMarkovModel}s is its graph 148 * representation with the states as nodes and directed edges weighted with 149 * transition probabilities. 150 * </p> 151 * 152 * @see de.ugoe.cs.eventbench.models.IDotCompatible#getDotRepresentation() 153 */ 154 @Override 47 155 public String getDotRepresentation() { 48 156 StringBuilder stringBuilder = new StringBuilder(); 49 157 stringBuilder.append("digraph model {" + StringTools.ENDLINE); 50 158 51 List<Event<?>> knownSymbols = new ArrayList<Event<?>>(trie.getKnownSymbols()); 52 53 for( Event<?> symbol : knownSymbols) { 54 final String thisSaneId = symbol.getShortId().replace("\"", "\\\"").replaceAll("[\r\n]",""); 55 stringBuilder.append(" " + symbol.hashCode() + " [label=\""+thisSaneId+"\"];" + StringTools.ENDLINE); 159 List<Event<?>> knownSymbols = new ArrayList<Event<?>>( 160 trie.getKnownSymbols()); 161 162 for (Event<?> symbol : knownSymbols) { 163 final String thisSaneId = symbol.getShortId().replace("\"", "\\\"") 164 .replaceAll("[\r\n]", ""); 165 stringBuilder.append(" " + symbol.hashCode() + " [label=\"" 166 + thisSaneId + "\"];" + StringTools.ENDLINE); 56 167 List<Event<?>> context = new ArrayList<Event<?>>(); 57 context.add(symbol); 168 context.add(symbol); 58 169 List<Event<?>> followers = trie.getFollowingSymbols(context); 59 for( Event<?> follower : followers ) { 60 stringBuilder.append(" "+symbol.hashCode()+" -> " + follower.hashCode() + " "); 61 stringBuilder.append("[label=\"" + getProbability(context, follower) + "\"];" + StringTools.ENDLINE); 170 for (Event<?> follower : followers) { 171 stringBuilder.append(" " + symbol.hashCode() + " -> " 172 + follower.hashCode() + " "); 173 stringBuilder.append("[label=\"" 174 + getProbability(context, follower) + "\"];" 175 + StringTools.ENDLINE); 62 176 } 63 177 } … … 65 179 return stringBuilder.toString(); 66 180 } 67 181 182 /** 183 * <p> 184 * Returns a {@link Graph} represenation of the model with the states as 185 * nodes and directed edges weighted with transition probabilities. 186 * </p> 187 * 188 * @return {@link Graph} of the model 189 */ 68 190 public Graph<String, MarkovEdge> getGraph() { 69 191 Graph<String, MarkovEdge> graph = new SparseMultigraph<String, MarkovEdge>(); 70 71 List<Event<?>> knownSymbols = new ArrayList<Event<?>>(trie.getKnownSymbols()); 72 73 for( Event<?> symbol : knownSymbols) { 192 193 List<Event<?>> knownSymbols = new ArrayList<Event<?>>( 194 trie.getKnownSymbols()); 195 196 for (Event<?> symbol : knownSymbols) { 74 197 String from = symbol.getShortId(); 75 198 List<Event<?>> context = new ArrayList<Event<?>>(); 76 context.add(symbol); 77 199 context.add(symbol); 200 78 201 List<Event<?>> followers = trie.getFollowingSymbols(context); 79 80 for ( Event<?> follower : followers) {202 203 for (Event<?> follower : followers) { 81 204 String to = follower.getShortId(); 82 MarkovEdge prob = new MarkovEdge(getProbability(context, follower)); 205 MarkovEdge prob = new MarkovEdge(getProbability(context, 206 follower)); 83 207 graph.addEdge(prob, from, to, EdgeType.DIRECTED); 84 208 } … … 86 210 return graph; 87 211 } 88 212 213 /** 214 * Inner class used for the {@link Graph} representation of the model. 215 * 216 * @author Steffen Herbold 217 * @version 1.0 218 */ 89 219 static public class MarkovEdge { 220 /** 221 * <p> 222 * Weight of the edge, i.e., its transition probability. 223 * </p> 224 */ 90 225 double weight; 91 MarkovEdge(double weight) { this.weight = weight; } 92 public String toString() { return ""+weight; } 93 } 94 95 public double calcEntropy() { 96 Matrix transmissionMatrix = getTransmissionMatrix(); 97 List<Event<?>> knownSymbols = new ArrayList<Event<?>>(trie.getKnownSymbols()); 98 int numStates = knownSymbols.size(); 99 100 int startStateIndex = knownSymbols.indexOf(Event.STARTEVENT); 101 int endStateIndex = knownSymbols.indexOf(Event.ENDEVENT); 102 if( startStateIndex==-1 ) { 103 Console.printerrln("Error calculating entropy. Initial state of markov chain not found."); 104 return Double.NaN; 105 } 106 if( endStateIndex==-1 ) { 107 Console.printerrln("Error calculating entropy. End state of markov chain not found."); 108 return Double.NaN; 109 } 110 transmissionMatrix.set(endStateIndex, startStateIndex, 1); 111 112 // Calculate stationary distribution by raising the power of the transmission matrix. 113 // The rank of the matrix should fall to 1 and each two should be the vector of the 114 // stationory distribution. 115 int iter = 0; 116 int rank = transmissionMatrix.rank(); 117 Matrix stationaryMatrix = (Matrix) transmissionMatrix.clone(); 118 while( iter<MAX_STATDIST_ITERATIONS && rank>1 ) { 119 stationaryMatrix = stationaryMatrix.times(stationaryMatrix); 120 rank = stationaryMatrix.rank(); 121 iter++; 122 } 123 124 if( rank!=1 ) { 125 Console.traceln("rank: " + rank); 126 Console.printerrln("Unable to calculate stationary distribution."); 127 return Double.NaN; 128 } 129 130 double entropy = 0.0; 131 for( int i=0 ; i<numStates ; i++ ) { 132 for( int j=0 ; j<numStates ; j++ ) { 133 if( transmissionMatrix.get(i,j)!=0 ) { 134 double tmp = stationaryMatrix.get(i, 0); 135 tmp *= transmissionMatrix.get(i, j); 136 tmp *= Math.log(transmissionMatrix.get(i,j))/Math.log(2); 137 entropy -= tmp; 138 } 139 } 140 } 141 return entropy; 226 227 /** 228 * <p> 229 * Constructor. Creates a new MarkovEdge. 230 * </p> 231 * 232 * @param weight 233 * weight of the edge, i.e., its transition probability 234 */ 235 MarkovEdge(double weight) { 236 this.weight = weight; 237 } 238 239 /** 240 * <p> 241 * The weight of the edge as {@link String}. 242 * </p> 243 */ 244 public String toString() { 245 return "" + weight; 246 } 142 247 } 143 248
Note: See TracChangeset
for help on using the changeset viewer.