All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.citec.tcs.alignment.StrictDTWFullAlgorithm Maven / Gradle / Ivy

/* 
 * TCS Alignment Toolbox
 * 
 * Copyright (C) 2013-2015
 * Benjamin Paaßen, Georg Zentgraf
 * AG Theoretical Computer Science
 * Centre of Excellence Cognitive Interaction Technology (CITEC)
 * University of Bielefeld
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see .
 */
package de.citec.tcs.alignment;

import de.citec.tcs.alignment.comparators.OperationType;
import de.citec.tcs.alignment.sequence.Node;
import de.citec.tcs.alignment.sequence.Sequence;
import java.util.Random;
import java.util.Stack;

/**
 * This is an implementation of the AbstractStrictDTWAlgorithm to
 * calculate just one exemplary optimal DTW path.
 *
 * @author Benjamin Paassen - [email protected]
 */
public class StrictDTWFullAlgorithm extends AbstractStrictDTWAlgorithm {

	public StrictDTWFullAlgorithm(final AlignmentSpecification spec) {
		super(AlignmentPath.class, spec);
	}

	/**
	 * {@inheritDoc }
	 */
	@Override
	public AlignmentPath transformToResult(
			double[][] dtwMatrix, Sequence a, Sequence b) {

		final int m = a.getNodes().size();
		final int n = b.getNodes().size();

		final double normalizedScore = dtwMatrix[m - 1][n - 1] / (double) (m + n);

		final AlignmentSpecification spec = getSpecification();

		final AlignmentPath path = new AlignmentPath(spec, a, b, normalizedScore);

		final Stack opStack = new Stack<>();
		int i = m - 1;
		int j = n - 1;
		final Random rand = new Random();
		Node left, right;
		Operation op;
		double[] local;
		while (i > 0 || j > 0) {
			//add the current operation at any rate.
			left = a.getNodes().get(i);
			right = b.getNodes().get(j);
			op = new Operation(left, right,
					OperationType.REPLACEMENT, path);
			local = spec.calculateReplacementCosts(left, right);
			op.setComparatorDistances(local);
			opStack.push(op);

			//then look how to go backwards.
			//if we are in the first column, we can just go upwards.
			if (j == 0) {
				i--;
				continue;
			}
			//if we are in the first row, we can just go left.
			if (i == 0) {
				j--;
				continue;
			}

			//otherwise look for current co-optimals.
			final double opt = Math.min(dtwMatrix[i - 1][j - 1],
					Math.min(dtwMatrix[i - 1][j], dtwMatrix[i][j - 1]));
			final boolean[] coopts = new boolean[3];

			coopts[0] = dtwMatrix[i - 1][j] == opt;
			coopts[1] = dtwMatrix[i - 1][j - 1] == opt;
			coopts[2] = dtwMatrix[i][j - 1] == opt;

			int num_coopts = 0;
			for (final boolean coopt : coopts) {
				if (coopt) {
					num_coopts++;
				}
			}

			if (num_coopts > 1) {
				//reduce the number of paths taken back to 1.
				int r = rand.nextInt(num_coopts);
				int c = 0;
				while (c < coopts.length) {
					if (coopts[c]) {
						if (r > 0) {
							coopts[c] = false;
						}
						r--;
					}
					c++;
				}
			}
			//go upwards.
			if (coopts[0]) {
				i--;
				continue;
			}
			//go diagonal.
			if (coopts[1]) {
				i--;
				j--;
				continue;
			}
			//go left.
			if (coopts[2]) {
				j--;
			}
		}

		//now push all operations on the path.
		while (!opStack.empty()) {
			path.getOperations().add(opStack.pop());
		}
		return path;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy