/* * File: MatrixVectorMultiplierDiagonalPreconditioner.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.math.matrix.Matrix; import gov.sandia.cognition.math.matrix.Vector; import gov.sandia.cognition.math.matrix.custom.DiagonalMatrix; /** * Implements a diagonal preconditioner for a matrix-vector multiplier. * * @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 MatrixVectorMultiplierDiagonalPreconditioner extends MatrixVectorMultiplierWithPreconditioner { DiagonalMatrix Minv; private MatrixVectorMultiplierDiagonalPreconditioner() { super(null); throw new UnsupportedOperationException("Can't call the null " + "constructor!"); } /** * Creates a new {@link MatrixVectorMultiplierDiagonalPreconditioner} for * the given matrix. * * @param m * The matrix. */ public MatrixVectorMultiplierDiagonalPreconditioner(Matrix m) { super(m); if (!m.isSquare()) { throw new IllegalArgumentException("This preconditioner only works " + "on square matrices"); } int n = m.getNumRows(); Minv = new DiagonalMatrix(n); for (int i = 0; i < n; ++i) { double ij = m.getElement(i, i); if (ij == 0) { throw new IllegalArgumentException("Diagonal preconditioner " + "only serves for matrices with non-zero diagonal elements"); } Minv.setElement(i, i, 1.0 / ij); } } @Override Vector precondition(Vector v) { return Minv.times(v); } }