// Copyright 2012 Georg-August-Universität Göttingen, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package de.ugoe.cs.autoquest.usageprofiles; import java.util.LinkedList; import java.util.List; import java.util.Random; import de.ugoe.cs.autoquest.eventcore.Event; import de.ugoe.cs.autoquest.eventcore.StringEventType; /** *

* This class provides functions to create flattened first-order Markov models from * {@link HighOrderMarkovModel}s and {@link PredictionByPartialMatch} models through state * splitting. *

*

* If possible, the normal high-order markov model should be used, as the Events may be broken by * the flattener, as, e.g., the information {@link ReplayableEvent}s contain is not preserved. *

* * @author Steffen Herbold * @version 1.0 */ public class ModelFlattener { private static final String EVENT_SEPARATOR = "-=-"; Trie firstOrderTrie; /** *

* Takes a {@link HighOrderMarkovModel} and returns a {@link FirstOrderMarkovModel} that * conserves the high-order memory through state splitting. *

* * @param model * model that is flattened * @return flattened first-order Markov model */ public FirstOrderMarkovModel flattenHighOrderMarkovModel(HighOrderMarkovModel model) { int markovOrder = model.trieOrder - 1; FirstOrderMarkovModel firstOrderModel = new FirstOrderMarkovModel(new Random()); firstOrderModel.trieOrder = 2; if (markovOrder == 1) { firstOrderModel.trie = new Trie(model.trie); firstOrderModel.trieOrder = 2; } else { firstOrderTrie = new Trie(); TrieNode rootNode = model.trie.find(null); generateFirstOrderTrie(rootNode, new LinkedList(), markovOrder); firstOrderTrie.updateKnownSymbols(); firstOrderModel.trie = firstOrderTrie; } return firstOrderModel; } /** *

* This method is not available yet and always return null! *

*

* Takes a {@link PredictionByPartialMatch} model and returns a {@link FirstOrderMarkovModel} * that conserves the high-order memory through state splitting. *

* * @param model * model that is flattened * @return flattened first-order Markov model */ public FirstOrderMarkovModel flattenPredictionByPartialMatch(PredictionByPartialMatch model) { // TODO implement method return null; } /** *

* Converts all nodes of the given depth into first-order node through state-splitting. For each * node at the given depth a new node is created and appropriate transitions will be added. *

*

* This method traverses through the tree recursively. If the recursion reaches the desired * depth in the tree, node are added. *

* * @param currentNode * node whose sub-trie is currently traversed * @param parentIDs * ID strings of the ancestors of the currentNode * @param depth * depth to go - NOT the current depth. */ private void generateFirstOrderTrie(TrieNode currentNode, List parentIDs, int depth) { for (TrieNode child : currentNode.getChildren()) { String currentId = child.getSymbol().getId(); if (depth > 1) { List childParentIDs = new LinkedList(parentIDs); childParentIDs.add(currentId); generateFirstOrderTrie(child, childParentIDs, depth - 1); } else { StringBuilder firstOrderID = new StringBuilder(); for (String parentID : parentIDs) { firstOrderID.append(parentID + EVENT_SEPARATOR); } firstOrderID.append(currentId); TrieNode firstOrderNode = firstOrderTrie.getChildCreate(new Event(new StringEventType(firstOrderID .toString()))); firstOrderNode.setCount(child.getCount()); for (TrieNode transitionChild : child.getChildren()) { StringBuilder transitionID = new StringBuilder(); for (String parentID : parentIDs.subList(1, parentIDs.size())) { transitionID.append(parentID + EVENT_SEPARATOR); } transitionID.append(currentId + EVENT_SEPARATOR); transitionID.append(transitionChild.getSymbol().getId()); TrieNode firstOrderTransitionChild = firstOrderNode.getChildCreate(new Event(new StringEventType(transitionID .toString()))); firstOrderTransitionChild.setCount(transitionChild.getCount()); } } } } }