
de.citec.tcs.alignment.StrictDTWFullAlgorithm Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of algorithms-lib Show documentation
Show all versions of algorithms-lib Show documentation
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