de.citec.tcs.alignment.PathList 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.DerivableComparator;
import de.citec.tcs.alignment.sequence.Sequence;
import de.citec.tcs.alignment.sequence.Value;
import java.util.ArrayList;
/**
* This is a list-based datastructure accumulating multiple AlignmentPaths. It
* is also able to calculate the average derivative of all given paths.
*
* @author Benjamin Paassen - [email protected]
*/
public class PathList extends ArrayList implements AlignmentDerivativeAlgorithm {
public PathList() {
super();
}
/**
* {@inheritDoc }
*/
@Override
public Y calculateParameterDerivative(
DerivableComparator comp, String keyword) {
return comp.transformToResult(calculateRawParameterDerivative(comp, keyword));
}
/**
* {@inheritDoc }
*/
@Override
public double[] calculateRawParameterDerivative(
DerivableComparator comp, String keyword) {
final int P = comp.getNumberOfParameters();
final double[] derivatives = new double[P];
if (this.isEmpty()) {
return derivatives;
}
/*
* now we let each path calculate its derivative and calculate the
* average.
*/
for (final AlignmentPath path : this) {
final double[] pathDerivatives = path.calculateRawParameterDerivative(comp, keyword);
for (int p = 0; p < P; p++) {
derivatives[p] += pathDerivatives[p];
}
}
for (int p = 0; p < P; p++) {
derivatives[p] /= (double) this.size();
}
return derivatives;
}
/**
* {@inheritDoc }
*/
@Override
public double[] calculateWeightDerivative() {
if (this.isEmpty()) {
throw new UnsupportedOperationException(
"Weight derivative without any paths is not defined.");
}
/*
* now we let each path calculate its weight derivative and take the
* average.
*/
final int K = get(0).getSpecificaton().size();
final double[] derivative = new double[K];
for (final AlignmentPath path : this) {
final double[] pathDerivative = path.calculateWeightDerivative();
for (int k = 0; k < K; k++) {
derivative[k] += pathDerivative[k];
}
}
for (int k = 0; k < K; k++) {
derivative[k] /= (double) this.size();
}
return derivative;
}
/**
* This transforms the PathList to a matrix, mostly for visualization
* purposes. The matrix is equivalent the dynamic programming algorithm of
* the StrictAlgorithm that created this PathMap. However, only those
* entries are non-zero that are relevant for at least one path in this map.
* The value of the output matrix is defined as the average over
* all path toMatrix outputs.
*
* @return the dynamic programming matrix of the algorithm that created this
* PathList with non-zero entries at positions that are relevant for at
* least
* one path.
*/
public double[][] toMatrix() {
final int m = get(0).getLeft().getNodes().size();
final int n = get(0).getRight().getNodes().size();
final double[][] out = new double[m + 1][n + 1];
for (final AlignmentPath path : this) {
int i = 0;
int j = 0;
double oldScore = 0;
for (final Operation op : path.getOperations()) {
switch (op.getType()) {
case DELETION:
case SKIPDELETION:
case DELETIONREPLACEMENT:
i++;
break;
case INSERTION:
case SKIPINSERTION:
case INSERTIONREPLACEMENT:
j++;
break;
case REPLACEMENT:
i++;
j++;
break;
default:
throw new UnsupportedOperationException("Unsupported operation: " + op.getType());
}
out[i][j] += oldScore + op.getWeightedLocalCost();
oldScore = out[i][j];
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < m; j++) {
if (out[i][j] > 0) {
out[i][j] /= (double) this.size();
}
}
}
return out;
}
/**
* Returns the average distance of all stored paths.
*
* @return the average distance of all stored paths.
*/
@Override
public double getDistance() {
if (this.isEmpty()) {
throw new UnsupportedOperationException(
"Average distance without any paths is not defined.");
}
double sum = 0;
for (final AlignmentPath p : this) {
sum += p.getDistance();
}
return sum / (double) this.size();
}
/**
* {@inheritDoc }
*/
@Override
public Sequence getLeft() {
if (this.isEmpty()) {
throw new UnsupportedOperationException("This PathList is empty.");
}
Sequence left = null;
for (final AlignmentPath p : this) {
if (left == null) {
left = p.getLeft();
} else {
if (left != p.getLeft()) {
throw new UnsupportedOperationException("The AlignmentPaths in this list have no consistent left sequence.");
}
}
}
return left;
}
/**
* {@inheritDoc }
*/
@Override
public Sequence getRight() {
if (this.isEmpty()) {
throw new UnsupportedOperationException("This PathList is empty.");
}
Sequence right = null;
for (final AlignmentPath p : this) {
if (right == null) {
right = p.getRight();
} else {
if (right != p.getRight()) {
throw new UnsupportedOperationException("The AlignmentPaths in this list have no consistent right sequence.");
}
}
}
return right;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy