
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