Ignore:
Timestamp:
07/04/11 15:21:50 (13 years ago)
Author:
sherbold
Message:
  • code documentation
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/EventBenchCore/src/de/ugoe/cs/eventbench/models/FirstOrderMarkovModel.java

    r86 r101  
    1414import Jama.Matrix; 
    1515 
    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 */ 
     28public class FirstOrderMarkovModel extends HighOrderMarkovModel implements 
     29                IDotCompatible { 
     30 
     31        /** 
     32         * <p> 
    1933         * Id for object serialization. 
     34         * </p> 
    2035         */ 
    2136        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         */ 
    2344        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         */ 
    2555        public FirstOrderMarkovModel(Random r) { 
    2656                super(1, r); 
    2757        } 
    28          
     58 
     59        /** 
     60         * <p> 
     61         * Generates the transmission matrix of the Markov model. 
     62         * </p> 
     63         *  
     64         * @return transmission matrix 
     65         */ 
    2966        private Matrix getTransmissionMatrix() { 
    30                 List<Event<?>> knownSymbols = new ArrayList<Event<?>>(trie.getKnownSymbols()); 
     67                List<Event<?>> knownSymbols = new ArrayList<Event<?>>( 
     68                                trie.getKnownSymbols()); 
    3169                int numStates = knownSymbols.size(); 
    3270                Matrix transmissionMatrix = new Matrix(numStates, numStates); 
    33                  
    34                 for( int i=0 ; i<numStates ; i++ ) { 
     71 
     72                for (int i = 0; i < numStates; i++) { 
    3573                        Event<?> currentSymbol = knownSymbols.get(i); 
    3674                        List<Event<?>> context = new ArrayList<Event<?>>(); 
    3775                        context.add(currentSymbol); 
    38                         for( int j=0 ; j<numStates ; j++ ) { 
     76                        for (int j = 0; j < numStates; j++) { 
    3977                                Event<?> follower = knownSymbols.get(j); 
    4078                                double prob = getProbability(context, follower); 
     
    4482                return transmissionMatrix; 
    4583        } 
    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 
    47155        public String getDotRepresentation() { 
    48156                StringBuilder stringBuilder = new StringBuilder(); 
    49157                stringBuilder.append("digraph model {" + StringTools.ENDLINE); 
    50158 
    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); 
    56167                        List<Event<?>> context = new ArrayList<Event<?>>(); 
    57                         context.add(symbol);  
     168                        context.add(symbol); 
    58169                        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); 
    62176                        } 
    63177                } 
     
    65179                return stringBuilder.toString(); 
    66180        } 
    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         */ 
    68190        public Graph<String, MarkovEdge> getGraph() { 
    69191                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) { 
    74197                        String from = symbol.getShortId(); 
    75198                        List<Event<?>> context = new ArrayList<Event<?>>(); 
    76                         context.add(symbol);  
    77                          
     199                        context.add(symbol); 
     200 
    78201                        List<Event<?>> followers = trie.getFollowingSymbols(context); 
    79                          
    80                         for( Event<?> follower : followers ) { 
     202 
     203                        for (Event<?> follower : followers) { 
    81204                                String to = follower.getShortId(); 
    82                                 MarkovEdge prob = new MarkovEdge(getProbability(context, follower)); 
     205                                MarkovEdge prob = new MarkovEdge(getProbability(context, 
     206                                                follower)); 
    83207                                graph.addEdge(prob, from, to, EdgeType.DIRECTED); 
    84208                        } 
     
    86210                return graph; 
    87211        } 
    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         */ 
    89219        static public class MarkovEdge { 
     220                /** 
     221                 * <p> 
     222                 * Weight of the edge, i.e., its transition probability. 
     223                 * </p> 
     224                 */ 
    90225                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                } 
    142247        } 
    143248 
Note: See TracChangeset for help on using the changeset viewer.