
de.citec.tcs.alignment.AlignmentList Maven / Gradle / Ivy
/*
* 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.DerivableComparator;
import java.util.ArrayList;
import java.util.List;
import lombok.NonNull;
/**
* 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]
* @param the class of the elements in the left input sequence.
* @param the class of the elements in the right input sequence.
*/
public class AlignmentList extends ArrayList> implements DerivableAlignmentDistance {
public AlignmentList() {
super();
}
/**
* This transforms the AlignmentList to a matrix, mostly for visualization purposes. The matrix
* is equivalent the dynamic programming algorithm of the StrictAlgorithm that created this
* AlignmentList. However, only those entries are non-zero that are relevant for at least one
* Alignment in this list.
* The value of the output matrix is defined as the average over all Alignment|s toMatrix
* outputs.
*
* @return the dynamic programming matrix of the algorithm that created this
* AlignmentList with non-zero entries at positions that are relevant for at
* least one Alignment.
*/
public double[][] toMatrix() {
final int m = getLeft().size();
final int n = getRight().size();
final double[][] out = new double[m + 1][n + 1];
for (final Alignment path : this) {
int i = 0;
int j = 0;
double oldScore = 0;
for (final Operation op : path) {
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.getDistance();
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 Alignment p : this) {
sum += p.getDistance();
}
return sum / (double) this.size();
}
@Override
public List getLeft() {
if (this.isEmpty()) {
throw new UnsupportedOperationException("This PathList is empty.");
}
List left = null;
for (final Alignment 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;
}
@Override
public List getRight() {
if (this.isEmpty()) {
throw new UnsupportedOperationException("This PathList is empty.");
}
List right = null;
for (final Alignment 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;
}
@Override
public double[] computeGradient(@NonNull DerivableComparator comp) {
final int P = comp.getNumberOfParameters();
final double[] gradient = new double[P];
if (this.isEmpty()) {
return gradient;
}
/*
* now we let each path calculate its derivative and calculate the
* average.
*/
for (final Alignment path : this) {
final double[] pathGradient = path.computeGradient(comp);
for (int p = 0; p < P; p++) {
gradient[p] += pathGradient[p];
}
}
for (int p = 0; p < P; p++) {
gradient[p] /= (double) this.size();
}
return gradient;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy