source: trunk/EventBenchCore/src/de/ugoe/cs/eventbench/models/Trie.java @ 106

Last change on this file since 106 was 106, checked in by sherbold, 13 years ago
  • code documentation
File size: 8.6 KB
RevLine 
[13]1package de.ugoe.cs.eventbench.models;
[1]2
[86]3import java.io.Serializable;
[102]4import java.util.Collection;
[9]5import java.util.LinkedHashSet;
[1]6import java.util.LinkedList;
7import java.util.List;
8
[30]9import de.ugoe.cs.util.StringTools;
10
[5]11import edu.uci.ics.jung.graph.DelegateTree;
[106]12import edu.uci.ics.jung.graph.Graph;
[5]13import edu.uci.ics.jung.graph.Tree;
14
[106]15/**
16 * <p>
17 * This class implements a <it>trie</it>, i.e., a tree of sequences that the
18 * occurence of subsequences up to a predefined length. This length is the trie
19 * order.
20 * </p>
21 *
22 * @author Steffen Herbold
23 *
24 * @param <T>
25 *            Type of the symbols that are stored in the trie.
26 *
27 * @see TrieNode
28 */
[86]29public class Trie<T> implements IDotCompatible, Serializable {
[106]30
[86]31        /**
[106]32         * <p>
[86]33         * Id for object serialization.
[106]34         * </p>
[86]35         */
36        private static final long serialVersionUID = 1L;
37
[106]38        /**
39         * <p>
40         * Collection of all symbols occuring in the trie.
41         * </p>
42         */
43        private Collection<T> knownSymbols;
44
45        /**
46         * <p>
47         * Reference to the root of the trie.
48         * </p>
49         */
[6]50        private final TrieNode<T> rootNode;
[106]51
52        /**
53         * <p>
54         * Contructor. Creates a new Trie.
55         * </p>
56         */
[6]57        public Trie() {
58                rootNode = new TrieNode<T>();
[9]59                knownSymbols = new LinkedHashSet<T>();
[6]60        }
[106]61
62        /**
63         * <p>
64         * Returns a collection of all symbols occuring in the trie.
65         * </p>
66         *
67         * @return symbols occuring in the trie
68         */
69        public Collection<T> getKnownSymbols() {
[9]70                return new LinkedHashSet<T>(knownSymbols);
71        }
[106]72
73        /**
74         * <p>
75         * Trains the current trie using the given sequence and adds all subsequence
76         * of length {@code maxOrder}.
77         * </p>
78         *
79         * @param sequence
80         *            sequence whose subsequences are added to the trie
81         * @param maxOrder
82         *            maximum length of the subsequences added to the trie
83         */
[9]84        public void train(List<T> sequence, int maxOrder) {
85                IncompleteMemory<T> latestActions = new IncompleteMemory<T>(maxOrder);
[106]86                int i = 0;
87                for (T currentEvent : sequence) {
[9]88                        latestActions.add(currentEvent);
89                        knownSymbols.add(currentEvent);
90                        i++;
[106]91                        if (i >= maxOrder) {
[9]92                                add(latestActions.getLast(maxOrder));
93                        }
94                }
95                int sequenceLength = sequence.size();
[106]96                for (int j = maxOrder - 1; j > 0; j--) {
97                        add(sequence.subList(sequenceLength - j, sequenceLength));
[9]98                }
99        }
[1]100
[106]101        /**
102         * <p>
103         * Adds a given subsequence to the trie and increases the counters
104         * accordingly.
105         * </p>
106         *
107         * @param subsequence
108         *            subsequence whose counters are increased
109         * @see TrieNode#add(List)
110         */
111        protected void add(List<T> subsequence) {
112                if (subsequence != null && !subsequence.isEmpty()) {
[9]113                        knownSymbols.addAll(subsequence);
[106]114                        subsequence = new LinkedList<T>(subsequence); // defensive copy!
[1]115                        T firstSymbol = subsequence.get(0);
[6]116                        TrieNode<T> node = getChildCreate(firstSymbol);
117                        node.add(subsequence);
[1]118                }
119        }
120
[106]121        /**
122         * <p>
123         * Returns the child of the root node associated with the given symbol or
124         * creates it if it does not exist yet.
125         * </p>
126         *
127         * @param symbol
128         *            symbol whose node is required
129         * @return node associated with the symbol
130         * @see TrieNode#getChildCreate(Object)
131         */
132        protected TrieNode<T> getChildCreate(T symbol) {
[6]133                return rootNode.getChildCreate(symbol);
[1]134        }
[106]135
136        /**
137         * <p>
138         * Returns the child of the root node associated with the given symbol or
139         * null if it does not exist.
140         * </p>
141         *
142         * @param symbol
143         *            symbol whose node is required
144         * @return node associated with the symbol; null if no such node exists
145         * @see TrieNode#getChild(Object)
146         */
[1]147        protected TrieNode<T> getChild(T symbol) {
[6]148                return rootNode.getChild(symbol);
[1]149        }
150
[106]151        /**
152         * <p>
153         * Returns the number of occurences of the given sequence.
154         * </p>
155         *
156         * @param sequence
157         *            sequence whose number of occurences is required
158         * @return number of occurences of the sequence
159         */
[1]160        public int getCount(List<T> sequence) {
161                int count = 0;
162                TrieNode<T> node = find(sequence);
[106]163                if (node != null) {
[1]164                        count = node.getCount();
165                }
166                return count;
167        }
[106]168
169        /**
170         * <p>
171         * Returns the number of occurences of the given prefix and a symbol that
172         * follows it.<br>
173         * Convenience function to simplify usage of {@link #getCount(List)}.
174         * </p>
175         *
176         * @param sequence
177         *            prefix of the sequence
178         * @param follower
179         *            suffix of the sequence
180         * @return number of occurences of the sequence
181         * @see #getCount(List)
182         */
[1]183        public int getCount(List<T> sequence, T follower) {
184                List<T> tmpSequence = new LinkedList<T>(sequence);
185                tmpSequence.add(follower);
186                return getCount(tmpSequence);
[106]187
[1]188        }
[106]189
190        /**
191         * <p>
192         * Searches the trie for a given sequence and returns the node associated
193         * with the sequence or null if no such node is found.
194         * </p>
195         *
196         * @param sequence
197         *            sequence that is searched for
198         * @return node associated with the sequence
199         * @see TrieNode#find(List)
200         */
[1]201        public TrieNode<T> find(List<T> sequence) {
[106]202                if (sequence == null || sequence.isEmpty()) {
[6]203                        return rootNode;
204                }
[5]205                List<T> sequenceCopy = new LinkedList<T>(sequence);
[1]206                TrieNode<T> result = null;
[6]207                TrieNode<T> node = getChild(sequenceCopy.get(0));
[106]208                if (node != null) {
[6]209                        sequenceCopy.remove(0);
210                        result = node.find(sequenceCopy);
[1]211                }
212                return result;
213        }
[106]214
215        /**
216         * <p>
217         * Returns a collection of all symbols that follow a given sequence in the
218         * trie. In case the sequence is not found or no symbols follow the sequence
219         * the result will be empty.
220         * </p>
221         *
222         * @param sequence
223         *            sequence whose followers are returned
224         * @return symbols following the given sequence
225         * @see TrieNode#getFollowingSymbols()
226         */
[102]227        public Collection<T> getFollowingSymbols(List<T> sequence) {
228                Collection<T> result = new LinkedList<T>();
[6]229                TrieNode<T> node = find(sequence);
[106]230                if (node != null) {
[6]231                        result = node.getFollowingSymbols();
[1]232                }
233                return result;
234        }
[106]235
236        /**
237         * <p>
238         * Returns the longest suffix of the given context that is contained in the
239         * tree and whose children are leaves.
240         * </p>
241         *
242         * @param context
243         *            context whose suffix is searched for
244         * @return longest suffix of the context
245         */
[1]246        public List<T> getContextSuffix(List<T> context) {
[5]247                List<T> contextSuffix = new LinkedList<T>(context); // defensive copy
[1]248                boolean suffixFound = false;
[106]249
250                while (!suffixFound) {
251                        if (contextSuffix.isEmpty()) {
[1]252                                suffixFound = true; // suffix is the empty word
253                        } else {
254                                TrieNode<T> node = find(contextSuffix);
[106]255                                if (node != null) {
256                                        if (!node.getFollowingSymbols().isEmpty()) {
[1]257                                                suffixFound = true;
258                                        }
259                                }
[106]260                                if (!suffixFound) {
[5]261                                        contextSuffix.remove(0);
262                                }
[1]263                        }
264                }
[106]265
[1]266                return contextSuffix;
267        }
[106]268
269        /**
270         * <p>
271         * Helper class for graph visualization of a trie.
272         * </p>
273         *
274         * @author Steffen Herbold
275         * @version 1.0
276         */
277        static public class Edge {
278        }
279
280        /**
281         * <p>
282         * Helper class for graph visualization of a trie.
283         * </p>
284         *
285         * @author Steffen Herbold
286         * @version 1.0
287         */
[5]288        static public class TrieVertex {
[106]289
290                /**
291                 * <p>
292                 * Id of the vertex.
293                 * </p>
294                 */
[5]295                private String id;
[106]296
297                /**
298                 * <p>
299                 * Contructor. Creates a new TrieVertex.
300                 * </p>
301                 *
302                 * @param id
303                 *            id of the vertex
304                 */
[5]305                protected TrieVertex(String id) {
306                        this.id = id;
307                }
[106]308
309                /**
310                 * <p>
311                 * Returns the id of the vertex.
312                 * </p>
313                 *
314                 * @see java.lang.Object#toString()
315                 */
316                @Override
[5]317                public String toString() {
318                        return id;
319                }
320        }
[106]321
322        /**
323         * <p>
324         * Returns a {@link Graph} representation of the trie.
325         * </p>
326         *
327         * @return {@link Graph} representation of the trie
328         */
[23]329        protected Tree<TrieVertex, Edge> getGraph() {
[5]330                DelegateTree<TrieVertex, Edge> graph = new DelegateTree<TrieVertex, Edge>();
[6]331                rootNode.getGraph(null, graph);
[5]332                return graph;
333        }
[106]334
335        /*
336         * (non-Javadoc)
337         *
338         * @see de.ugoe.cs.eventbench.models.IDotCompatible#getDotRepresentation()
339         */
[30]340        public String getDotRepresentation() {
341                StringBuilder stringBuilder = new StringBuilder();
342                stringBuilder.append("digraph model {" + StringTools.ENDLINE);
343                rootNode.appendDotRepresentation(stringBuilder);
344                stringBuilder.append('}' + StringTools.ENDLINE);
345                return stringBuilder.toString();
346        }
[106]347
348        /**
349         * <p>
350         * Returns the string representation of the root node.
351         * </p>
352         *
353         * @see TrieNode#toString()
354         * @see java.lang.Object#toString()
355         */
[1]356        @Override
357        public String toString() {
[6]358                return rootNode.toString();
[1]359        }
[106]360
361        /**
362         * <p>
363         * Returns the number of symbols contained in the trie.
364         * </p>
365         *
366         * @return
367         */
[66]368        public int getNumSymbols() {
369                return knownSymbols.size();
370        }
[1]371}
Note: See TracBrowser for help on using the repository browser.