All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.citec.tcs.alignment.AlignmentList Maven / Gradle / Ivy

Go to download

This module defines the interface for AlignmentAlgorithms as well as some helper classes. An AlignmentAlgorithm computes an Alignment of two given input sequences, given a Comparator that works in these sequences. More details on the AlignmentAlgorithm can be found in the respective interface. More information on Comparators can be found in the comparators module. The resulting 'Alignment' may be just a real-valued dissimilarity between the input sequence or may incorporate additional information, such as a full Alignment, a PathList, a PathMap or a CooptimalModel. If those results support the calculation of a Gradient, they implement the DerivableAlignmentDistance interface. In more detail, the Alignment class represents the result of a backtracing scheme, listing all Operations that have been applied in one co-optimal Alignment. A classic AlignmentAlgorithm does not result in a differentiable dissimilarity, because the minimum function is not differentiable. Therefore, this package also contains utility functions for a soft approximation of the minimum function, namely Softmin. For faster (parallel) computation of many different alignments or gradients we also provide the ParallelProcessingEngine, the SquareParallelProcessingEngine and the ParallelGradientEngine.

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.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