//package svm.instances.dependency.kernel;
//
//import java.util.ArrayList;
//import java.util.List;
//
//import edu.udo.cs.ls8.kobra.suffixtree.SuffixTreeManager;
//import svm.instances.dependency.TokenSequence;
//import base.Kernel;
//
//public class FastSequenceKernel implements Kernel<TokenSequence>
//{
//	private static final String PARAMETER_STRING_X_ATTRIBUTE = "compare_string_x";
//	private static final String PARAMETER_STRING_Y_ATTRIBUTE = "compare_string_y";
//
//	private static final String PARAMETER_REMOVE_CHARS_FROM_STRING = "remove_characters_from_string";
//	private static final String PARAMETER_CHARSEQUENCE_FOR_CHAR_REMOVAL = "characters_to_remove_from_input_string";
//	// private static final String PARAMETER_MAX_LENGTH_OF_ITEMSET = "trim_itemset_to_max_length";
//
//	private static final String PARAMETER_SINGLE_WORDS_AS_ITEMS = "treat_single_words_as_items";
//	private static final String PARAMETER_DELIMITER_CHARSEQUENCE_GRAPHSTRING = "delimiter_charseq._for_matching_strings";
//
//	private static final String PARAMETER_SELECTED_WEIGHTING_FUNCTION = "weight_function";
//	private static final String[] PARAMETER_WEIGHTING_FUNCTION = { "CONSTANT", "LENGTH_DEPENDENT", "EXPONENTIAL", "BAG_OF_CHARACTERS", "BAG_OF_WORDS", "DEPTH_ENCODING" };
//
//	private static enum WEIGHTING_STRATEGY
//	{
//		CONSTANT, LENGTH_DEPENDENT, EXPONENTIAL, BAG_OF_CHARACTERS, BAG_OF_WORDS, DEPTH_ENCODING;
//	};
//
//	private static int selectedWeightFunc = 1;
//
//	private static final String PARAMETER_WEIGHT = "weight_per_item";
//	private static final String PARAMETER_LAMBDA = "w=(1/lambda)_(use w>1.0)";
//	private static final String PARAMETER_USE_GENERATED_WEIGHTS = "use_generated_weights_list";
//	private static final String PARAMETER_WEIGHTS_1_ATTRIBUTE = "weights_attribute_exampleSet_1";
//	private static final String PARAMETER_WEIGHTS_2_ATTRIBUTE = "weights_attribute_exampleSet_2";
//	private static final String PARAMETER_UNIQUE_CHAR_ATTRIBUTE = "unique_char_for_string_termination";
//
//	private static final String PARAMETER_SELECTED_PRECACHE_STRATEGY = "precache_strategy";
//	private static final String[] PARAMETER_PRECACHE_STRATEGY = { "NO_CACHING", "CACHE_EXAMPLESET_2", "WINDOW" };
//
//	private static enum PRECACHE_STRATEGY
//	{
//		NO_CACHING, CACHE_SET_Y, WINDOW;
//	};
//
//	private static int selectedPrecacheStrategy = 1;
//
//	private static final String PARAMETER_PRECACHING_WINDOW_SIZE_X = "window_size_x";
//	private static final String PARAMETER_PRECACHING_WINDOW_SIZE_Y = "window_size_y";
//
//	private static final String PARAMETER_LOG_TOTAL_COMP_TIMES = "log_total_computation_times";
//	private static final String PARAMETER_LOG_KERNEL_COMPUTATION = "log_kernel_computation";
//	private static final String PARAMETER_LOG_SIMILARITIES = "log_similarities";
//	private static final String PARAMETER_LOG_KERNEL_DETAIL_COMPUTATION = "log_kernel_computation_details_(use_with_caution)";
//	// private static final String PARAMETER_LOG_WEIGHTS_COMPUTATION = "log_weights_computation_(use_with_caution)";
//
//	private final InputPort mExampleSet1Input = getInputPorts().createPort("example set 1", ExampleSet.class);
//	private final InputPort mExampleSet2Input = getInputPorts().createPort("example set 2", ExampleSet.class);
//	private final OutputPort mExampleSetOutput = getOutputPorts().createPort("example set output");
//
//	private ExampleSet exSet1 = null;
//	private ExampleSet exSet2 = null;
//
//	private static List<List<Double>> mListOfWeightsOfItemsX = new ArrayList<List<Double>>(); // weights of items in itemset X
//	private static List<List<Double>> mListOfWeightsOfItemsY = new ArrayList<List<Double>>(); // weights of items in itemset Y
//
//	private static List<List<String>> listOfSuffixPatternListOfStringsX = new ArrayList<List<String>>();
//	private static List<List<String>> listOfSuffixPatternListOfStringsY = new ArrayList<List<String>>();
//	private static List<List<Character>> listOfSuffixPatternListOfCharactersX = new ArrayList<List<Character>>();
//	private static List<List<Character>> listOfSuffixPatternListOfCharactersY = new ArrayList<List<Character>>();
//
//	@SuppressWarnings("rawtypes")
//	private static SuffixTreeManager suffixTreeMangrX = null;
//	@SuppressWarnings("rawtypes")
//	private static SuffixTreeManager suffixTreeMangrY = null;
//
//	private static List<SuffixTreeManager<?>> mListOfSuffixTreeManagersX = new ArrayList<SuffixTreeManager<?>>();
//	private static List<SuffixTreeManager<?>> mListOfSuffixTreeManagersY = new ArrayList<SuffixTreeManager<?>>();
//
//	private static List<Double> mListOfSimilaritiesOfItemsX = new ArrayList<Double>(); // similarities between items within itemset X
//	private static List<Double> mListOfSimilaritiesOfItemsY = new ArrayList<Double>(); // similarities between items within itemset Y
//
//	private static double mSimilarityOfItemSetX = 0.0d; // similarity of itemset X with itself
//	private static double mSimilarityOfItemSetY = 0.0d; // similarity of itemset X with itself
//
//	private static boolean bKeepSingleWords = false;
//	private static double mWeight = 1.0d;
//	private static boolean mUseManualWeights = false;
//	private static char mTerminationChar = '§';
//
//	private static boolean logKernelInfo = false;
//	private static boolean logKernelDetailInfo = false;
//	private static boolean logSimilarityInfo = false;
//
//	private static long timeForParsingInput = 0;
//	private static long timeForCalcSuffixTrees = 0;
//	private static long timeForMatchingStatistics = 0;
//	private static long timeForCalcContribValues = 0;
//	private static long timeForCalcSimilarities = 0;
//
//	private static int numberOfSuffixTrees = 0;
//	private static boolean set1EqualsSet2 = false;
//	private static boolean set1HasOne_vs_Set2HasOne = false;
//
//	@Override
//	public double k(TokenSequence a, TokenSequence b)
//	{
//		// TODO Auto-generated method stub
//		return 0;
//	}
//
//	@Override
//	public void doWork()
//	{
//		exSet1 = (ExampleSet) mExampleSet1Input.getData(ExampleSet.class).clone();
//		exSet2 = (ExampleSet) mExampleSet2Input.getData(ExampleSet.class).clone();
//
//		boolean bRemoveCharsFromString = false;
//		char[] charsToRemoveFromInputString = new char[0];
//		// int maxLengthOfInputStrings = getParameterAsInt(PARAMETER_MAX_LENGTH_OF_ITEMSET);
//
//		bKeepSingleWords = true;// getParameterAsBoolean(PARAMETER_SINGLE_WORDS_AS_ITEMS);
//		String delimCharSequence = "[], ";// getParameterAsString(PARAMETER_DELIMITER_CHARSEQUENCE_GRAPHSTRING);
//		mTerminationChar = '\0'; // getParameterAsChar(PARAMETER_UNIQUE_CHAR_ATTRIBUTE);
//
//		// Store the weights into fresh lists, if the parameter is set
//		// *
//
//		mListOfWeightsOfItemsX = new ArrayList<List<Double>>(); // weights of items in itemset X
//		mListOfWeightsOfItemsY = new ArrayList<List<Double>>(); // weights of items in itemset Y
//
//		mUseManualWeights = false;
//
//		// -------------------------------------------------------------------------------------------
//
//		// -------------------------------------------------------------------------------------------
//		/*
//		 * Precaching
//		 * 
//		 * 1. Preprocess the lists of patterns from the attributes "mStringAttribX" and "mStringAttribY" of each Example.
//		 * Each extracted patternlist can then be re-used when comparing with all the strings of the other ExampleSet, thus saving valuable time.
//		 * 
//		 * - in case of a so called graphStrings - which represents a tree by a set of node labels (e.g. pos tags) in bracket notation,
//		 * a dedicated GraphStringParser extracts the "words" to a patternLists.
//		 * 
//		 * - in case of strings we split the strings into a lists of single characters.
//		 * 
//		 * 2. Construct the SuffixTrees (via a SuffixTreeManager) for each given patternList
//		 * - a unique termination character is required
//		 * - a defaultWeight can be assigned
//		 * - the resulting Manager is collected in a list of managers for the SuffixTrees of set X and Y
//		 * 
//		 * 3. Perform a matching of the shorter itemset with the SuffixTree of the longer itemset.
//		 * As such we require SuffixTrees from all itemsets X and Y.
//		 */
//
//		long startTotalTime = System.nanoTime();
//		long startTime = System.nanoTime();
//
//		mListOfSuffixTreeManagersX = new ArrayList<SuffixTreeManager<?>>();
//		mListOfSuffixTreeManagersY = new ArrayList<SuffixTreeManager<?>>();
//
//		suffixTreeMangrX = null;
//		suffixTreeMangrY = null;
//
//		mListOfSimilaritiesOfItemsX = new ArrayList<Double>();
//		mListOfSimilaritiesOfItemsY = new ArrayList<Double>();
//
//		listOfSuffixPatternListOfStringsX = new ArrayList<List<String>>();
//		listOfSuffixPatternListOfStringsY = new ArrayList<List<String>>();
//		listOfSuffixPatternListOfCharactersX = new ArrayList<List<Character>>();
//		listOfSuffixPatternListOfCharactersY = new ArrayList<List<Character>>();
//
//		timeForCalcSuffixTrees = 0;
//		timeForMatchingStatistics = 0;
//		timeForCalcContribValues = 0;
//		timeForCalcSimilarities = 0;
//		numberOfSuffixTrees = 0;
//		timeForParsingInput = 0;
//
//		// 1.
//
//		for (int n = 0; n < exSet1.size(); n++)
//		{
//			String patternString = exSet1.getExample(n).getValueAsString(stringXAttrib);
//
//			if (bRemoveCharsFromString)
//			{
//				for (char c : charsToRemoveFromInputString)
//					patternString = patternString.replaceAll("" + c, "");
//			}
//			List<Character> suffixPatternListOfCharacters = new ArrayList<Character>();
//			// int counter = 0;
//			for (char c : patternString.toCharArray())
//			{
//				// if ( counter == maxLengthOfInputStrings) break; //terminate when maximumLength of items has been reached; avoid using subList or substring as these methods became O(n) operations
//				// with Java 7
//				suffixPatternListOfCharacters.add(c);
//				// counter++;
//			}
//			listOfSuffixPatternListOfCharactersX.add(suffixPatternListOfCharacters);
//		}
//
//		for (int m = 0; m < exSet2.size(); m++)
//		{
//			String patternString = exSet2.getExample(m).getValueAsString(stringYAttrib);
//
//			// if(patternString.length() > maxLengthOfInputStrings)
//			// patternString = patternString.substring(0, maxLengthOfInputStrings);
//
//			if (bRemoveCharsFromString)
//			{
//				for (char c : charsToRemoveFromInputString)
//					patternString = patternString.replaceAll("" + c, "");
//			}
//
//			List<Character> suffixPatternListOfCharacters = new ArrayList<Character>();
//			// int counter = 0;
//			for (char c : patternString.toCharArray())
//			{
//				// if ( counter == maxLengthOfInputStrings) break;
//				suffixPatternListOfCharacters.add(c);
//				// counter++;
//			}
//			listOfSuffixPatternListOfCharactersY.add(suffixPatternListOfCharacters);
//		}
//
//		timeForParsingInput = (long) ((System.nanoTime() - startTime) / 1000);
//
//		// -------------------------------------------------------------------------------------------
//		//
//		// Loop for computation of the (n*m) fast string kernels in O(n*m) time
//		//
//
//		MemoryExampleTable table = new MemoryExampleTable(attributes);
//		DataRowFactory factory = new DataRowFactory(DataRowFactory.TYPE_DOUBLE_ARRAY, '.');
//		List<DataRow> data_rows = new ArrayList<DataRow>();
//
//		// prepare the data rows aka kernel matrix; the first column is reserved for ids
//		for (int n = 0; n < exSet1.size(); n++)
//		{
//			data_rows.add(factory.create(table.getNumberOfAttributes()));
//			data_rows.get(n).set(attributes.get(0 + shiftByOne), n + 1); // set the id, starting with 1
//		}
//
//		if (selectedPrecacheStrategy == PRECACHE_STRATEGY.CACHE_SET_Y.ordinal())
//		{
//			preCacheSuffixTreeSetY(0, exSet2.size()); // calc & precache all the SuffixTrees of itemSet Y
//		}
//
//		if (selectedPrecacheStrategy == PRECACHE_STRATEGY.WINDOW.ordinal())
//		{
//			int window_size_x = getParameterAsInt(PARAMETER_PRECACHING_WINDOW_SIZE_X);
//			int window_size_y = getParameterAsInt(PARAMETER_PRECACHING_WINDOW_SIZE_Y);
//
//			if (window_size_x > exSet1.size())
//				window_size_x = exSet1.size();
//			if (window_size_y > exSet2.size())
//				window_size_y = exSet2.size();
//
//			for (int n = 0; n < exSet1.size(); n += window_size_x)
//			{
//				preCacheSuffixTreeSetX(n, window_size_x); // calc & precache all the SuffixTrees of itemSet X (from n to n+window_size_x)
//
//				for (int m = (set1EqualsSet2 ? n : 0); m < exSet2.size(); m += window_size_y)
//				{
//					preCacheSuffixTreeSetY(m, window_size_y); // calc & precache all the SuffixTrees of itemSet Y (from m to m+window_size_y)
//
//					for (int x = 0; x < window_size_x; x++)
//					{
//						int pos_x = n + x; // determine the "correct" x-coordinate
//						if (pos_x == exSet1.size())
//							break;
//
//						for (int y = 0; y < window_size_y; y++)
//						{
//							int pos_y = m + y; // determine the "correct" y-coordinate
//							if (pos_y == exSet2.size())
//								break;
//
//							double similarity = 0.0d;
//							if (pos_x == pos_y)
//								similarity = 1.0d;
//							else
//							{
//								suffixTreeMangrX = mListOfSuffixTreeManagersX.get(x);
//								suffixTreeMangrY = mListOfSuffixTreeManagersY.get(y);
//
//								mSimilarityOfItemSetX = mListOfSimilaritiesOfItemsX.get(x);
//								mSimilarityOfItemSetY = mListOfSimilaritiesOfItemsY.get(y);
//
//								similarity = computeSimilarityOfCurrentPairOfExamples(pos_x, pos_y);
//							}
//
//							// if ( pos_x <= pos_y )
//							data_rows.get(pos_x).set(attributes.get(pos_y + shiftByOne + 1), similarity); // +1 because we have the id column on the first position
//
//							// fill lower triangle matrix if ExampleSet1 == ExampleSet2
//							if (set1EqualsSet2 && pos_x < pos_y)
//								data_rows.get(pos_y).set(attributes.get(pos_x + shiftByOne + 1), similarity);
//						}
//					}
//				}
//			}
//		}
//		else
//		{ // if precaching is "no_caching" "line_by_line":
//			for (int n = 0; n < exSet1.size(); n++)
//			{
//				// cache the itemset X + SuffixTree of the current example n:
//				preCacheSuffixTreeX(n);
//
//				for (int m = (set1EqualsSet2 ? n : 0); m < exSet2.size(); m++)
//				{
//					double similarity = 0.0d;
//					if (n == m && !set1HasOne_vs_Set2HasOne)
//						similarity = 1.0d;
//					else
//					{
//						if (selectedPrecacheStrategy == PRECACHE_STRATEGY.NO_CACHING.ordinal())
//						{
//							// suffixTreeMangrX is already set
//							preCacheSuffixTreeY(m);
//						}
//						else if (selectedPrecacheStrategy == PRECACHE_STRATEGY.CACHE_SET_Y.ordinal())
//						{
//							// suffixTreeMangrX is already set
//							suffixTreeMangrY = mListOfSuffixTreeManagersY.get(m);
//							mSimilarityOfItemSetY = mListOfSimilaritiesOfItemsY.get(m);
//						}
//						else
//						{ // precache_all:
//							suffixTreeMangrX = mListOfSuffixTreeManagersX.get(n);
//							suffixTreeMangrY = mListOfSuffixTreeManagersY.get(m);
//
//							mSimilarityOfItemSetX = mListOfSimilaritiesOfItemsX.get(n);
//							mSimilarityOfItemSetY = mListOfSimilaritiesOfItemsY.get(m);
//						}
//					}
//
//					similarity = computeSimilarityOfCurrentPairOfExamples(n, m);
//
//					// compute and store the similarity in the attribute column of this DataRow:
//					data_rows.get(n).set(attributes.get(m + shiftByOne + 1), similarity);
//					if (set1EqualsSet2 && n < m)
//						data_rows.get(m).set(attributes.get(n + shiftByOne + 1), similarity);
//				}
//			}
//		}
//
//		// transfer all data rows to the MemoryExampleTable
//		for (int n = 0; n < exSet1.size(); n++)
//			table.addDataRow(data_rows.get(n));
//
//
//
//		SimpleExampleSet resultSet = new SimpleExampleSet(table, specialAttributesMap);
//
//		// add labels from the original example set:
//		if (exSet1.getAttributes().getLabel() != null)
//			for (int i = 0; i < resultSet.size(); i++)
//			{
//				Example origEx = exSet1.getExample(i);
//				resultSet.getExample(i).setLabel(origEx.getLabel());
//			}
//
//		mExampleSetOutput.deliver(resultSet);
//	}
//
//	// compute the similarity of the currently set suffixTreeMangrX and suffixTreeMangrY
//	@SuppressWarnings("unchecked")
//	private double computeSimilarityOfCurrentPairOfExamples(int n, int m) throws OperatorException
//	{
//		if (logKernelInfo)
//			LogService.getRoot().log(Level.INFO, "Computing (" + n + "," + m + ")");
//
//		long startTime = 0;
//		double k = 0.0d;
//
//		if (n == m && !set1HasOne_vs_Set2HasOne)
//			k = 1.0d; // since the result for equal itemSets will always be 1.0 we skip any calculation
//		else
//		{
//			// compute the similarities of itemSets X with itemSets Y
//			// The SuffixTree with the larger itemset will be used, and the smaller set passed to calculate the matching statistics
//
//			if (suffixTreeMangrX.getNumberOfItems() >= suffixTreeMangrY.getNumberOfItems())
//			{
//				startTime = System.nanoTime();
//				suffixTreeMangrX.calculateMatchingStatistics(suffixTreeMangrY.getItems());
//				timeForMatchingStatistics += (long) ((System.nanoTime() - startTime) / 1000);
//
//				startTime = System.nanoTime();
//				// compute the sum of similarities of all matching substrings
//				try
//				{
//					k = suffixTreeMangrX.computeSimilarity();
//				}
//				catch (Exception e)
//				{
//					throw new OperatorException(e.getMessage());
//				}
//			}
//			else
//			{
//				startTime = System.nanoTime();
//				suffixTreeMangrY.calculateMatchingStatistics(suffixTreeMangrX.getItems());
//				timeForMatchingStatistics += (long) ((System.nanoTime() - startTime) / 1000);
//
//				startTime = System.nanoTime();
//				// compute the sum of similarities of all matching substrings
//				try
//				{
//					k = suffixTreeMangrY.computeSimilarity();
//				}
//				catch (Exception e)
//				{
//					throw new OperatorException(e.getMessage());
//				}
//
//			}
//
//			double simProduct = mSimilarityOfItemSetX * mSimilarityOfItemSetY;
//			double sqrRoot = Math.sqrt(simProduct);
//
//			if (logSimilarityInfo)
//				LogService.getRoot().log(Level.INFO,
//						"------------" +
//								"\n normalising result:" +
//								"\n k(" + n + "," + m + "): " + k +
//								"\n k(X=" + n + ",X=" + n + "): " + mSimilarityOfItemSetX +
//								"\n k(Y=" + m + ",Y=" + m + "): " + mSimilarityOfItemSetY +
//								"\n k(X,X) * k(Y,Y): " + simProduct +
//								"\n sqrt[k(X,X) * k(Y,Y)]: " + sqrRoot);
//
//			k = (sqrRoot == 0) ? 0 : k / sqrRoot; // normalize by division of k by the square root of the product of the similarities of itemsets X and Y with itself:
//			timeForCalcSimilarities += (long) ((System.nanoTime() - startTime) / 1000);
//		}
//
//		if (logKernelInfo)
//			LogService.getRoot().log(Level.INFO, "--- \n Final k = k(X,Y) / sqrt[k(X,X) * k(Y,Y)] = " + k);
//		if (logKernelDetailInfo)
//			LogService.getRoot().log(Level.INFO, "\n------------\n");
//
//		return k;
//	}
//
//	private void preCacheSuffixTreeSetX(int startIndexOfInterval, int interval_size) throws OperatorException
//	{
//		long startTime = 0;
//
//		mListOfSimilaritiesOfItemsX = new ArrayList<Double>(); // fresh set of similarities
//		mListOfSuffixTreeManagersX = new ArrayList<SuffixTreeManager<?>>(); // fresh set of SuffixTrees
//
//		// make sure we do not exceed the size of the ExampleSet
//		int lastIndex = interval_size;
//		if (exSet1.size() < startIndexOfInterval + interval_size)
//			lastIndex = exSet1.size() % interval_size;
//
//		for (int index = startIndexOfInterval; index < startIndexOfInterval + lastIndex; index++)
//		{
//			startTime = System.nanoTime();
//
//			if (mUseManualWeights && selectedWeightFunc == WEIGHTING_STRATEGY.DEPTH_ENCODING.ordinal())
//			{
//				if (bKeepSingleWords)
//					suffixTreeMangrX = new SuffixTreeManager<String>(listOfSuffixPatternListOfStringsX.get(index), "" + mTerminationChar, mListOfWeightsOfItemsX.get(index), mWeight,
//							selectedWeightFunc);
//				else
//					suffixTreeMangrX = new SuffixTreeManager<Character>(listOfSuffixPatternListOfCharactersX.get(index), mTerminationChar, mListOfWeightsOfItemsX.get(index), mWeight,
//							selectedWeightFunc);
//			}
//			else
//			{
//				if (bKeepSingleWords)
//					suffixTreeMangrX = new SuffixTreeManager<String>(listOfSuffixPatternListOfStringsX.get(index), "" + mTerminationChar, mWeight, selectedWeightFunc);
//				else
//					suffixTreeMangrX = new SuffixTreeManager<Character>(listOfSuffixPatternListOfCharactersX.get(index), mTerminationChar, mWeight, selectedWeightFunc);
//			}
//
//			numberOfSuffixTrees++;
//			timeForCalcSuffixTrees += (long) ((System.nanoTime() - startTime) / 1000);
//
//			suffixTreeMangrX.setLogger(LogService.getRoot(), logKernelDetailInfo);
//
//			startTime = System.nanoTime();
//			suffixTreeMangrX.calculateMatchingStatisticsWithOwnItems(); // measure the similarity of this set of items with itself
//			timeForMatchingStatistics += (long) ((System.nanoTime() - startTime) / 1000);
//
//			startTime = System.nanoTime();
//			suffixTreeMangrX.calculateContribValues();
//			timeForCalcContribValues += (long) ((System.nanoTime() - startTime) / 1000);
//
//			startTime = System.nanoTime();
//			try
//			{
//				mListOfSimilaritiesOfItemsX.add(suffixTreeMangrX.computeSimilarity());
//			}
//			catch (Exception e)
//			{
//				throw new OperatorException(e.getMessage());
//			}
//			timeForCalcSimilarities += (long) ((System.nanoTime() - startTime) / 1000);
//
//			mListOfSuffixTreeManagersX.add(suffixTreeMangrX);
//		}
//	}
//
//	private void preCacheSuffixTreeSetY(int startIndexOfInterval, int interval_size) throws OperatorException
//	{
//		long startTime = 0;
//
//		mListOfSimilaritiesOfItemsY = new ArrayList<Double>(); // fresh set of similarities
//		mListOfSuffixTreeManagersY = new ArrayList<SuffixTreeManager<?>>(); // fresh set of SuffixTrees
//
//		// make sure we do not exceed the size of the ExampleSet
//		int lastIndex = interval_size;
//		if (exSet2.size() < startIndexOfInterval + interval_size)
//			lastIndex = exSet2.size() % interval_size;
//
//		for (int index = startIndexOfInterval; index < startIndexOfInterval + lastIndex; index++)
//		{
//			startTime = System.nanoTime();
//
//			if (bKeepSingleWords)
//				suffixTreeMangrY = new SuffixTreeManager<String>(listOfSuffixPatternListOfStringsY.get(index), "" + mTerminationChar, mWeight, selectedWeightFunc);
//			else
//				suffixTreeMangrY = new SuffixTreeManager<Character>(listOfSuffixPatternListOfCharactersY.get(index), mTerminationChar, mWeight, selectedWeightFunc);
//
//			numberOfSuffixTrees++;
//			timeForCalcSuffixTrees += (long) ((System.nanoTime() - startTime) / 1000);
//
//			suffixTreeMangrY.setLogger(LogService.getRoot(), logKernelDetailInfo);
//
//			startTime = System.nanoTime();
//			suffixTreeMangrY.calculateMatchingStatisticsWithOwnItems(); // measure the similarity of this set of items with itself
//			timeForMatchingStatistics += (long) ((System.nanoTime() - startTime) / 1000);
//
//			startTime = System.nanoTime();
//			suffixTreeMangrY.calculateContribValues();
//			timeForCalcContribValues += (long) ((System.nanoTime() - startTime) / 1000);
//
//			startTime = System.nanoTime();
//
//			try
//			{
//				mListOfSimilaritiesOfItemsY.add(suffixTreeMangrY.computeSimilarity());
//			}
//			catch (Exception e)
//			{
//				throw new OperatorException(e.getMessage());
//			}
//			timeForCalcSimilarities += (long) ((System.nanoTime() - startTime) / 1000);
//
//			mListOfSuffixTreeManagersY.add(suffixTreeMangrY);
//		}
//	}
//
//	private void preCacheSuffixTreeX(int index) throws OperatorException
//	{
//		long startTime = System.nanoTime();
//
//		if (mUseManualWeights && selectedWeightFunc == WEIGHTING_STRATEGY.DEPTH_ENCODING.ordinal())
//		{
//			if (bKeepSingleWords)
//				suffixTreeMangrX = new SuffixTreeManager<String>(listOfSuffixPatternListOfStringsX.get(index), "" + mTerminationChar, mListOfWeightsOfItemsX.get(index), mWeight, selectedWeightFunc);
//			else
//				suffixTreeMangrX = new SuffixTreeManager<Character>(listOfSuffixPatternListOfCharactersX.get(index), mTerminationChar, mListOfWeightsOfItemsX.get(index), mWeight, selectedWeightFunc);
//		}
//		else
//		{
//			if (bKeepSingleWords)
//				suffixTreeMangrX = new SuffixTreeManager<String>(listOfSuffixPatternListOfStringsX.get(index), "" + mTerminationChar, mWeight, selectedWeightFunc);
//			else
//				suffixTreeMangrX = new SuffixTreeManager<Character>(listOfSuffixPatternListOfCharactersX.get(index), mTerminationChar, mWeight, selectedWeightFunc);
//		}
//
//		numberOfSuffixTrees++;
//		timeForCalcSuffixTrees += (long) ((System.nanoTime() - startTime) / 1000);
//
//		suffixTreeMangrX.setLogger(LogService.getRoot(), logKernelDetailInfo);
//
//		startTime = System.nanoTime();
//		suffixTreeMangrX.calculateMatchingStatisticsWithOwnItems(); // measure the similarity of this set of items with itself
//		timeForMatchingStatistics += (long) ((System.nanoTime() - startTime) / 1000);
//
//		startTime = System.nanoTime();
//		suffixTreeMangrX.calculateContribValues();
//		timeForCalcContribValues += (long) ((System.nanoTime() - startTime) / 1000);
//
//		startTime = System.nanoTime();
//		// Compute similarity of this itemsetX with itself:
//		try
//		{
//			mSimilarityOfItemSetX = suffixTreeMangrX.computeSimilarity();
//		}
//		catch (Exception e)
//		{
//			throw new OperatorException(e.getMessage());
//		}
//		timeForCalcSimilarities += (long) ((System.nanoTime() - startTime) / 1000);
//	}
//
//	private void preCacheSuffixTreeY(int index) throws OperatorException
//	{
//		long startTime = System.nanoTime();
//
//		if (mUseManualWeights && selectedWeightFunc == WEIGHTING_STRATEGY.DEPTH_ENCODING.ordinal())
//		{
//			if (bKeepSingleWords)
//				suffixTreeMangrY = new SuffixTreeManager<String>(listOfSuffixPatternListOfStringsY.get(index), "" + mTerminationChar, mListOfWeightsOfItemsY.get(index), mWeight, selectedWeightFunc);
//			else
//				suffixTreeMangrY = new SuffixTreeManager<Character>(listOfSuffixPatternListOfCharactersY.get(index), mTerminationChar, mListOfWeightsOfItemsY.get(index), mWeight, selectedWeightFunc);
//		}
//		else
//		{
//			if (bKeepSingleWords)
//				suffixTreeMangrY = new SuffixTreeManager<String>(listOfSuffixPatternListOfStringsY.get(index), "" + mTerminationChar, mWeight, selectedWeightFunc);
//			else
//				suffixTreeMangrY = new SuffixTreeManager<Character>(listOfSuffixPatternListOfCharactersY.get(index), mTerminationChar, mWeight, selectedWeightFunc);
//		}
//
//		numberOfSuffixTrees++;
//		timeForCalcSuffixTrees += (long) ((System.nanoTime() - startTime) / 1000);
//
//		suffixTreeMangrY.setLogger(LogService.getRoot(), logKernelDetailInfo);
//
//		startTime = System.nanoTime();
//		suffixTreeMangrY.calculateMatchingStatisticsWithOwnItems(); // measure the similarity of this set of items with itself
//		timeForMatchingStatistics += (long) ((System.nanoTime() - startTime) / 1000);
//
//		startTime = System.nanoTime();
//		suffixTreeMangrY.calculateContribValues();
//		timeForCalcContribValues += (long) ((System.nanoTime() - startTime) / 1000);
//
//		startTime = System.nanoTime();
//		// Compute similarity of this itemsetY with itself:
//		try
//		{
//			mSimilarityOfItemSetY = suffixTreeMangrY.computeSimilarity();
//		}
//		catch (Exception e)
//		{
//			throw new OperatorException(e.getMessage());
//		}
//		timeForCalcSimilarities += (long) ((System.nanoTime() - startTime) / 1000);
//	}
//
//	// Rough estimation of the total calculation time (based on the input of the very first example
//	// - assuming all input string have roughly the same length):
//	private int estimateTotalCalculationTime() throws OperatorException
//	{
//		timeForCalcSuffixTrees = 0;
//		timeForMatchingStatistics = 0;
//		timeForCalcContribValues = 0;
//		timeForCalcSimilarities = 0;
//		numberOfSuffixTrees = 0;
//
//		try
//		{
//			preCacheSuffixTreeX(0);
//		}
//		catch (Exception e)
//		{
//			throw new OperatorException(e.getMessage());
//		}
//
//		// use the first one to "warm" up (since first run is always very slow)
//		if (exSet1.size() > 1)
//		{
//			timeForCalcSuffixTrees = 0;
//			timeForMatchingStatistics = 0;
//			timeForCalcContribValues = 0;
//			timeForCalcSimilarities = 0;
//			numberOfSuffixTrees = 0;
//			try
//			{
//				preCacheSuffixTreeX(1);
//			}
//			catch (Exception e)
//			{
//				throw (OperatorException) e;
//			}
//		}
//
//		long totalCalculations = exSet1.size() * exSet2.size(); // O(n * m)
//
//		if (selectedPrecacheStrategy == PRECACHE_STRATEGY.NO_CACHING.ordinal())
//			totalCalculations += exSet2.size(); // O(n*m + m)
//
//		else if (selectedPrecacheStrategy == PRECACHE_STRATEGY.CACHE_SET_Y.ordinal())
//			totalCalculations = exSet1.size() + exSet2.size(); // O(n + m)
//
//		else if (selectedPrecacheStrategy == PRECACHE_STRATEGY.WINDOW.ordinal())
//		{
//			int window_size_x = getParameterAsInt(PARAMETER_PRECACHING_WINDOW_SIZE_X);
//			int window_size_y = getParameterAsInt(PARAMETER_PRECACHING_WINDOW_SIZE_Y);
//			totalCalculations = exSet1.size() / window_size_x + exSet2.size() / window_size_y; // rough estimation suffices
//		}
//
//		float estimatedTimeForSuffixTrees = totalCalculations * timeForCalcSuffixTrees / 1000000.0f;
//		float estimatedTimeForMatchingStats = exSet1.size() * exSet2.size() * timeForMatchingStatistics / 1000000.0f;
//		float estimatedTimeForContribValues = totalCalculations * timeForCalcContribValues / 1000000.0f;
//		float estimatedTimeForSimilarities = totalCalculations * timeForCalcSimilarities / 1000000.0f;
//
//		// LogService.getRoot().log(Level.INFO, "Estimated calc for SuffixTrees: \t" + totalCalculations * timeForCalcSuffixTrees /1000.0f + " ms.");
//		// LogService.getRoot().log(Level.INFO, "Estimated calc for MatchingStatistics: \t" + totalCalculations * timeForMatchingStatistics /1000.0f + " ms.");
//		// LogService.getRoot().log(Level.INFO, "Estimated calc for ContribValues: \t" + totalCalculations * timeForCalcContribValues /1000.0f + " ms.");
//		// LogService.getRoot().log(Level.INFO, "Estimated calc for Similarities: \t" + totalCalculations * timeForCalcSimilarities /1000.0f + " ms.");
//
//		int result = (int) (estimatedTimeForSuffixTrees + estimatedTimeForMatchingStats + estimatedTimeForContribValues + estimatedTimeForSimilarities);
//
//		timeForCalcSuffixTrees = 0;
//		timeForMatchingStatistics = 0;
//		timeForCalcContribValues = 0;
//		timeForCalcSimilarities = 0;
//		numberOfSuffixTrees = 0;
//
//		return result;
//	}
//
//	public List<ParameterType> getParameterTypes()
//	{
//		List<ParameterType> types = super.getParameterTypes();
//
//		types.add(new ParameterTypeString(PARAMETER_STRING_X_ATTRIBUTE,
//				"attribute of the 1st input string",
//				"stringX", false));
//
//		types.add(new ParameterTypeString(PARAMETER_STRING_Y_ATTRIBUTE,
//				"attribute of the 2nd input string",
//				"stringY", false));
//
//		types.add(new ParameterTypeChar(PARAMETER_UNIQUE_CHAR_ATTRIBUTE,
//				"The given character here *must not* appear in any of the the input strings (required during the construction of Suffix Trees)",
//				'§', false));
//
//		types.add(new ParameterTypeBoolean(PARAMETER_REMOVE_CHARS_FROM_STRING,
//				"toggle on if you want specific characters to be removed from input strings",
//				false, false));
//
//		ParameterType type = new ParameterTypeString(PARAMETER_CHARSEQUENCE_FOR_CHAR_REMOVAL,
//				"any of the characters you define here will be removed from input strings",
//				"\", ;:'´`°^{}()[]€$§&@#", false);
//		type.registerDependencyCondition(new BooleanParameterCondition(this, PARAMETER_REMOVE_CHARS_FROM_STRING, false, true));
//		types.add(type);
//
//		// types.add(new ParameterTypeInt(PARAMETER_MAX_LENGTH_OF_ITEMSET,
//		// "Trim the created itemset (of words or characters) to this maximum length.",
//		// 0,Integer.MAX_VALUE, 10000, true));
//
//		type = new ParameterTypeBoolean(PARAMETER_SINGLE_WORDS_AS_ITEMS,
//				"treat single words as items. Only equal items will be matched. If unchecked each character of a string becomes an item",
//				false, false);
//		type.registerDependencyCondition(new BooleanParameterCondition(this, PARAMETER_REMOVE_CHARS_FROM_STRING, false, false));
//		types.add(type);
//
//		type = new ParameterTypeString(PARAMETER_DELIMITER_CHARSEQUENCE_GRAPHSTRING,
//				"delimiter char sequence for the matching strings",
//				"[], ", false);
//		type.registerDependencyCondition(new BooleanParameterCondition(this, PARAMETER_REMOVE_CHARS_FROM_STRING, false, false));
//		type.registerDependencyCondition(new BooleanParameterCondition(this, PARAMETER_SINGLE_WORDS_AS_ITEMS, false, true));
//		type.setExpert(true);
//		types.add(type);
//
//		types.add(new ParameterTypeBoolean(PARAMETER_USE_GENERATED_WEIGHTS,
//				"Toggle on if you want to use the weights list given from ",
//				false, false));
//		types.add(type);
//
//		type = new ParameterTypeString(PARAMETER_WEIGHTS_1_ATTRIBUTE,
//				"The name of the attribute containing the weights from ExampleSet 1 for the nodes in the parse tree of each example",
//				"weights", false);
//		type.registerDependencyCondition(new BooleanParameterCondition(this, PARAMETER_USE_GENERATED_WEIGHTS, false, true));
//		types.add(type);
//
//		type = new ParameterTypeString(PARAMETER_WEIGHTS_2_ATTRIBUTE,
//				"The name of the attribute containing the weights from ExampleSet 2 for the nodes in the parse tree of each example",
//				"weights", false);
//		type.registerDependencyCondition(new BooleanParameterCondition(this, PARAMETER_USE_GENERATED_WEIGHTS, false, true));
//		types.add(type);
//
//		type = new ParameterTypeCategory(
//				PARAMETER_SELECTED_WEIGHTING_FUNCTION,
//				"chose a weight function; for large strings the exponential function is more appropriate",
//				PARAMETER_WEIGHTING_FUNCTION,
//				1);
//		type.setExpert(true);
//		types.add(type);
//
//		type = new ParameterTypeDouble(PARAMETER_WEIGHT,
//				"Define a default weight",
//				0.0d, Double.MAX_VALUE, 1.0d, true);
//		type.registerDependencyCondition(new EqualTypeCondition(this, PARAMETER_SELECTED_WEIGHTING_FUNCTION, PARAMETER_WEIGHTING_FUNCTION, true, 1));
//		types.add(type);
//
//		type = new ParameterTypeDouble(PARAMETER_LAMBDA,
//				"Use values > 1. The reciprocal value is calculated from the parameter input (hence a 2 will result in lambda 0.5)",
//				1.0000000000000002d, Double.MAX_VALUE, 1.0000000000000002, true);
//		type.registerDependencyCondition(new EqualTypeCondition(this, PARAMETER_SELECTED_WEIGHTING_FUNCTION, PARAMETER_WEIGHTING_FUNCTION, true, 2, 5));
//		types.add(type);
//
//		types.add(new ParameterTypeBoolean(PARAMETER_LOG_TOTAL_COMP_TIMES,
//				"log the total computation time & statistics",
//				true, true));
//
//		types.add(new ParameterTypeBoolean(PARAMETER_LOG_SIMILARITIES,
//				"log the similarities of the compared strings (not normalized)",
//				false, true));
//
//		types.add(new ParameterTypeBoolean(PARAMETER_LOG_KERNEL_COMPUTATION,
//				"log the results of the kernel computation for a given pair of examples",
//				false, true));
//
//		types.add(new ParameterTypeBoolean(PARAMETER_LOG_KERNEL_DETAIL_COMPUTATION,
//				"log details during the kernel computation (e.g. matching substrings)",
//				false, true));
//
//		// types.add(new ParameterTypeBoolean(PARAMETER_LOG_WEIGHTS_COMPUTATION,
//		// "logging output of the calculation of weights",
//		// false, true));
//
//		type = new ParameterTypeCategory(
//				PARAMETER_SELECTED_PRECACHE_STRATEGY,
//				"chose the precache strategy \"WINDOW\" if you deal with very large data sets (e.g. comparing several thousand examples among each other)",
//				PARAMETER_PRECACHE_STRATEGY,
//				1);
//		type.setExpert(true);
//		types.add(type);
//
//		type = new ParameterTypeInt(PARAMETER_PRECACHING_WINDOW_SIZE_X,
//				"interval size x along ExampleSet 1 during precaching of a window moving from left to right and top to bottom in the matrix of ExampleSets",
//				1, Integer.MAX_VALUE, 10, true);
//		type.registerDependencyCondition(new EqualTypeCondition(this, PARAMETER_SELECTED_PRECACHE_STRATEGY, PARAMETER_PRECACHE_STRATEGY, true, 2));
//		type.setExpert(true);
//		types.add(type);
//
//		type = new ParameterTypeInt(PARAMETER_PRECACHING_WINDOW_SIZE_Y,
//				"interval size y along ExampleSet 2 during precaching with a window moving from left to right and top to down in the matrix of ExampleSets",
//				1, Integer.MAX_VALUE, 10, true);
//		type.registerDependencyCondition(new EqualTypeCondition(this, PARAMETER_SELECTED_PRECACHE_STRATEGY, PARAMETER_PRECACHE_STRATEGY, true, 2));
//		type.setExpert(true);
//		types.add(type);
//
//		return types;
//	}
//
//}