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

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

Go to download

This module containts standard implementations of AlignmentAlgorithms. In contrast to the adp module these implementations are hand-tailored for some specific algorithms and thus achieve somewhat faster runtime (a constant factor of maybe 30-50 percent).

The newest version!
/* 
 * TCS Alignment Toolbox Version 3
 * 
 * Copyright (C) 2016
 * Benjamin Paaßen
 * 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.Comparator;
import de.citec.tcs.alignment.comparators.OperationType;
import java.util.List;
import java.util.Random;
import java.util.Stack;
import lombok.NonNull;

/**
 * This is an implementation of the AbstractStrictDTWAlgorithm to calculate just one exemplary
 * optimal DTW Alignment.
 *
 * @author Benjamin Paassen - [email protected]
 * @param  the class of the elements in the left input sequence.
 * @param  the class of the elements in the right input sequence.
 */
public class StrictDTWFullAlgorithm extends AbstractStrictDTWAlgorithm {

	public StrictDTWFullAlgorithm(@NonNull final Comparator comp) {
		super(Alignment.class, comp);
	}

	@Override
	public Alignment transformToResult(@NonNull double[][] dtwMatrix,
			@NonNull double[][] repCosts, @NonNull double[][] delRepCosts, @NonNull double[][] insRepCosts,
			@NonNull List a, @NonNull List b) {

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

		final double normalizedDistance = normalizeDissimilarity(dtwMatrix[m - 1][n - 1], a, b);

		final Alignment path = new Alignment<>(getComparator(), a, b, normalizedDistance);

		final Stack opStack = new Stack<>();
		int i = m - 1;
		int j = n - 1;
		final Random rand = new Random();
		X left;
		Y right;
		Operation op;
		while (i > 0 || j > 0) {
			// get the current sequence elements
			left = a.get(i);
			right = b.get(j);

			// then look how to go backwards.
			// if we are in the first column, we can just go upwards.
			if (j == 0) {
				final OperationType type = OperationType.DELETIONREPLACEMENT;
				op = new Operation(left, right, type, delRepCosts[i][j]);
				opStack.push(op);
				i--;
				continue;
			}
			// if we are in the first row, we can just go left.
			if (i == 0) {
				final OperationType type = OperationType.INSERTIONREPLACEMENT;
				op = new Operation(left, right, type, insRepCosts[i][j]);
				opStack.push(op);
				j--;
				continue;
			}

			// otherwise look for current co-optimals.
			final double opt = dtwMatrix[i][j];
			final boolean[] coopts = new boolean[3];

			coopts[0] = dtwMatrix[i - 1][j] + repCosts[i][j] == opt;
			coopts[1] = dtwMatrix[i - 1][j - 1] + delRepCosts[i][j] == opt;
			coopts[2] = dtwMatrix[i][j - 1] + insRepCosts[i][j] == 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++;
				}
			}
			final OperationType type;
			final double cost;

			if (coopts[0]) {
				// go upwards.
				type = OperationType.DELETIONREPLACEMENT;
				cost = delRepCosts[i][j];
				i--;
			} else if (coopts[1]) {
				// go diagonal.
				type = OperationType.REPLACEMENT;
				cost = repCosts[i][j];
				i--;
				j--;
			} else if (coopts[2]) {
				// go left.
				type = OperationType.INSERTIONREPLACEMENT;
				cost = insRepCosts[i][j];
				j--;
			} else {
				throw new RuntimeException("Internal error: No co-optimal state during backtracing!");
			}
			op = new Operation(left, right, type, cost);
			opStack.push(op);
		}

		// push the last replacement of the initial elements onto the stack.
		left = a.get(0);
		right = b.get(0);
		op = new Operation(left, right, OperationType.REPLACEMENT, repCosts[0][0]);
		opStack.push(op);

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

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy