// 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.tasktrees.temporalrelation; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance; import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession; import de.ugoe.cs.autoquest.usageprofiles.SymbolMap; import de.ugoe.cs.autoquest.usageprofiles.Trie; import de.ugoe.cs.autoquest.usageprofiles.TrieProcessor; /** *

* TODO comment *

* * @author Patrick Harms */ public class TaskInstanceTrie extends Trie { /** */ private static final long serialVersionUID = 1L; /** *

* the task comparator to be used for comparing tasks *

*/ private TaskComparator comparator; /** *

* TODO: comment *

* * @param taskComparator2 */ public TaskInstanceTrie(TaskComparator taskComparator) { super(taskComparator); this.comparator = taskComparator; } /** * */ public void trainSessions(List userSessions, int maxOrder) { if (maxOrder < 1) { return; } SymbolMap> equalTaskInstancesMap = new SymbolMap>(comparator); Map> taskInstancesMap = new HashMap>(); System.out.println("preparing training"); for (IUserSession session : userSessions) { for (ITaskInstance taskInstance : session) { List equalTaskInstances = equalTaskInstancesMap.getValue(taskInstance); if (equalTaskInstances == null) { equalTaskInstances = new LinkedList(); equalTaskInstancesMap.addSymbol(taskInstance, equalTaskInstances); } equalTaskInstances.add(taskInstance); taskInstancesMap.put(taskInstance, equalTaskInstances); } } System.out.println("performing training"); for (IUserSession session : userSessions) { train(session, maxOrder, taskInstancesMap); } updateKnownSymbols(); } /* (non-Javadoc) * @see de.ugoe.cs.autoquest.usageprofiles.Trie#equals(java.lang.Object) */ @Override public boolean equals(Object other) { if (this == other) { return true; } else if (other instanceof TaskInstanceTrie) { return super.equals(other); } else { return false; } } /* (non-Javadoc) * @see de.ugoe.cs.autoquest.usageprofiles.Trie#hashCode() */ @Override public int hashCode() { return super.hashCode(); } /** * */ private void train(IUserSession userSession, int maxOrder, Map> taskInstancesMap) { List executedTasks = userSession.getExecutedTasks(); List subsequence = new LinkedList(); int numberOfTrainedSubsequences = 0; int sequenceMaxCount = 0; for (ITaskInstance currentTaskInstance : executedTasks) { int occurrenceCount = taskInstancesMap.get(currentTaskInstance).size(); if ((numberOfTrainedSubsequences % 10) == 0) { sequenceMaxCount = getCurrentSequenceMaxCount(); } if (occurrenceCount < sequenceMaxCount) { // this task instance does not need to be considered, as it occurs not often enough // to be part of a sequence, that occurs most often. Therefore train all remaining // sequences so far and go on, until the next useful sequence is found. while (subsequence.size() > 1) { add(subsequence); subsequence.remove(0); } subsequence.clear(); } else { subsequence.add(currentTaskInstance); if (subsequence.size() == maxOrder) { add(subsequence); subsequence.remove(0); numberOfTrainedSubsequences++; } } } // add shorter remaining subsequences, if any while (subsequence.size() > 1) { add(subsequence); subsequence.remove(0); } } /** *

* TODO: comment *

* * @return */ private int getCurrentSequenceMaxCount() { MaxSequenceCountFinder processor = new MaxSequenceCountFinder(); super.process(processor); return processor.getMaxCount(); } /** * @author Patrick Harms */ private static class MaxSequenceCountFinder implements TrieProcessor { /** * */ private int currentCount = 0; /* (non-Javadoc) * @see de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util.List, int) */ @Override public TrieProcessor.Result process(List foundTask, int count) { if (foundTask.size() == 2) { this.currentCount = Math.max(this.currentCount, count); // do not consider children return TrieProcessor.Result.SKIP_NODE; } else { return TrieProcessor.Result.CONTINUE; } } /** * */ private int getMaxCount() { return currentCount; } } }