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
Line 
1package de.ugoe.cs.eventbench.models;
2
3import java.io.Serializable;
4import java.util.Collection;
5import java.util.LinkedHashSet;
6import java.util.LinkedList;
7import java.util.List;
8
9import de.ugoe.cs.util.StringTools;
10
11import edu.uci.ics.jung.graph.DelegateTree;
12import edu.uci.ics.jung.graph.Graph;
13import edu.uci.ics.jung.graph.Tree;
14
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 */
29public class Trie<T> implements IDotCompatible, Serializable {
30
31        /**
32         * <p>
33         * Id for object serialization.
34         * </p>
35         */
36        private static final long serialVersionUID = 1L;
37
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         */
50        private final TrieNode<T> rootNode;
51
52        /**
53         * <p>
54         * Contructor. Creates a new Trie.
55         * </p>
56         */
57        public Trie() {
58                rootNode = new TrieNode<T>();
59                knownSymbols = new LinkedHashSet<T>();
60        }
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() {
70                return new LinkedHashSet<T>(knownSymbols);
71        }
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         */
84        public void train(List<T> sequence, int maxOrder) {
85                IncompleteMemory<T> latestActions = new IncompleteMemory<T>(maxOrder);
86                int i = 0;
87                for (T currentEvent : sequence) {
88                        latestActions.add(currentEvent);
89                        knownSymbols.add(currentEvent);
90                        i++;
91                        if (i >= maxOrder) {
92                                add(latestActions.getLast(maxOrder));
93                        }
94                }
95                int sequenceLength = sequence.size();
96                for (int j = maxOrder - 1; j > 0; j--) {
97                        add(sequence.subList(sequenceLength - j, sequenceLength));
98                }
99        }
100
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()) {
113                        knownSymbols.addAll(subsequence);
114                        subsequence = new LinkedList<T>(subsequence); // defensive copy!
115                        T firstSymbol = subsequence.get(0);
116                        TrieNode<T> node = getChildCreate(firstSymbol);
117                        node.add(subsequence);
118                }
119        }
120
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) {
133                return rootNode.getChildCreate(symbol);
134        }
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         */
147        protected TrieNode<T> getChild(T symbol) {
148                return rootNode.getChild(symbol);
149        }
150
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         */
160        public int getCount(List<T> sequence) {
161                int count = 0;
162                TrieNode<T> node = find(sequence);
163                if (node != null) {
164                        count = node.getCount();
165                }
166                return count;
167        }
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         */
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);
187
188        }
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         */
201        public TrieNode<T> find(List<T> sequence) {
202                if (sequence == null || sequence.isEmpty()) {
203                        return rootNode;
204                }
205                List<T> sequenceCopy = new LinkedList<T>(sequence);
206                TrieNode<T> result = null;
207                TrieNode<T> node = getChild(sequenceCopy.get(0));
208                if (node != null) {
209                        sequenceCopy.remove(0);
210                        result = node.find(sequenceCopy);
211                }
212                return result;
213        }
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         */
227        public Collection<T> getFollowingSymbols(List<T> sequence) {
228                Collection<T> result = new LinkedList<T>();
229                TrieNode<T> node = find(sequence);
230                if (node != null) {
231                        result = node.getFollowingSymbols();
232                }
233                return result;
234        }
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         */
246        public List<T> getContextSuffix(List<T> context) {
247                List<T> contextSuffix = new LinkedList<T>(context); // defensive copy
248                boolean suffixFound = false;
249
250                while (!suffixFound) {
251                        if (contextSuffix.isEmpty()) {
252                                suffixFound = true; // suffix is the empty word
253                        } else {
254                                TrieNode<T> node = find(contextSuffix);
255                                if (node != null) {
256                                        if (!node.getFollowingSymbols().isEmpty()) {
257                                                suffixFound = true;
258                                        }
259                                }
260                                if (!suffixFound) {
261                                        contextSuffix.remove(0);
262                                }
263                        }
264                }
265
266                return contextSuffix;
267        }
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         */
288        static public class TrieVertex {
289
290                /**
291                 * <p>
292                 * Id of the vertex.
293                 * </p>
294                 */
295                private String id;
296
297                /**
298                 * <p>
299                 * Contructor. Creates a new TrieVertex.
300                 * </p>
301                 *
302                 * @param id
303                 *            id of the vertex
304                 */
305                protected TrieVertex(String id) {
306                        this.id = id;
307                }
308
309                /**
310                 * <p>
311                 * Returns the id of the vertex.
312                 * </p>
313                 *
314                 * @see java.lang.Object#toString()
315                 */
316                @Override
317                public String toString() {
318                        return id;
319                }
320        }
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         */
329        protected Tree<TrieVertex, Edge> getGraph() {
330                DelegateTree<TrieVertex, Edge> graph = new DelegateTree<TrieVertex, Edge>();
331                rootNode.getGraph(null, graph);
332                return graph;
333        }
334
335        /*
336         * (non-Javadoc)
337         *
338         * @see de.ugoe.cs.eventbench.models.IDotCompatible#getDotRepresentation()
339         */
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        }
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         */
356        @Override
357        public String toString() {
358                return rootNode.toString();
359        }
360
361        /**
362         * <p>
363         * Returns the number of symbols contained in the trie.
364         * </p>
365         *
366         * @return
367         */
368        public int getNumSymbols() {
369                return knownSymbols.size();
370        }
371}
Note: See TracBrowser for help on using the repository browser.