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

de.citec.tcs.alignment.SoftPathModel 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.comparators.GapComparator;
import de.citec.tcs.alignment.comparators.OperationType;
import de.citec.tcs.alignment.comparators.SparseDerivableComparator;
import de.citec.tcs.alignment.comparators.SparseLocalDerivative;
import de.citec.tcs.alignment.parallel.MatrixEngine.MatrixCoordinate;
import de.citec.tcs.alignment.sequence.Sequence;
import de.citec.tcs.alignment.sequence.Value;
import java.util.Iterator;
import java.util.Stack;

/**
 * This is the soft pendant to the AlignmentPath. It does not really model a
 * path in this case but stored all softmin "probabilities" which operation
 * could have been taken in each alignment step.
 *
 * It is able to calculate the soft derivative.
 *
 * @author Benjamin Paassen - [email protected]
 */
public class SoftPathModel implements AlignmentDerivativeAlgorithm {

	private final AlignmentSpecification specification;
	private final Sequence left;
	private final Sequence right;
	private final double distance;
	private final double beta;
	private final SoftMatrixEntry[][] pathMatrix;

	public SoftPathModel(AlignmentSpecification specification,
			Sequence left, Sequence right,
			double distance, double beta,
			SoftMatrixEntry[][] pathMatrix) {
		this.specification = specification;
		this.left = left;
		this.right = right;
		this.distance = distance;
		this.beta = beta;
		this.pathMatrix = pathMatrix;	//check validity
		if (left.getNodeSpecification() != specification.getNodeSpecification()
				&& !left.getNodeSpecification().equals(specification.getNodeSpecification())) {
			throw new IllegalArgumentException(
					"The first input sequence has an unexpected node specification!");
		}
		if (left.getNodeSpecification() != right.getNodeSpecification()
				&& !left.getNodeSpecification().equals(right.getNodeSpecification())) {
			throw new IllegalArgumentException(
					"The node specifications of both input sequences to not match!");
		}
		if (left.getNodes().size() != pathMatrix.length - 1) {
			throw new IllegalArgumentException(
					"The given PathMatrix does not fit the given sequences!");
		}
		for (int i = 0; i < pathMatrix.length; i++) {
			if (right.getNodes().size() != pathMatrix[i].length - 1) {
				throw new IllegalArgumentException(
						"The given PathMatrix does not fit the given sequences!");
			}
		}

		//check validity of comparators.
		for (int k = 0; k < specification.size(); k++) {
			if (!(specification.getComparator(k) instanceof GapComparator)) {
				throw new UnsupportedOperationException("The comparator for keyword "
						+ specification.getKeyword(k) + " does not support gaps!");
			}
		}
	}

	/**
	 * {@inheritDoc }
	 */
	@Override
	public Sequence getLeft() {
		return left;
	}

	/**
	 * {@inheritDoc }
	 */
	@Override
	public Sequence getRight() {
		return right;
	}

	/**
	 * {@inheritDoc }
	 */
	@Override
	public double getDistance() {
		return distance;
	}

	/**
	 * Returns the AlignmentSpecification that was basis for this Alignment.
	 *
	 * @return the AlignmentSpecification that was basis for this Alignment.
	 */
	public AlignmentSpecification getSpecification() {
		return specification;
	}

	/**
	 * The parameter defining the "softness" of the alignment. For beta towards
	 * infinity this alignment becomes closer to the strict alignment. For beta
	 * = 0 all possible alignments are equally considered and softmin returns
	 * the average. Please note that a low beta value might lead to a very rough
	 * approximation and that for higher sequence lengths beta has to be higher,
	 * too.
	 *
	 * @return The parameter defining the "softness" of the alignment. For beta
	 * towards infinity this alignment becomes closer to the strict alignment.
	 * For beta = 0 all possible alignments are equally considered and softmin
	 * returns the average. Please note that a low beta value might lead to a
	 * very rough approximation and that for higher sequence lengths beta has to
	 * be higher, too.
	 */
	public double getBeta() {
		return beta;
	}

	/**
	 * This is the dynamic programming matrix calculated by a
	 * SoftAlignmentAlgorithm. It is not recommended to work directly with this
	 * matrix and detailed documentation is not within the scope of this API.
	 *
	 * @return the dynamic programming matrix calculated by a
	 * SoftAlignmentAlgorithm.
	 */
	public SoftMatrixEntry[][] getPathMatrix() {
		return pathMatrix;
	}

	/**
	 * {@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];
		final int k = specification.getKeywordIndex(keyword);
		if (specification.getComparator(k) != comp) {
			throw new UnsupportedOperationException(
					"The given comparator was not used for the given keyword!");
		}
		final double weight = specification.getWeighting()[k];
		if (weight == 0) {
			/*
			 * if the comparator has no weight, we return an empty array without
			 * doing any calculation.
			 */
			return derivatives;
		}

		//support sparsity
		boolean sparse = comp instanceof SparseDerivableComparator;
		final SparseDerivableComparator sparseComp;
		if (sparse) {
			sparseComp = (SparseDerivableComparator) comp;
		} else {
			sparseComp = null;
		}

		//pre-calculation caching
		final int m = left.getNodes().size();
		final int n = right.getNodes().size();

		final int origK = specification.getOriginalIndex(k);

		//start of calculation.
        /*
		 * We emulate a recursion by using a stack to make it more efficient, as
		 * we do not have to backtrace the whole matrix but only some paths
		 * within. We can disregard paths with zero probability.
		 */
		final SparseMatrix sparseMatrix
				= new SparseMatrix();
		final Stack calcStack = new Stack();
		//we start at the end and trace back.
		MatrixCoordinate current = new MatrixCoordinate(m, n);
		//the (0,0) cell is initialized with a zero vector.
		sparseMatrix.set(0, 0, new double[P]);
		calcStack.push(current);
		while (!calcStack.empty()) {
			current = calcStack.pop();
			final int i = current.i;
			final int j = current.j;

			if (sparseMatrix.get(i, j) != null) {
				continue;
			}
			//if we are in the first column, we can only delete.
			double[] delOld = null;
			double[] localDeriv = new double[P];
			if (j == 0) {
				//if we have to calculate this term, look if we have the necessary preconditions.
				delOld = sparseMatrix.get(i - 1, j);
				if (delOld == null) {
					//if we don't have that yet, calculate it first.
					calcStack.push(new MatrixCoordinate(i, j));
					calcStack.push(new MatrixCoordinate(i - 1, j));
					continue;
				}
				//if we have it, calculate result.
				fillDeletionInformation(pathMatrix[i][j], pathMatrix[i - 1][j].softmin, i);
				//calculate local derivative
				calculateLocalDerivative(comp, sparseComp, sparse,
						(X) left.getNodes().get(i - 1).getValue(origK), null,
						OperationType.DELETION,
						localDeriv, P);
				//embed it in the softmin derivative term.
				for (int p = 0; p < P; p++) {
					localDeriv[p] = (delOld[p] + weight * localDeriv[p])
							* pathMatrix[i][j].delSoftDerivative;
				}
				//store it in the matrix.
				sparseMatrix.set(i, j, localDeriv);
				continue;
			}

			//if we are in the first row, we can only insert.
			double[] insOld = null;
			if (i == 0) {
				//if we have to calculate this term, look if we have the necessary preconditions.
				insOld = sparseMatrix.get(i, j - 1);
				if (insOld == null) {
					//if we don't have that yet, calculate it first.
					calcStack.push(new MatrixCoordinate(i, j));
					calcStack.push(new MatrixCoordinate(i, j - 1));
					continue;
				}
				//if we have it, calculate result.
				fillInsertionInformation(pathMatrix[i][j],
						pathMatrix[i][j - 1].softmin, j);
				//calculate local derivative
				calculateLocalDerivative(comp, sparseComp, sparse,
						null, (X) right.getNodes().get(j - 1).getValue(origK),
						OperationType.INSERTION,
						localDeriv, P);
				//embed it in the softmin derivative term.
				for (int p = 0; p < P; p++) {
					localDeriv[p] = (insOld[p] + weight * localDeriv[p])
							* pathMatrix[i][j].insSoftDerivative;
				}
				//store it in the matrix
				sparseMatrix.set(i, j, localDeriv);
				continue;
			}

			//if we are inside the matrix, the calculation becomes more complex.
			boolean pushedBack = false;
			double[] repOld = null;

			//handle deletion first, similar to above.
			if (pathMatrix[i][j].delProb > 0) {
				//if we are above threshold, look for preconditions.
				delOld = sparseMatrix.get(i - 1, j);
				if (delOld == null) {
					//if we don't have that yet, calculate it first.
					calcStack.push(new MatrixCoordinate(i, j));
					pushedBack = true;
					calcStack.push(new MatrixCoordinate(i - 1, j));
				}
			}
			//handle insertion
			if (pathMatrix[i][j].insProb > 0) {
				//if we are above threshold, look for preconditions.
				insOld = sparseMatrix.get(i, j - 1);
				if (insOld == null) {
					//if we don't have that yet, calculate it first.
					if (!pushedBack) {
						calcStack.push(new MatrixCoordinate(i, j));
						pushedBack = true;
					}
					calcStack.push(new MatrixCoordinate(i, j - 1));
				}
			}
			//handle replacement
			if (pathMatrix[i][j].repProb > 0) {
				//if we are above threshold, look for preconditions.
				repOld = sparseMatrix.get(i - 1, j - 1);
				if (repOld == null) {
					//if we don't have that yet, calculate it first. 
					if (!pushedBack) {
						calcStack.push(new MatrixCoordinate(i, j));
						pushedBack = true;
					}
					calcStack.push(new MatrixCoordinate(i - 1, j - 1));
				}
			}
			if (!pushedBack) {
				//if we have all preconditions, calculate the result.
				final X leftVal;
				if (i > 0) {
					leftVal = (X) left.getNodes().get(i - 1).getValue(origK);
				} else {
					leftVal = null;
				}
				final X rightVal;
				if (j > 0) {
					rightVal = (X) right.getNodes().get(j - 1).getValue(origK);
				} else {
					rightVal = null;
				}
				final double[] del = new double[P];
				final double[] ins = new double[P];
				final double[] rep = new double[P];
				if (delOld != null) {
					fillDeletionInformation(pathMatrix[i][j],
							pathMatrix[i - 1][j].softmin, i);
					//calculate local derivative
					calculateLocalDerivative(comp, sparseComp, sparse,
							leftVal, rightVal, OperationType.DELETION,
							localDeriv, P);
					//embed it in the softmin derivative term.
					for (int p = 0; p < P; p++) {
						del[p] = (delOld[p] + weight * localDeriv[p])
								* pathMatrix[i][j].delSoftDerivative;
					}
				}
				if (insOld != null) {
					fillInsertionInformation(pathMatrix[i][j],
							pathMatrix[i][j - 1].softmin, j);
					//calculate local derivative
					calculateLocalDerivative(comp, sparseComp, sparse,
							leftVal, rightVal, OperationType.INSERTION,
							localDeriv, P);
					//embed it in the softmin derivative term.
					for (int p = 0; p < P; p++) {
						ins[p] = (insOld[p] + localDeriv[p] * weight)
								* pathMatrix[i][j].insSoftDerivative;
					}
				}
				if (repOld != null) {
					fillReplacementInformation(pathMatrix[i][j],
							pathMatrix[i - 1][j - 1].softmin, i, j);
					//calculate local derivative
					calculateLocalDerivative(comp, sparseComp, sparse,
							leftVal, rightVal, OperationType.REPLACEMENT,
							localDeriv, P);
					//embed it in the softmin derivative term.
					for (int p = 0; p < P; p++) {
						rep[p] = (repOld[p] + localDeriv[p] * weight)
								* pathMatrix[i][j].repSoftDerivative;
					}
				}
				final double[] result = new double[P];
				for (int p = 0; p < P; p++) {
					result[p] = del[p] + ins[p] + rep[p];
				}
				sparseMatrix.set(i, j, result);
			}
		}
		return sparseMatrix.get(m, n);
	}

	private static  void calculateLocalDerivative(
			DerivableComparator comp,
			SparseDerivableComparator sparseComp, boolean sparse,
			X leftVal, X rightVal, OperationType type,
			double[] localDeriv, int P) {
		//if we do not have a sparse comparator, we iterate over all parameters.
		if (!sparse) {
			for (int p = 0; p < P; p++) {
				localDeriv[p] = comp.calculateLocalDerivative(p, leftVal, rightVal, type);
			}
		} else {
			//clean local derivative.
			for (int p = 0; p < P; p++) {
				localDeriv[p] = 0;
			}
			//otherwise use sparsity
			final Iterator it = sparseComp.
					calculateSparseLocalDerivative(leftVal, rightVal,
							type).iterator();
			while (it.hasNext()) {
				final SparseLocalDerivative.SparseDeriativeEntry sparseLocalDerivative = it.next();
				localDeriv[sparseLocalDerivative.getParameterIndex()]
						= sparseLocalDerivative.getDerivative();
			}
		}
	}

	/**
	 * {@inheritDoc }
	 */
	public double[] calculateWeightDerivative() {
		final int m = left.getNodes().size();
		final int n = right.getNodes().size();

		//pre-calculation caching
		final int K = specification.getWeighting().length;
		//start of calculation.
        /*
		 * We emulate a recursion by using a stack to make it more efficient, as
		 * we do not have to backtrace the whole matrix but only some paths
		 * within. We can disregard paths with zero probability.
		 */
		final SparseMatrix sparseMatrix
				= new SparseMatrix();
		final Stack calcStack = new Stack();
		//we start at the end and trace back.
		MatrixCoordinate current = new MatrixCoordinate(m, n);
		calcStack.push(current);
		while (!calcStack.empty()) {
			current = calcStack.pop();
			//get dependent cells.
			final int i = current.i;
			final int j = current.j;

			if (sparseMatrix.get(i, j) != null) {
				continue;
			}

			if (i == 0 && j == 0) {
				//if we are at the start, store 0.
				sparseMatrix.set(i, j, new WeightDerivativeEntry(0, 0, new double[K]));
				continue;
			}
			//if we are in the first column, we can only delete.
			WeightDerivativeEntry delOld = null;
			if (j == 0) {
				//if we have to calculate this term, look if we have the necessary preconditions.
				delOld = sparseMatrix.get(i - 1, j);
				if (delOld == null) {
					//if we don't have that yet, calculate it first.
					calcStack.push(new MatrixCoordinate(i, j));
					calcStack.push(new MatrixCoordinate(i - 1, j));
					continue;
				}
				//if we have it, calculate result.
				fillDeletionInformation(pathMatrix[i][j],
						pathMatrix[i - 1][j].softmin, i);
				final WeightDerivativeEntry newEntry = new WeightDerivativeEntry(
						i, j, new double[K]);
				for (int k = 0; k < K; k++) {
					newEntry.weightDerivatives[k] = (delOld.weightDerivatives[k]
							+ pathMatrix[i][j].delCosts[k])
							* pathMatrix[i][j].delSoftDerivative;
				}
				sparseMatrix.set(i, j, newEntry);
				continue;
			}

			//if we are in the first row, we can only insert.
			WeightDerivativeEntry insOld = null;
			if (i == 0) {
				//if we have to calculate this term, look if we have the necessary preconditions.
				insOld = sparseMatrix.get(i, j - 1);
				if (insOld == null) {
					//if we don't have that yet, calculate it first.
					calcStack.push(new MatrixCoordinate(i, j));
					calcStack.push(new MatrixCoordinate(i, j - 1));
					continue;
				}
				//if we have it, calculate result.
				fillInsertionInformation(pathMatrix[i][j],
						pathMatrix[i][j - 1].softmin, j);
				final WeightDerivativeEntry newEntry = new WeightDerivativeEntry(
						i, j, new double[K]);
				for (int k = 0; k < K; k++) {
					newEntry.weightDerivatives[k] = (insOld.weightDerivatives[k]
							+ pathMatrix[i][j].insCosts[k])
							* pathMatrix[i][j].insSoftDerivative;
				}
				sparseMatrix.set(i, j, newEntry);
				continue;
			}

			//if we are inside the matrix, the calculation becomes more complex.
			boolean pushedBack = false;
			WeightDerivativeEntry repOld = null;

			//handle deletion first, similar to above.
			if (pathMatrix[i][j].delProb > 0) {
				//if we are above threshold, look for preconditions.
				delOld = sparseMatrix.get(i - 1, j);
				if (delOld == null) {
					//if we don't have that yet, calculate it first.
					calcStack.push(new MatrixCoordinate(i, j));
					pushedBack = true;
					calcStack.push(new MatrixCoordinate(i - 1, j));
				}
			}
			//handle insertion
			if (pathMatrix[i][j].insProb > 0) {
				//if we are above threshold, look for preconditions.
				insOld = sparseMatrix.get(i, j - 1);
				if (insOld == null) {
					//if we don't have that yet, calculate it first.
					if (!pushedBack) {
						calcStack.push(new MatrixCoordinate(i, j));
						pushedBack = true;
					}
					calcStack.push(new MatrixCoordinate(i, j - 1));
				}
			}
			//handle replacement
			if (pathMatrix[i][j].repProb > 0) {
				//if we are above threshold, look for preconditions.
				repOld = sparseMatrix.get(i - 1, j - 1);
				if (repOld == null) {
					//if we don't have that yet, calculate it first. 
					if (!pushedBack) {
						calcStack.push(new MatrixCoordinate(i, j));
						pushedBack = true;
					}
					calcStack.push(new MatrixCoordinate(i - 1, j - 1));
				}
			}
			if (!pushedBack) {
				//if we have all preconditions, calculate the result.
				final double[] delVals = new double[K];
				final double[] insVals = new double[K];
				final double[] repVals = new double[K];
				if (delOld != null) {
					fillDeletionInformation(pathMatrix[i][j],
							pathMatrix[i - 1][j].softmin, i);
					for (int k = 0; k < K; k++) {
						delVals[k] = (delOld.weightDerivatives[k]
								+ pathMatrix[i][j].delCosts[k])
								* pathMatrix[i][j].delSoftDerivative;
					}
				}
				if (insOld != null) {
					fillInsertionInformation(pathMatrix[i][j],
							pathMatrix[i][j - 1].softmin, j);
					for (int k = 0; k < K; k++) {
						insVals[k] = (insOld.weightDerivatives[k]
								+ pathMatrix[i][j].insCosts[k])
								* pathMatrix[i][j].insSoftDerivative;
					}
				}
				if (repOld != null) {
					fillReplacementInformation(pathMatrix[i][j],
							pathMatrix[i - 1][j - 1].softmin, i, j);
					for (int k = 0; k < K; k++) {
						repVals[k] = (repOld.weightDerivatives[k]
								+ pathMatrix[i][j].repCosts[k])
								* pathMatrix[i][j].repSoftDerivative;
					}
				}
				final double[] weightDerivs = new double[K];
				for (int k = 0; k < K; k++) {
					weightDerivs[k] = delVals[k] + insVals[k] + repVals[k];
				}
				final WeightDerivativeEntry newEntry
						= new WeightDerivativeEntry(i, j, weightDerivs);
				sparseMatrix.set(i, j, newEntry);
			}
		}
		return sparseMatrix.get(m, n).weightDerivatives;
	}

	/**
	 * Fills the missing information for the given SoftMatrixEntry. We calculate
	 * this here on demand to prevent unnecessary calculations.
	 *
	 * Please note that this method is hand-tailored for the combination of
	 * SoftAlignmentFullAlgorithm and SoftPathModel. It is not recommended to
	 * use this for other purposes.
	 *
	 * @param entry
	 * @param i
	 */
	private void fillDeletionInformation(SoftMatrixEntry entry,
			double delOldScore, int i) {
		if (entry.delCosts == null) {
			entry.delCosts = specification.calculateDeletionCosts(
					left.getNodes().get(i - 1));
			entry.delSoftDerivative = entry.delProb * (1 - beta * (delOldScore
					+ entry.delLocal - entry.softmin));
		}
	}

	/**
	 * Fills the missing information for the given SoftMatrixEntry. We calculate
	 * this here on demand to prevent unnecessary calculations.
	 *
	 * Please note that this method is hand-tailored for the combination of
	 * SoftAlignmentFullAlgorithm and SoftPathModel. It is not recommended to
	 * use this for other purposes.
	 *
	 * @param entry
	 * @param j
	 */
	private void fillInsertionInformation(SoftMatrixEntry entry,
			double insOldScore, int j) {
		if (entry.insCosts == null) {
			entry.insCosts = specification.calculateInsertionCosts(
					right.getNodes().get(j - 1));
			entry.insSoftDerivative = entry.insProb * (1 - beta * (insOldScore
					+ entry.insLocal - entry.softmin));
		}
	}

	/**
	 * Fills the missing information for the given SoftMatrixEntry. We calculate
	 * this here on demand to prevent unnecessary calculations.
	 *
	 * Please note that this method is hand-tailored for the combination of
	 * SoftAlignmentFullAlgorithm and SoftPathModel. It is not recommended to
	 * use this for other purposes.
	 *
	 * @param entry
	 * @param i
	 * @param j
	 */
	private void fillReplacementInformation(SoftMatrixEntry entry,
			double repOldScore, int i, int j) {
		if (entry.repCosts == null) {
			entry.repCosts = specification.calculateReplacementCosts(
					left.getNodes().get(i - 1),
					right.getNodes().get(j - 1));
			entry.repSoftDerivative = entry.repProb * (1 - beta * (repOldScore
					+ entry.repLocal - entry.softmin));
		}
	}

	public static class SoftMatrixEntry implements AlignmentMatrixEntry {

		private double[] delCosts;
		private double delLocal;
		private double delProb;
		private double delSoftDerivative;
		private double[] insCosts;
		private double insLocal;
		private double insProb;
		private double insSoftDerivative;
		private double[] repCosts;
		private double repLocal;
		private double repProb;
		private double repSoftDerivative;
		private double softmin;

		public SoftMatrixEntry() {
		}

		public double[] getDelCosts() {
			return delCosts;
		}

		public void setDelCosts(double[] delCosts) {
			this.delCosts = delCosts;
		}

		public double getDelLocal() {
			return delLocal;
		}

		public void setDelLocal(double delLocal) {
			this.delLocal = delLocal;
		}

		public double getDelProb() {
			return delProb;
		}

		public void setDelProb(double delProb) {
			this.delProb = delProb;
		}

		public double getDelSoftDerivative() {
			return delSoftDerivative;
		}

		public void setDelSoftDerivative(double delSoftDerivative) {
			this.delSoftDerivative = delSoftDerivative;
		}

		public double[] getInsCosts() {
			return insCosts;
		}

		public void setInsCosts(double[] insCosts) {
			this.insCosts = insCosts;
		}

		public double getInsLocal() {
			return insLocal;
		}

		public void setInsLocal(double insLocal) {
			this.insLocal = insLocal;
		}

		public double getInsProb() {
			return insProb;
		}

		public void setInsProb(double insProb) {
			this.insProb = insProb;
		}

		public double getInsSoftDerivative() {
			return insSoftDerivative;
		}

		public void setInsSoftDerivative(double insSoftDerivative) {
			this.insSoftDerivative = insSoftDerivative;
		}

		public double[] getRepCosts() {
			return repCosts;
		}

		public void setRepCosts(double[] repCosts) {
			this.repCosts = repCosts;
		}

		public double getRepLocal() {
			return repLocal;
		}

		public void setRepLocal(double repLocal) {
			this.repLocal = repLocal;
		}

		public double getRepProb() {
			return repProb;
		}

		public void setRepProb(double repProb) {
			this.repProb = repProb;
		}

		public double getRepSoftDerivative() {
			return repSoftDerivative;
		}

		public void setRepSoftDerivative(double repSoftDerivative) {
			this.repSoftDerivative = repSoftDerivative;
		}

		public double getSoftmin() {
			return softmin;
		}

		public void setSoftmin(double softmin) {
			this.softmin = softmin;
		}
	}

	private static class WeightDerivativeEntry {

		public int i;
		public int j;
		public double[] weightDerivatives;

		public WeightDerivativeEntry() {
		}

		public WeightDerivativeEntry(int i, int j, double[] weightDerivatives) {
			this.i = i;
			this.j = j;
			this.weightDerivatives = weightDerivatives;
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy