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

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