/* * File: MatrixVectorMultiplier.java * Authors: Jeremy D. Wendt * Company: Sandia National Laboratories * Project: Cognitive Foundry * * Copyright 2016, Sandia Corporation. * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive * license for use of this work by or on behalf of the U.S. Government. * Export of this program may require a license from the United States * Government. See CopyrightHistory.txt for complete details. */ package gov.sandia.cognition.learning.algorithm.minimization.matrix; import gov.sandia.cognition.annotation.PublicationReference; import gov.sandia.cognition.annotation.PublicationType; import gov.sandia.cognition.evaluator.Evaluator; import gov.sandia.cognition.math.matrix.Matrix; import gov.sandia.cognition.math.matrix.Vector; /** * The necessary multiplication wrapper class to match the FunctionMinimizer * interface. Takes a matrix. Multiplies the input vector by the matrix, * returning the result. * * @author Jeremy D. Wendt * @since 4.0.0 */ @PublicationReference(author = "Jonathan Richard Shewchuk", title = "An Introduction to the Conjugate Gradient Method Without the Agonizing Pain", type = PublicationType.WebPage, year = 1994, url = "http://www.cs.cmu.edu/~quake-papers/painless-conjugate-gradient.pdf‎") public class MatrixVectorMultiplier implements Evaluator<Vector, Vector> { /** * The matrix to multiply with. This is a deep-copy of the input to prevent * any weirdness from altering the matrix after the constructor is called. */ protected Matrix m; /** * Never call this. * * @throws UnsupportedOperationException Because it's not supported. */ private MatrixVectorMultiplier() { throw new UnsupportedOperationException("Can't call the null " + "constructor!"); } /** * Clones the input matrix to prevent any later edits to the input from * changing the results of iterative multiplications. * * @param m The matrix to multiply with */ public MatrixVectorMultiplier(Matrix m) { this.m = m.clone(); } /** * Returns m times input. * * @param input The vector to multiply by m. * @return m times input. */ @Override public Vector evaluate(Vector input) { return m.times(input); } /** * Ensures that the input x and rhs are of the correct dimensions to work * with m. * * @param xi The current estimate of the unknown final left-hand-side vector * x. * @param rhs The right-hand-side vector (b). * @return True if the dimensions match, else false. */ boolean canEvaluateAgainst(Vector xi, Vector rhs) { if ((xi.getDimensionality() != m.getNumColumns()) || (rhs.getDimensionality() != m.getNumRows())) { return false; } return true; } @Override public boolean equals(Object o) { if (!(o instanceof MatrixVectorMultiplier)) { return false; } MatrixVectorMultiplier other = (MatrixVectorMultiplier) o; if ((m == null) && (other.m != null)) { return false; } else if ((m != null) && !m.equals(other.m)) { return false; } return true; } @Override public int hashCode() { int hash = 1; return hash * 17 + ((m == null) ? 0 : m.hashCode()); } }