de.citec.tcs.alignment.PathMap 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;
import java.util.List;
import java.util.TreeMap;
/**
* This is a TreeMap-based datastructure implementing a mapping from scores to
* AlignmentPaths. It is also able to calculate the derivative of all given
* paths weighted by their score.
*
* The weighting that is used can be chosen by the user.
*
* @author Benjamin Paassen - [email protected]
*/
public class PathMap implements AlignmentDerivativeAlgorithm {
private final TreeMap> actualMap
= new TreeMap>();
private int size = 0;
private ScoreBasedWeighting weighting = ScoreBasedWeighting.SOFTMIN;
public PathMap() {
super();
}
/**
* Returns the weighting that is used during derivative calculation.
*
* @return the weighting that is used during derivative calculation.
*/
public ScoreBasedWeighting getWeighting() {
return weighting;
}
/**
* Sets the weighting that is used during derivative calculation.
*
* @param weighting the weighting that is used during derivative
* calculation.
*/
public void setWeighting(ScoreBasedWeighting weighting) {
this.weighting = weighting;
}
/**
* Adds a new AlignmentPath to this map.
*
* @param path a new AlignmentPath.
*/
public void put(AlignmentPath path) {
size++;
ArrayList list = actualMap.get(path.getDistance());
if (list == null) {
list = new ArrayList();
actualMap.put(path.getDistance(), list);
}
list.add(path);
}
/**
* Returns the number of paths stored in this map.
*
* @return the number of paths stored in this map.
*/
public int getSize() {
return size;
}
/**
* Returns all paths stored in this map in order of their score (from
* good/low to bad/high).
*
* @return all paths stored in this map in order of their score (from
* good/low to bad/high).
*/
public List getAllPaths() {
final ArrayList list = new ArrayList();
for (final ArrayList paths : actualMap.values()) {
list.addAll(paths);
}
return list;
}
/**
* Returns all paths with the given score. If the score is not found within
* this map an empty list is returned.
*
* @param score a score.
*
* @return all paths with the given score.
*/
public List getPaths(double score) {
final ArrayList list = actualMap.get(score);
if (list == null) {
return new ArrayList();
}
return list;
}
/**
* Get all scores for which paths exist within this map.
*
* @return all scores for which paths exist within this map.
*/
public List getScores() {
final ArrayList returnList = new ArrayList(actualMap.keySet());
return returnList;
}
/**
* Removes all AlignmentPaths with the given score from the map and returns
* them. If the score is not found within this map an empty list is
* returned.
*
* @param score a score.
*
* @return all AlignmentPaths with the given score from the map and returns
* them.
*/
public List removeValues(double score) {
final ArrayList list = actualMap.remove(score);
if (list == null) {
return new ArrayList();
}
size -= list.size();
return list;
}
/**
* Returns the lowest/best score stored in this map.
*
* @return the lowest/best score stored in this map.
*/
public double lowestScore() {
return actualMap.firstKey();
}
/**
* Returns the highest/worst score stored in this map.
*
* @return the highest/worst score stored in this map.
*/
public double highestScore() {
return actualMap.lastKey();
}
/**
* Returns the average score according to the given weighting scheme.
*
* @return the average score according to the given weighting scheme.
*/
public double averageScore() {
if (actualMap.isEmpty()) {
throw new UnsupportedOperationException("This PathMap is empty.");
}
//first calculate the weights for all paths.
final List allPaths = getAllPaths();
final double[] scores = new double[allPaths.size()];
int l = 0;
for (AlignmentPath path : allPaths) {
scores[l] = path.getDistance();
l++;
}
final double[] weights = weighting.calculateWeighting(scores);
double avgScore = 0;
for (l = 0; l < allPaths.size(); l++) {
avgScore += scores[l] * weights[l];
}
return avgScore;
}
/**
* {@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 (getSize() == 0) {
return derivatives;
}
//first calculate the weights for all paths.
final List allPaths = getAllPaths();
final double[] scores = new double[allPaths.size()];
int l = 0;
for (AlignmentPath path : allPaths) {
scores[l] = path.getDistance();
l++;
}
final double[] weights = weighting.calculateWeighting(scores);
/*
* now we let each path calculate its derivative and weight it according
* to the weighting specified.
*/
l = 0;
for (final AlignmentPath path : allPaths) {
final double[] pathDerivatives = path.calculateRawParameterDerivative(
comp, keyword);
for (int p = 0; p < P; p++) {
derivatives[p] += weights[l] * pathDerivatives[p];
}
l++;
}
return derivatives;
}
/**
* {@inheritDoc }
*/
public double[] calculateWeightDerivative() {
if (getSize() == 0) {
throw new UnsupportedOperationException(
"Weight derivative without any paths is not defined.");
}
//first calculate the weights for all paths.
final List allPaths = getAllPaths();
final double[] scores = new double[allPaths.size()];
int l = 0;
for (AlignmentPath path : allPaths) {
scores[l] = path.getDistance();
l++;
}
final double[] weights = weighting.calculateWeighting(scores);
/*
* now we let each path calculate its weight derivative and take the
* weighted minimum as discussed.
*/
final int K = actualMap.firstEntry().getValue().get(0).
getSpecificaton().size();
final double[] derivative = new double[K];
l = 0;
for (final AlignmentPath path : allPaths) {
final double[] pathDerivative = path.calculateWeightDerivative();
for (int k = 0; k < K; k++) {
derivative[k] += weights[l] * pathDerivative[k];
}
l++;
}
return derivative;
}
/**
* This transforms the PathMap 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 weighted average over
* all path toMatrix outputs.
*
* @return the dynamic programming matrix of the algorithm that created this
* PathMap with non-zero entries at positions that are relevant for at least
* one path.
*/
public double[][] toMatrix() {
//first calculate the weights for all paths.
final List allPaths = getAllPaths();
final double[] scores = new double[allPaths.size()];
int l = 0;
for (final AlignmentPath path : allPaths) {
scores[l] = path.getDistance();
l++;
}
final double[] weights = weighting.calculateWeighting(scores);
final int m = allPaths.get(0).getLeft().getNodes().size();
final int n = allPaths.get(0).getRight().getNodes().size();
final double[][] out = new double[m + 1][n + 1];
l = 0;
for (final AlignmentPath path : allPaths) {
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] += weights[l] * (oldScore + op.getWeightedLocalCost());
oldScore = out[i][j];
}
l++;
}
return out;
}
/**
* Returns the average distance of all stored paths.
*
* @return the average distance of all stored paths.
*/
@Override
public double getDistance() {
return averageScore();
}
/**
* {@inheritDoc }
*/
@Override
public Sequence getLeft() {
if (actualMap.isEmpty()) {
throw new UnsupportedOperationException("This PathMap is empty.");
}
Sequence left = null;
for (final AlignmentPath p : getAllPaths()) {
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 (actualMap.isEmpty()) {
throw new UnsupportedOperationException("This PathMap is empty.");
}
Sequence right = null;
for (final AlignmentPath p : getAllPaths()) {
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