// 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.ITask;
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
*/
class TaskInstanceTrie extends Trie {
/** */
private static final long serialVersionUID = 1L;
/**
*
* the task comparator to be used for comparing tasks
*
*/
private TaskHandlingStrategy taskStrategy;
/**
*
* TODO: comment
*
*
* @param taskComparator2
*/
public TaskInstanceTrie(TaskHandlingStrategy taskStrategy) {
super(taskStrategy);
this.taskStrategy = taskStrategy;
}
/**
*
*/
public void trainSessions(List userSessions, int maxOrder) {
if (maxOrder < 1) {
return;
}
SymbolMap equalTaskInstancesMap =
taskStrategy.createSymbolMap();
Map instanceCountMap = new HashMap();
System.out.println("preparing training");
int noOfTaskInstances = 0;
for (IUserSession session : userSessions) {
for (ITaskInstance taskInstance : session) {
Counter counter = equalTaskInstancesMap.getValue(taskInstance);
if (counter == null) {
counter = new Counter();
equalTaskInstancesMap.addSymbol(taskInstance, counter);
}
counter.count++;
instanceCountMap.put(taskInstance.getTask(), counter);
noOfTaskInstances++;
}
}
System.out.println("performing training of " + noOfTaskInstances + " task instances");
Counter processedTaskInstances = new Counter();
int counterRecheckAt = noOfTaskInstances / 10; // recheck the maximum count after each
// 10% of processed task instances
for (IUserSession session : userSessions) {
train(session, maxOrder, instanceCountMap, processedTaskInstances, counterRecheckAt);
}
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 taskInstanceCountMap,
Counter processedTaskInstances,
int counterRecheckAt)
{
List executedTasks = userSession.getExecutedTasks();
List subsequence = new LinkedList();
int sequenceMaxCount = 0;
for (ITaskInstance currentTaskInstance : executedTasks) {
int occurrenceCount = taskInstanceCountMap.get(currentTaskInstance.getTask()).count;
if (processedTaskInstances.count >= counterRecheckAt) {
sequenceMaxCount = getCurrentSequenceMaxCount();
processedTaskInstances.count = 0;
}
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);
}
}
processedTaskInstances.count++;
}
// 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;
}
}
/**
* @author Patrick Harms
*/
private static class Counter {
int count = 0;
}
}