mtj-0.9.14/ 0000755 0000000 0000000 00000000000 11762646445 011114 5 ustar root root mtj-0.9.14/nbproject/ 0000755 0000000 0000000 00000000000 11467303576 013077 5 ustar root root mtj-0.9.14/nbproject/project.xml 0000644 0000000 0000000 00000001352 11324170636 015257 0 ustar root root
A
* that lie within the allocated band are copied over, the rest
* is ignored (including main diagonal entries)
* @param kd
* Number of bands below the main diagonal (subdiagonals)
*/
public UnitLowerTriangBandMatrix(Matrix A, int kd) {
this(A, kd, true);
}
/**
* Constructor for UnitLowerTriangBandMatrix
*
* @param A
* Matrix to copy contents from. Only the parts of A
* that lie within the allocated band are copied over, the rest
* is ignored (including main diagonal entries)
* @param kd
* Number of bands below the main diagonal (subdiagonals)
* @param deep
* True for a deep copy. For shallow copies, A
* must be a banded matrix
*/
public UnitLowerTriangBandMatrix(Matrix A, int kd, boolean deep) {
super(A, kd, deep, Diag.Unit);
}
@Override
public void add(int row, int column, double value) {
if (row == column)
throw new IllegalArgumentException("row == column");
super.add(row, column, value);
}
@Override
public double get(int row, int column) {
if (row == column)
return 1;
return super.get(row, column);
}
@Override
public void set(int row, int column, double value) {
if (row == column)
throw new IllegalArgumentException("row == column");
super.set(row, column, value);
}
@Override
public UnitLowerTriangBandMatrix copy() {
return new UnitLowerTriangBandMatrix(this, kl);
}
@Override
public Matrix zero() {
throw new UnsupportedOperationException();
}
@Override
void copy(Matrix A) {
for (MatrixEntry e : A)
if (inBand(e.row(), e.column()) && e.row() != e.column())
set(e.row(), e.column(), e.get());
}
}
mtj-0.9.14/src/no/uib/cipr/matrix/UpperSymmPackMatrix.java 0000644 0000000 0000000 00000006105 11027512662 022114 0 ustar root root /*
* Copyright (C) 2003-2006 Bjørn-Ove Heimsund
*
* This file is part of MTJ.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* This library 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package no.uib.cipr.matrix;
/**
* Upper symmetric packed matrix. Same storage as
* {@link no.uib.cipr.matrix.UpperTriangPackMatrix UpperTriangPackMatrix}, but
* the lower triangular part is known by symmetry.
*/
public class UpperSymmPackMatrix extends AbstractSymmPackMatrix {
/**
* Constructor for UpperSymmPackMatrix
*
* @param n
* Size of the matrix. Since the matrix must be square, this
* equals both the number of rows and columns
*/
public UpperSymmPackMatrix(int n) {
super(n, UpLo.Upper);
}
/**
* Constructor for UpperSymmPackMatrix
*
* @param A
* Matrix to copy contents from. Only the entries of the relevant
* part are copied
*/
public UpperSymmPackMatrix(Matrix A) {
this(A, true);
}
/**
* Constructor for UpperSymmPackMatrix
*
* @param A
* Matrix to copy contents from. Only the entries of the relevant
* part are copied
* @param deep
* True if the copy is deep, else false (giving a shallow copy).
* For shallow copies, A
must be a packed matrix
*/
public UpperSymmPackMatrix(Matrix A, boolean deep) {
super(A, deep, UpLo.Upper);
}
@Override
public void add(int row, int column, double value) {
if (row <= column)
data[getIndex(row, column)] += value;
}
@Override
public void set(int row, int column, double value) {
if (row <= column)
data[getIndex(row, column)] = value;
}
@Override
public double get(int row, int column) {
if (row <= column)
return data[getIndex(row, column)];
return data[getIndex(column, row)];
}
/**
* Checks the row and column indices, and returns the linear data index
*/
int getIndex(int row, int column) {
check(row, column);
return row + (column + 1) * column / 2;
}
@Override
void copy(Matrix A) {
for (MatrixEntry e : A)
if (e.row() <= e.column())
set(e.row(), e.column(), e.get());
}
@Override
public UpperSymmPackMatrix copy() {
return new UpperSymmPackMatrix(this);
}
}
mtj-0.9.14/src/no/uib/cipr/matrix/BandMatrix.java 0000644 0000000 0000000 00000016017 11027512662 020223 0 ustar root root /*
* Copyright (C) 2003-2006 Bjørn-Ove Heimsund
*
* This file is part of MTJ.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* This library 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package no.uib.cipr.matrix;
import java.util.Arrays;
import org.netlib.blas.BLAS;
import org.netlib.lapack.LAPACK;
import org.netlib.util.intW;
/**
* Banded matrix. The banded matrix is a useful sparse structure for many kinds
* of direct computations, however it should only be used if the band is
* sufficiently narrow as wide bands actually wastes both memory and compute
* time. The matrix
*
*
a11 | *a12 | ** | * | * |
a21 | *a22 | *a23 | ** | * |
a31 | *a32 | *a33 | *a34 | ** |
* | a42 | *a43 | *a44 | *a45 | *
* | * | a53 | *a54 | *a55 | *
* has two lower diagonals and one upper diagonal. It will be stored in the * array *
**
* | a11 | *a21 | *a31 | *a21 | *a22 | *a32 | *a42 | *a23 | *a33 | *a43 | *a53 | *a34 | *a44 | *a54 | ** | a45 | *a55 | ** | * |
* Empty cells are allocated, but never referenced. *
*/ public class BandMatrix extends AbstractBandMatrix { /** * Constructor for BandMatrix * * @param n * Size of the matrix. Since the matrix must be square, this * equals both the number of rows and columns * @param kl * Number of bands above the main diagonal (superdiagonals) * @param ku * Number of bands below the main diagonal (subdiagonals) */ public BandMatrix(int n, int kl, int ku) { super(n, kl, ku); } /** * Constructor for BandMatrix * * @param A * Matrix to copy contents from. Only the parts ofA
* that lie within the allocated band are copied over, the rest
* is ignored
* @param kl
* Number of bands above the main diagonal (superdiagonals)
* @param ku
* Number of bands below the main diagonal (subdiagonals)
*/
public BandMatrix(Matrix A, int kl, int ku) {
super(A, kl, ku);
}
/**
* Constructor for BandMatrix
*
* @param A
* Matrix to copy contents from. Only the parts of A
* that lie within the allocated band are copied over, the rest
* is ignored
* @param kl
* Number of bands above the main diagonal (superdiagonals)
* @param ku
* Number of bands below the main diagonal (subdiagonals)
* @param deep
* True for a deep copy. For shallow copies, A
* must be a banded matrix
*/
public BandMatrix(Matrix A, int kl, int ku, boolean deep) {
super(A, kl, ku, deep);
}
@Override
public BandMatrix copy() {
return new BandMatrix(this, kl, ku);
}
@Override
public Matrix zero() {
Arrays.fill(data, 0);
return this;
}
@Override
public Vector multAdd(double alpha, Vector x, Vector y) {
if (!(x instanceof DenseVector) || !(y instanceof DenseVector))
return super.multAdd(alpha, x, y);
checkMultAdd(x, y);
double[] xd = ((DenseVector) x).getData(), yd = ((DenseVector) y)
.getData();
BLAS.getInstance().dgbmv(Transpose.NoTranspose.netlib(), numRows, numColumns, kl,
ku, alpha, data, kl + ku + 1, xd, 1, 1, yd, 1);
return y;
}
@Override
public Vector transMultAdd(double alpha, Vector x, Vector y) {
if (!(x instanceof DenseVector) || !(y instanceof DenseVector))
return super.transMultAdd(alpha, x, y);
checkTransMultAdd(x, y);
double[] xd = ((DenseVector) x).getData(), yd = ((DenseVector) y)
.getData();
BLAS.getInstance().dgbmv(Transpose.Transpose.netlib(), numRows, numColumns, kl, ku,
alpha, data, kl + ku + 1, xd, 1, 1, yd, 1);
return y;
}
@Override
public Matrix solve(Matrix B, Matrix X) {
if (!(X instanceof DenseMatrix))
throw new UnsupportedOperationException("X must be a DenseMatrix");
checkSolve(B, X);
double[] Xd = ((DenseMatrix) X).getData();
X.set(B);
// Allocate factorization matrix. The factorization matrix will be
// large enough to accomodate any pivots
BandMatrix Af = new BandMatrix(this, kl, ku + kl);
int[] ipiv = new int[numRows];
intW info = new intW(0);
LAPACK.getInstance().dgbsv(numRows, kl, ku, X.numColumns(),
Af.getData(), Matrices.ld(2 * kl + ku + 1), ipiv, Xd, Matrices.ld(numRows), info);
if (info.val > 0)
throw new MatrixSingularException();
else if (info.val < 0)
throw new IllegalArgumentException();
return X;
}
@Override
public Vector solve(Vector b, Vector x) {
DenseMatrix B = new DenseMatrix(b, false), X = new DenseMatrix(x, false);
solve(B, X);
return x;
}
@Override
public Matrix transpose() {
checkTranspose();
if (kl != ku)
throw new IllegalArgumentException("kl != ku");
for (int j = 0; j < numColumns; ++j)
for (int i = j + 1; i < Math.min(j + kl + 1, numRows); ++i) {
double value = get(i, j);
set(i, j, get(j, i));
set(j, i, value);
}
return this;
}
}
mtj-0.9.14/src/no/uib/cipr/matrix/UpperTriangPackMatrix.java 0000644 0000000 0000000 00000011627 11027512662 022420 0 ustar root root /*
* Copyright (C) 2003-2006 Bjørn-Ove Heimsund
*
* This file is part of MTJ.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* This library 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package no.uib.cipr.matrix;
/**
* Upper triangular packed matrix. In contrast with
* {@link no.uib.cipr.matrix.LowerTriangDenseMatrix LowerTriangDenseMatrix},
* this matrix exploits the sparsity by only storing about half the matrix. As
* such, the triangular matrix
* *
a11 | *a12 | *a13 | *a14 | *
* | a22 | *a23 | *a24 | *
* | * | a33 | *a34 | *
* | * | * | a44 | *
* is packed as follows: *
**
a11 | *a12 | *a22 | *a13 | *a23 | *a33 | *a14 | *a24 | *a34 | *a44 | *
A
must be a packed matrix
*/
public UpperTriangPackMatrix(Matrix A, boolean deep) {
super(A, deep, UpLo.Upper, Diag.NonUnit);
}
/**
* Constructor for UpperTriangPackMatrix
*
* @param A
* Matrix to copy contents from. Only the entries of the relevant
* part are copied
* @param deep
* True if the copy is deep, else false (giving a shallow copy).
* For shallow copies, A
must be a packed matrix
*/
UpperTriangPackMatrix(Matrix A, boolean deep, Diag diag) {
super(A, deep, UpLo.Upper, diag);
}
@Override
public void add(int row, int column, double value) {
if (row > column)
throw new IllegalArgumentException("row > column");
data[getIndex(row, column)] += value;
}
@Override
public void set(int row, int column, double value) {
if (row > column)
throw new IllegalArgumentException("row > column");
data[getIndex(row, column)] = value;
}
@Override
public double get(int row, int column) {
if (row > column)
return 0;
return data[getIndex(row, column)];
}
/**
* Checks the row and column indices, and returns the linear data index
*/
int getIndex(int row, int column) {
check(row, column);
return row + (column + 1) * column / 2;
}
@Override
void copy(Matrix A) {
for (MatrixEntry e : A)
if (e.row() <= e.column())
set(e.row(), e.column(), e.get());
}
@Override
public UpperTriangPackMatrix copy() {
return new UpperTriangPackMatrix(this);
}
}
mtj-0.9.14/src/no/uib/cipr/matrix/UpperSymmDenseMatrix.java 0000644 0000000 0000000 00000005662 11027512662 022303 0 ustar root root /*
* Copyright (C) 2003-2006 Bjørn-Ove Heimsund
*
* This file is part of MTJ.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* This library 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package no.uib.cipr.matrix;
/**
* Upper symmetrix dense matrix. It has the same storage layout as the
* {@link no.uib.cipr.matrix.DenseMatrix DenseMatrix}, but only refers to
* elements above or on the main diagonal. The remaining elements are never
* accessed nor changed, and is known only by symmetry.
*/
public class UpperSymmDenseMatrix extends AbstractSymmDenseMatrix {
/**
* Constructor for UpperSymmDenseMatrix
*
* @param n
* Size of the matrix. Since the matrix must be square, this
* equals both the number of rows and columns
*/
public UpperSymmDenseMatrix(int n) {
super(n, UpLo.Upper);
}
/**
* Constructor for UpperSymmDenseMatrix
*
* @param A
* Matrix to copy. It must be a square matrix, and only the upper
* triangular part is copied
*/
public UpperSymmDenseMatrix(Matrix A) {
this(A, true);
}
/**
* Constructor for UpperSymmDenseMatrix
*
* @param A
* Matrix to copy. It must be a square matrix, and only the upper
* triangular part is copied
* @param deep
* If false, a shallow copy is made. In that case, A
* must be a dense matrix
*/
public UpperSymmDenseMatrix(Matrix A, boolean deep) {
super(A, deep, UpLo.Upper);
}
@Override
public void add(int row, int column, double value) {
if (row <= column)
super.add(row, column, value);
}
@Override
public double get(int row, int column) {
if (row > column)
return super.get(column, row);
return super.get(row, column);
}
@Override
public void set(int row, int column, double value) {
if (row <= column)
super.set(row, column, value);
}
@Override
public UpperSymmDenseMatrix copy() {
return new UpperSymmDenseMatrix(this);
}
@Override
void copy(Matrix A) {
for (MatrixEntry e : A)
if (e.row() <= e.column())
set(e.row(), e.column(), e.get());
}
}
mtj-0.9.14/src/no/uib/cipr/matrix/SVD.java 0000644 0000000 0000000 00000013421 11027512662 016622 0 ustar root root /*
* Copyright (C) 2003-2006 Bjørn-Ove Heimsund
*
* This file is part of MTJ.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* This library 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package no.uib.cipr.matrix;
import org.netlib.lapack.LAPACK;
import org.netlib.util.intW;
/**
* Computes singular value decompositions
*/
public class SVD {
/**
* Work array
*/
private final double[] work;
/**
* Work array
*/
private final int[] iwork;
/**
* Matrix dimension
*/
private final int m, n;
/**
* Compute the singular vectors fully?
*/
private final boolean vectors;
/**
* Job to do
*/
private final JobSVD job;
/**
* The singular values
*/
private final double[] S;
/**
* Singular vectors
*/
private final DenseMatrix U, Vt;
/**
* Creates an empty SVD which will compute all singular values and vectors
*
* @param m
* Number of rows
* @param n
* Number of columns
*/
public SVD(int m, int n) {
this(m, n, true);
}
/**
* Creates an empty SVD
*
* @param m
* Number of rows
* @param n
* Number of columns
* @param vectors
* True to compute the singular vectors, false for just the
* singular values
*/
public SVD(int m, int n, boolean vectors) {
this.m = m;
this.n = n;
this.vectors = vectors;
// Allocate space for the decomposition
S = new double[Math.min(m, n)];
if (vectors) {
U = new DenseMatrix(m, m);
Vt = new DenseMatrix(n, n);
} else
U = Vt = null;
job = vectors ? JobSVD.All : JobSVD.None;
// Find workspace requirements
iwork = new int[8 * Math.min(m, n)];
// Query optimal workspace
double[] worksize = new double[1];
intW info = new intW(0);
LAPACK.getInstance().dgesdd(job.netlib(), m, n, new double[0],
Matrices.ld(m), new double[0], new double[0], Matrices.ld(m),
new double[0], Matrices.ld(n), worksize, -1,
iwork, info);
// Allocate workspace
int lwork = -1;
if (info.val != 0) {
if (vectors)
lwork = 3
* Math.min(m, n)
* Math.min(m, n)
+ Math.max(Math.max(m, n), 4 * Math.min(m, n)
* Math.min(m, n) + 4 * Math.min(m, n));
else
lwork = 3
* Math.min(m, n)
* Math.min(m, n)
+ Math.max(Math.max(m, n), 5 * Math.min(m, n)
* Math.min(m, n) + 4 * Math.min(m, n));
} else
lwork = (int) worksize[0];
lwork = Math.max(lwork, 1);
work = new double[lwork];
}
/**
* Convenience method for computing a full SVD
*
* @param A
* Matrix to decompose, not modified
* @return Newly allocated factorization
* @throws NotConvergedException
*/
public static SVD factorize(Matrix A) throws NotConvergedException {
return new SVD(A.numRows(), A.numColumns()).factor(new DenseMatrix(A));
}
/**
* Computes an SVD
*
* @param A
* Matrix to decompose. Size must conform, and it will be
* overwritten on return. Pass a copy to avoid this
* @return The current decomposition
* @throws NotConvergedException
*/
public SVD factor(DenseMatrix A) throws NotConvergedException {
if (A.numRows() != m)
throw new IllegalArgumentException("A.numRows() != m");
else if (A.numColumns() != n)
throw new IllegalArgumentException("A.numColumns() != n");
intW info = new intW(0);
LAPACK.getInstance().dgesdd(job.netlib(), m, n, A.getData(), Matrices.ld(m), S,
vectors ? U.getData() : new double[0], Matrices.ld(m),
vectors ? Vt.getData() : new double[0], Matrices.ld(n), work, work.length,
iwork, info);
if (info.val > 0)
throw new NotConvergedException(
NotConvergedException.Reason.Iterations);
else if (info.val < 0)
throw new IllegalArgumentException();
return this;
}
/**
* True if singular vectors are stored
*/
public boolean hasSingularVectors() {
return U != null;
}
/**
* Returns the left singular vectors, column-wise. Not available for partial
* decompositions
*
* @return Matrix of size m*m
*/
public DenseMatrix getU() {
return U;
}
/**
* Returns the right singular vectors, row-wise. Not available for partial
* decompositions
*
* @return Matrix of size n*n
*/
public DenseMatrix getVt() {
return Vt;
}
/**
* Returns the singular values (stored in descending order)
*
* @return Array of size min(m,n)
*/
public double[] getS() {
return S;
}
}
mtj-0.9.14/src/no/uib/cipr/matrix/RQ.java 0000644 0000000 0000000 00000007762 11027512662 016523 0 ustar root root /*
* Copyright (C) 2003-2006 Bjørn-Ove Heimsund
*
* This file is part of MTJ.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* This library 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package no.uib.cipr.matrix;
import org.netlib.lapack.LAPACK;
import org.netlib.util.intW;
/**
* Computes RQ decompositions
*/
public class RQ extends OrthogonalComputer {
/**
* Constructs an empty RQ decomposition
*
* @param m
* Number of rows
* @param n
* Number of columns. Must be larger than or equal the number of
* rows
*/
public RQ(int m, int n) {
super(m, n, true);
if (n < m)
throw new IllegalArgumentException("n < m");
int lwork;
// Query optimal workspace. First for computing the factorization
{
work = new double[1];
intW info = new intW(0);
LAPACK.getInstance().dgerqf(m, n, new double[0], Matrices.ld(m), new double[0],
work, -1, info);
if (info.val != 0)
lwork = m;
else
lwork = (int) work[0];
lwork = Math.max(1, lwork);
work = new double[lwork];
}
// Workspace needed for generating an explicit orthogonal matrix
{
workGen = new double[1];
intW info = new intW(0);
LAPACK.getInstance().dorgrq(m, n, m, new double[0],Matrices.ld(m),
new double[0], workGen, -1, info);
if (info.val != 0)
lwork = m;
else
lwork = (int) workGen[0];
lwork = Math.max(1, lwork);
workGen = new double[lwork];
}
}
/**
* Convenience method to compute an RQ decomposition
*
* @param A
* Matrix to decompose. Not modified
* @return Newly allocated decomposition
*/
public static RQ factorize(Matrix A) {
return new RQ(A.numRows(), A.numColumns()).factor(new DenseMatrix(A));
}
@Override
public RQ factor(DenseMatrix A) {
if (Q.numRows() != A.numRows())
throw new IllegalArgumentException("Q.numRows() != A.numRows()");
else if (Q.numColumns() != A.numColumns())
throw new IllegalArgumentException(
"Q.numColumns() != A.numColumns()");
else if (R == null)
throw new IllegalArgumentException("R == null");
/*
* Calculate factorisation, and extract the triangular factor
*/
intW info = new intW(0);
LAPACK.getInstance().dgerqf(m, n, A.getData(), Matrices.ld(m), tau, work,
work.length, info);
if (info.val < 0)
throw new IllegalArgumentException();
R.zero();
for (MatrixEntry e : A)
if (e.column() >= (n - m) + e.row())
R.set(e.row(), e.column() - (n - m), e.get());
/*
* Generate the orthogonal matrix
*/
info.val = 0;
LAPACK.getInstance().dorgrq(m, n, k, A.getData(), Matrices.ld(m), tau, workGen,
workGen.length, info);
if (info.val < 0)
throw new IllegalArgumentException();
Q.set(A);
return this;
}
/**
* Returns the upper triangular factor
*/
public UpperTriangDenseMatrix getR() {
return R;
}
}
mtj-0.9.14/src/no/uib/cipr/matrix/UpperSymmBandMatrix.java 0000644 0000000 0000000 00000006140 11027512662 022101 0 ustar root root /*
* Copyright (C) 2003-2006 Bjørn-Ove Heimsund
*
* This file is part of MTJ.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* This library 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package no.uib.cipr.matrix;
/**
* Upper symmetrical banded matrix. The same storage as
* {@link no.uib.cipr.matrix.BandMatrix BandMatrix}, but without subdiagonals.
* Lower part of the matrix is implictly known by symmetry
*/
public class UpperSymmBandMatrix extends AbstractSymmBandMatrix {
/**
* Constructor for UpperSymmBandMatrix
*
* @param n
* Size of the matrix. Since the matrix must be square, this
* equals both the number of rows and columns
* @param kd
* Number of bands off the main diagonal (off diagonals)
*/
public UpperSymmBandMatrix(int n, int kd) {
super(n, 0, kd, UpLo.Upper);
}
/**
* Constructor for UpperSymmBandMatrix
*
* @param A
* Matrix to copy contents from. Only the parts of A
* that lie within the allocated band are copied over, the rest
* is ignored
* @param kd
* Number of bands off the main diagonal (off diagonals)
*/
public UpperSymmBandMatrix(Matrix A, int kd) {
this(A, kd, true);
}
/**
* Constructor for UpperSymmBandMatrix
*
* @param A
* Matrix to copy contents from. Only the parts of A
* that lie within the allocated band are copied over, the rest
* is ignored
* @param kd
* Number of bands off the main diagonal (off diagonals)
* @param deep
* True for a deep copy. For shallow copies, A
* must be a banded matrix
*/
public UpperSymmBandMatrix(Matrix A, int kd, boolean deep) {
super(A, 0, kd, deep, UpLo.Upper);
}
@Override
public void add(int row, int column, double value) {
if (row <= column)
super.add(row, column, value);
}
@Override
public double get(int row, int column) {
if (row > column)
return super.get(column, row);
return super.get(row, column);
}
@Override
public void set(int row, int column, double value) {
if (row <= column)
super.set(row, column, value);
}
@Override
public UpperSymmBandMatrix copy() {
return new UpperSymmBandMatrix(this, kd);
}
}
mtj-0.9.14/src/no/uib/cipr/matrix/DenseCholesky.java 0000644 0000000 0000000 00000015110 11034473524 020724 0 ustar root root /*
* Copyright (C) 2003-2006 Bjørn-Ove Heimsund
*
* This file is part of MTJ.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* This library 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package no.uib.cipr.matrix;
import no.uib.cipr.matrix.Matrix.Norm;
import org.netlib.lapack.LAPACK;
import org.netlib.util.doubleW;
import org.netlib.util.intW;
/**
* Dense Cholesky decomposition
*/
public class DenseCholesky {
/**
* Matrix dimension
*/
private final int n;
/**
* Cholesky decomposition of a lower matrix
*/
private LowerTriangDenseMatrix Cl;
/**
* Cholesky decomposition of an upper matrix
*/
private UpperTriangDenseMatrix Cu;
/**
* If the matrix is SPD or not
*/
private boolean notspd;
/**
* True for upper part, else false
*/
private final boolean upper;
/**
* Constructor for DenseCholesky
*
* @param n
* Matrix size
* @param upper
* True for decomposing an upper symmetrical matrix, false for a
* lower symmetrical matrix
*/
public DenseCholesky(int n, boolean upper) {
this.n = n;
this.upper = upper;
if (upper)
Cu = new UpperTriangDenseMatrix(n);
else
Cl = new LowerTriangDenseMatrix(n);
}
/**
* Calculates a Cholesky decomposition
*
* @param A
* Matrix to decompose. Not modified
* @return The current decomposition
*/
public static DenseCholesky factorize(Matrix A) {
return new DenseCholesky(A.numRows(), true)
.factor(new UpperSPDDenseMatrix(A));
}
/**
* Calculates a Cholesky decomposition
*
* @param A
* Matrix to decompose. Overwritten on return
* @return The current decomposition
*/
public DenseCholesky factor(LowerSPDDenseMatrix A) {
if (upper)
throw new IllegalArgumentException(
"Cholesky decomposition constructed for upper matrices");
return decompose(A);
}
/**
* Calculates a Cholesky decomposition
*
* @param A
* Matrix to decompose. Overwritten on return
* @return The current decomposition
*/
public DenseCholesky factor(UpperSPDDenseMatrix A) {
if (!upper)
throw new IllegalArgumentException(
"Cholesky decomposition constructed for lower matrices");
return decompose(A);
}
private DenseCholesky decompose(AbstractDenseMatrix A) {
if (n != A.numRows())
throw new IllegalArgumentException("n != A.numRows()");
notspd = false;
intW info = new intW(0);
if (upper)
LAPACK.getInstance().dpotrf(UpLo.Upper.netlib(), A.numRows(),
A.getData(), Matrices.ld(A.numRows()), info);
else
LAPACK.getInstance().dpotrf(UpLo.Lower.netlib(), A.numRows(),
A.getData(), Matrices.ld(A.numRows()), info);
if (info.val > 0)
notspd = true;
else if (info.val < 0)
throw new IllegalArgumentException();
if (upper)
Cu.set(A);
else
Cl.set(A);
return this;
}
/**
* Returns true if the matrix decomposed is symmetrical, positive definite
*/
public boolean isSPD() {
return !notspd;
}
/**
* Returns the decomposition matrix. Only valid for decomposition of a lower
* SPD matrix
*/
public LowerTriangDenseMatrix getL() {
if (!upper)
return Cl;
else
throw new UnsupportedOperationException();
}
/**
* Returns the decomposition matrix. Only valid for decomposition of a upper
* SPD matrix
*/
public UpperTriangDenseMatrix getU() {
if (upper)
return Cu;
else
throw new UnsupportedOperationException();
}
/**
* Solves for B
, overwriting it on return
*/
public DenseMatrix solve(DenseMatrix B) throws MatrixNotSPDException {
if (notspd)
throw new MatrixNotSPDException();
if (n != B.numRows())
throw new IllegalArgumentException("n != B.numRows()");
intW info = new intW(0);
if (upper)
LAPACK.getInstance().dpotrs(UpLo.Upper.netlib(), Cu.numRows(),
B.numColumns(), Cu.getData(), Matrices.ld(Cu.numRows()),
B.getData(), Matrices.ld(Cu.numRows()), info);
else
LAPACK.getInstance().dpotrs(UpLo.Lower.netlib(), Cl.numRows(),
B.numColumns(), Cl.getData(), Matrices.ld(Cl.numRows()),
B.getData(), Matrices.ld(Cl.numRows()), info);
if (info.val < 0)
throw new IllegalArgumentException();
return B;
}
/**
* Computes the reciprocal condition number
*
* @param A
* The matrix this is a decomposition of
* @return The reciprocal condition number. Values close to unity indicate a
* well-conditioned system, while numbers close to zero do not.
*/
public double rcond(Matrix A) {
if (n != A.numRows())
throw new IllegalArgumentException("n != A.numRows()");
if (!A.isSquare())
throw new IllegalArgumentException("!A.isSquare()");
double anorm = A.norm(Norm.One);
double[] work = new double[3 * n];
int[] iwork = new int[n];
intW info = new intW(0);
doubleW rcond = new doubleW(0);
if (upper)
LAPACK.getInstance().dpocon(UpLo.Upper.netlib(), n, Cu.getData(),
Matrices.ld(n), anorm, rcond, work, iwork, info);
else
LAPACK.getInstance().dpocon(UpLo.Lower.netlib(), n, Cl.getData(),
Matrices.ld(n), anorm, rcond, work, iwork, info);
if (info.val < 0)
throw new IllegalArgumentException();
return rcond.val;
}
}
mtj-0.9.14/src/no/uib/cipr/matrix/SymmTridiagEVD.java 0000644 0000000 0000000 00000012607 11027512662 020763 0 ustar root root /*
* Copyright (C) 2003-2006 Bjørn-Ove Heimsund
*
* This file is part of MTJ.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* This library 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package no.uib.cipr.matrix;
import org.netlib.lapack.LAPACK;
import org.netlib.util.intW;
/**
* Computes eigenvalues of symmetrical, tridiagonal matrices
*/
public class SymmTridiagEVD extends SymmEVD {
/**
* Double work array
*/
private final double[] work;
/**
* Integer work array
*/
private final int[] iwork;
/**
* Range of eigenvalues to compute
*/
private final JobEigRange range;
/**
* Eigenvector supports
*/
private final int[] isuppz;
/**
* Tolerance criteria
*/
private final double abstol;
/**
* Sets up an eigenvalue decomposition for symmetrical, tridiagonal
* matrices. Computes all eigenvalues and eigenvectors, and uses a low
* default tolerance criteria
*
* @param n
* Size of the matrix
*/
public SymmTridiagEVD(int n) {
this(n, true);
}
/**
* Sets up an eigenvalue decomposition for symmetrical, tridiagonal
* matrices. Computes all eigenvalues and eigenvectors
*
* @param n
* Size of the matrix
* @param abstol
* Absolute tolerance criteria
*/
public SymmTridiagEVD(int n, double abstol) {
this(n, true, abstol);
}
/**
* Sets up an eigenvalue decomposition for symmetrical, tridiagonal
* matrices. Uses a low default tolerance criteria
*
* @param n
* Size of the matrix
* @param vectors
* True to compute the eigenvectors, false for just the
* eigenvalues
*/
public SymmTridiagEVD(int n, boolean vectors) {
this(n, vectors, LAPACK.getInstance().dlamch("Safe minimum"));
}
/**
* Sets up an eigenvalue decomposition for symmetrical, tridiagonal matrices
*
* @param n
* Size of the matrix
* @param vectors
* True to compute the eigenvectors, false for just the
* eigenvalues
* @param abstol
* Absolute tolerance criteria
*/
public SymmTridiagEVD(int n, boolean vectors, double abstol) {
super(n, vectors);
this.abstol = abstol;
range = JobEigRange.All;
isuppz = new int[2 * Math.max(1, n)];
// Find the needed workspace
double[] worksize = new double[1];
int[] iworksize = new int[1];
intW info = new intW(0);
LAPACK.getInstance().dstevr(job.netlib(), range.netlib(), n, new double[0],
new double[0], 0, 0, 0, 0, abstol, new intW(1), new double[0],
new double[0], Matrices.ld(n), isuppz, worksize, -1, iworksize, -1, info);
// Allocate workspace
int lwork = 0, liwork = 0;
if (info.val != 0) {
lwork = 20 * n;
liwork = 10 * n;
} else {
lwork = (int) worksize[0];
liwork = iworksize[0];
}
lwork = Math.max(1, lwork);
liwork = Math.max(1, liwork);
work = new double[lwork];
iwork = new int[liwork];
}
/**
* Convenience method for computing the full eigenvalue decomposition of the
* given matrix
*
* @param A
* Matrix to factorize. Main diagonal and superdiagonal is
* copied, and the matrix is not modified
* @return Newly allocated decomposition
* @throws NotConvergedException
*/
public static SymmTridiagEVD factorize(Matrix A)
throws NotConvergedException {
return new SymmTridiagEVD(A.numRows()).factor(new SymmTridiagMatrix(A));
}
/**
* Computes the eigenvalue decomposition of the given matrix
*
* @param A
* Matrix to factorize. Overwritten on return
* @return The current eigenvalue decomposition
* @throws NotConvergedException
*/
public SymmTridiagEVD factor(SymmTridiagMatrix A)
throws NotConvergedException {
if (A.numRows() != n)
throw new IllegalArgumentException("A.numRows() != n");
intW info = new intW(0);
LAPACK.getInstance().dstevr(job.netlib(), range.netlib(), n, A.getDiagonal(),
A.getOffDiagonal(), 0, 0, 0, 0, abstol, new intW(1), w,
job == JobEig.All ? Z.getData() : new double[0], Matrices.ld(n), isuppz, work,
work.length, iwork, iwork.length, info);
if (info.val > 0)
throw new NotConvergedException(
NotConvergedException.Reason.Iterations);
else if (info.val < 0)
throw new IllegalArgumentException();
return this;
}
}
mtj-0.9.14/src/no/uib/cipr/matrix/sparse/ 0000755 0000000 0000000 00000000000 11554357132 016623 5 ustar root root mtj-0.9.14/src/no/uib/cipr/matrix/sparse/CG.java 0000644 0000000 0000000 00000005027 11027512662 017757 0 ustar root root /*
* Copyright (C) 2003-2006 Bjørn-Ove Heimsund
*
* This file is part of MTJ.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* This library 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Derived from public domain software at http://www.netlib.org/templates
*/
package no.uib.cipr.matrix.sparse;
import no.uib.cipr.matrix.Matrix;
import no.uib.cipr.matrix.Vector;
/**
* Conjugate Gradients solver. CG solves the symmetric positive definite linear
* system Ax=b
using the Conjugate Gradient method.
*
* @author Templates
*/
public class CG extends AbstractIterativeSolver {
/**
* Vectors for use in the iterative solution process
*/
private Vector p, z, q, r;
/**
* Constructor for CG. Uses the given vector as template for creating
* scratch vectors. Typically, the solution or the right hand side vector
* can be passed, and the template is not modified
*
* @param template
* Vector to use as template for the work vectors needed in the
* solution process
*/
public CG(Vector template) {
p = template.copy();
z = template.copy();
q = template.copy();
r = template.copy();
}
public Vector solve(Matrix A, Vector b, Vector x)
throws IterativeSolverNotConvergedException {
checkSizes(A, b, x);
double alpha = 0, beta = 0, rho = 0, rho_1 = 0;
A.multAdd(-1, x, r.set(b));
for (iter.setFirst(); !iter.converged(r, x); iter.next()) {
M.apply(r, z);
rho = r.dot(z);
if (iter.isFirst())
p.set(z);
else {
beta = rho / rho_1;
p.scale(beta).add(z);
}
A.mult(p, q);
alpha = rho / p.dot(q);
x.add(alpha, p);
r.add(-alpha, q);
rho_1 = rho;
}
return x;
}
}
mtj-0.9.14/src/no/uib/cipr/matrix/sparse/QMR.java 0000644 0000000 0000000 00000015265 11027512662 020132 0 ustar root root /*
* Copyright (C) 2003-2006 Bjørn-Ove Heimsund
*
* This file is part of MTJ.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* This library 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Derived from public domain software at http://www.netlib.org/templates
*/
package no.uib.cipr.matrix.sparse;
import no.uib.cipr.matrix.Matrix;
import no.uib.cipr.matrix.NotConvergedException;
import no.uib.cipr.matrix.Vector;
import no.uib.cipr.matrix.Vector.Norm;
/**
* Quasi-Minimal Residual method. QMR solves the unsymmetric linear system
* Ax = b
using the Quasi-Minimal Residual method. QMR uses two
* preconditioners, and by default these are the same preconditioner.
*
* @author Templates
*/
public class QMR extends AbstractIterativeSolver {
/**
* Left preconditioner
*/
private Preconditioner M1;
/**
* Right preconditioner
*/
private Preconditioner M2;
/**
* Vectors for use in the iterative solution process
*/
private Vector r, y, z, v, w, p, q, d, s, v_tld, w_tld, y_tld, z_tld,
p_tld;
/**
* Constructor for QMR. Uses the given vector as template for creating
* scratch vectors. Typically, the solution or the right hand side vector
* can be passed, and the template is not modified
*
* @param template
* Vector to use as template for the work vectors needed in the
* solution process
*/
public QMR(Vector template) {
M1 = M;
M2 = M;
r = template.copy();
y = template.copy();
z = template.copy();
v = template.copy();
w = template.copy();
p = template.copy();
q = template.copy();
d = template.copy();
s = template.copy();
v_tld = template.copy();
w_tld = template.copy();
y_tld = template.copy();
z_tld = template.copy();
p_tld = template.copy();
}
/**
* Constructor for QMR. Uses the given vector as template for creating
* scratch vectors. Typically, the solution or the right hand side vector
* can be passed, and the template is not modified. Allows setting different
* right and left preconditioners
*
* @param template
* Vector to use as template for the work vectors needed in the
* solution process
* @param M1
* Left preconditioner
* @param M2
* Right preconditioner
*/
public QMR(Vector template, Preconditioner M1, Preconditioner M2) {
this.M1 = M1;
this.M2 = M2;
r = template.copy();
y = template.copy();
z = template.copy();
v = template.copy();
w = template.copy();
p = template.copy();
q = template.copy();
d = template.copy();
s = template.copy();
v_tld = template.copy();
w_tld = template.copy();
y_tld = template.copy();
z_tld = template.copy();
p_tld = template.copy();
}
public Vector solve(Matrix A, Vector b, Vector x)
throws IterativeSolverNotConvergedException {
checkSizes(A, b, x);
double rho = 0, rho_1 = 0, xi = 0, gamma = 1., gamma_1 = 0, theta = 0, theta_1 = 0, eta = -1., delta = 0, ep = 0, beta = 0;
A.multAdd(-1, x, r.set(b));
v_tld.set(r);
M1.apply(v_tld, y);
rho = y.norm(Norm.Two);
w_tld.set(r);
M2.transApply(w_tld, z);
xi = z.norm(Norm.Two);
for (iter.setFirst(); !iter.converged(r, x); iter.next()) {
if (rho == 0)
throw new IterativeSolverNotConvergedException(
NotConvergedException.Reason.Breakdown, "rho", iter);
if (xi == 0)
throw new IterativeSolverNotConvergedException(
NotConvergedException.Reason.Breakdown, "xi", iter);
v.set(1 / rho, v_tld);
y.scale(1 / rho);
w.set(1 / xi, w_tld);
z.scale(1 / xi);
delta = z.dot(y);
if (delta == 0)
throw new IterativeSolverNotConvergedException(
NotConvergedException.Reason.Breakdown, "delta", iter);
M2.apply(y, y_tld);
M1.transApply(z, z_tld);
if (iter.isFirst()) {
p.set(y_tld);
q.set(z_tld);
} else {
p.scale(-xi * delta / ep).add(y_tld);
q.scale(-rho * delta / ep).add(z_tld);
}
A.mult(p, p_tld);
ep = q.dot(p_tld);
if (ep == 0)
throw new IterativeSolverNotConvergedException(
NotConvergedException.Reason.Breakdown, "ep", iter);
beta = ep / delta;
if (beta == 0)
throw new IterativeSolverNotConvergedException(
NotConvergedException.Reason.Breakdown, "beta", iter);
v_tld.set(-beta, v).add(p_tld);
M1.apply(v_tld, y);
rho_1 = rho;
rho = y.norm(Norm.Two);
A.transMultAdd(q, w_tld.set(-beta, w));
M2.transApply(w_tld, z);
xi = z.norm(Norm.Two);
gamma_1 = gamma;
theta_1 = theta;
theta = rho / (gamma_1 * beta);
gamma = 1 / Math.sqrt(1 + theta * theta);
if (gamma == 0)
throw new IterativeSolverNotConvergedException(
NotConvergedException.Reason.Breakdown, "gamma", iter);
eta = -eta * rho_1 * gamma * gamma / (beta * gamma_1 * gamma_1);
if (iter.isFirst()) {
d.set(eta, p);
s.set(eta, p_tld);
} else {
double val = theta_1 * theta_1 * gamma * gamma;
d.scale(val).add(eta, p);
s.scale(val).add(eta, p_tld);
}
x.add(d);
r.add(-1, s);
}
return x;
}
@Override
public void setPreconditioner(Preconditioner M) {
super.setPreconditioner(M);
M1 = M;
M2 = M;
}
}
mtj-0.9.14/src/no/uib/cipr/matrix/sparse/FlexCompColMatrix.java 0000644 0000000 0000000 00000014735 11027512662 023034 0 ustar root root /*
* Copyright (C) 2003-2006 Bjørn-Ove Heimsund
*
* This file is part of MTJ.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* This library 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package no.uib.cipr.matrix.sparse;
import java.util.Arrays;
import java.util.Iterator;
import no.uib.cipr.matrix.AbstractMatrix;
import no.uib.cipr.matrix.DenseVector;
import no.uib.cipr.matrix.Matrix;
import no.uib.cipr.matrix.MatrixEntry;
import no.uib.cipr.matrix.Vector;
import no.uib.cipr.matrix.VectorEntry;
import no.uib.cipr.matrix.sparse.SuperIterator.SuperIteratorEntry;
/**
* Matrix stored column-wise into sparse vectors
*/
public class FlexCompColMatrix extends AbstractMatrix {
/**
* Matrix data
*/
SparseVector[] colD;
/**
* Constructor for FlexCompColMatrix
*
* @param numRows
* Number of rows
* @param numColumns
* Number of column
*/
public FlexCompColMatrix(int numRows, int numColumns) {
super(numRows, numColumns);
colD = new SparseVector[numColumns];
for (int i = 0; i < numColumns; ++i)
colD[i] = new SparseVector(numRows);
}
/**
* Constructor for FlexCompColMatrix
*
* @param A
* Matrix to copy contents from
* @param deep
* True for a deep copy, false for a reference copy. A reference
* copy can only be made of an FlexCompColMatrix
*/
public FlexCompColMatrix(Matrix A, boolean deep) {
super(A);
colD = new SparseVector[numColumns];
if (deep) {
for (int i = 0; i < numColumns; ++i)
colD[i] = new SparseVector(numRows);
set(A);
} else {
FlexCompColMatrix Ar = (FlexCompColMatrix) A;
for (int i = 0; i < numColumns; ++i)
colD[i] = Ar.getColumn(i);
}
}
/**
* Constructor for FlexCompColMatrix
*
* @param A
* Matrix to copy contents from. The copy will be deep
*/
public FlexCompColMatrix(Matrix A) {
this(A, true);
}
/**
* Returns the given column
*/
public SparseVector getColumn(int i) {
return colD[i];
}
/**
* Sets the given column equal the passed vector
*/
public void setColumn(int i, SparseVector x) {
if (x.size() != numRows)
throw new IllegalArgumentException(
"New column must be of the same size as existing column");
colD[i] = x;
}
@Override
public Vector multAdd(double alpha, Vector x, Vector y) {
if (!(x instanceof DenseVector) || !(y instanceof DenseVector))
return super.multAdd(alpha, x, y);
checkMultAdd(x, y);
double[] xd = ((DenseVector) x).getData();
double[] yd = ((DenseVector) y).getData();
// y = 1/alpha * y
y.scale(1. / alpha);
// y = A*x + y
for (int i = 0; i < numColumns; ++i) {
SparseVector v = colD[i];
int[] index = v.getIndex();
double[] data = v.getData();
int length = v.getUsed();
for (int j = 0; j < length; ++j)
yd[index[j]] += data[j] * xd[i];
}
// y = alpha*y = alpha * A'x + y
return y.scale(alpha);
}
@Override
public Vector transMultAdd(final double alpha, final Vector x,
final Vector y) {
checkTransMultAdd(x, y);
for (int i = 0; i < numColumns; ++i)
y.add(i, alpha * colD[i].dot(x));
return y;
}
@Override
public void add(int row, int column, double value) {
colD[column].add(row, value);
}
@Override
public void set(int row, int column, double value) {
colD[column].set(row, value);
}
@Override
public double get(int row, int column) {
return colD[column].get(row);
}
@Override
public IteratorAx = b
* using the Generalized Minimum Residual method. The GMRES iteration is
* restarted after a given number of iterations. By default it is restarted
* after 30 iterations.
*
* @author Templates
*/
public class GMRES extends AbstractIterativeSolver {
/**
* After this many iterations, the GMRES will be restarted.
*/
private int restart;
/**
* Vectors for use in the iterative solution process
*/
private Vector w, u, r;
/**
* Vectors spanning the subspace
*/
private Vector[] v;
/**
* Restart vector
*/
private DenseVector s;
/**
* Hessenberg matrix
*/
private DenseMatrix H;
/**
* Givens rotations for the QR factorization
*/
private GivensRotation[] rotation;
/**
* Constructor for GMRES. Uses the given vector as template for creating
* scratch vectors. Typically, the solution or the right hand side vector
* can be passed, and the template is not modified. The iteration is
* restarted every 30 iterations
*
* @param template
* Vector to use as template for the work vectors needed in the
* solution process
*/
public GMRES(Vector template) {
this(template, 30);
}
/**
* Constructor for GMRES. Uses the given vector as template for creating
* scratch vectors. Typically, the solution or the right hand side vector
* can be passed, and the template is not modified
*
* @param template
* Vector to use as template for the work vectors needed in the
* solution process
* @param restart
* GMRES iteration is restarted after this number of iterations
*/
public GMRES(Vector template, int restart) {
w = template.copy();
u = template.copy();
r = template.copy();
setRestart(restart);
}
/**
* Sets the restart parameter
*
* @param restart
* GMRES iteration is restarted after this number of iterations
*/
public void setRestart(int restart) {
this.restart = restart;
if (restart <= 0)
throw new IllegalArgumentException(
"restart must be a positive integer");
s = new DenseVector(restart + 1);
H = new DenseMatrix(restart + 1, restart);
rotation = new GivensRotation[restart + 1];
v = new Vector[restart + 1];
for (int i = 0; i < v.length; ++i)
v[i] = r.copy().zero();
}
public Vector solve(Matrix A, Vector b, Vector x)
throws IterativeSolverNotConvergedException {
checkSizes(A, b, x);
A.multAdd(-1, x, u.set(b));
M.apply(u, r);
double normr = r.norm(Norm.Two);
M.apply(b, u);
// Outer iteration
for (iter.setFirst(); !iter.converged(r, x); iter.next()) {
v[0].set(1 / normr, r);
s.zero().set(0, normr);
int i = 0;
// Inner iteration
for (; i < restart && !iter.converged(Math.abs(s.get(i))); i++, iter
.next()) {
A.mult(v[i], u);
M.apply(u, w);
for (int k = 0; k <= i; k++) {
H.set(k, i, w.dot(v[k]));
w.add(-H.get(k, i), v[k]);
}
H.set(i + 1, i, w.norm(Norm.Two));
v[i + 1].set(1. / H.get(i + 1, i), w);
// QR factorization of H using Givens rotations
for (int k = 0; k < i; ++k)
rotation[k].apply(H, i, k, k + 1);
rotation[i] = new GivensRotation(H.get(i, i), H.get(i + 1, i));
rotation[i].apply(H, i, i, i + 1);
rotation[i].apply(s, i, i + 1);
}
// Update solution in current subspace
new UpperTriangDenseMatrix(H, i, false).solve(s, s);
for (int j = 0; j < i; j++)
x.add(s.get(j), v[j]);
A.multAdd(-1, x, u.set(b));
M.apply(u, r);
normr = r.norm(Norm.Two);
}
return x;
}
}
mtj-0.9.14/src/no/uib/cipr/matrix/sparse/CompRowMatrix.java 0000644 0000000 0000000 00000040006 11027512662 022235 0 ustar root root /*
* Copyright (C) 2003-2006 Bjørn-Ove Heimsund
*
* This file is part of MTJ.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* This library 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package no.uib.cipr.matrix.sparse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import no.uib.cipr.matrix.AbstractMatrix;
import no.uib.cipr.matrix.DenseVector;
import no.uib.cipr.matrix.Matrix;
import no.uib.cipr.matrix.MatrixEntry;
import no.uib.cipr.matrix.Vector;
import no.uib.cipr.matrix.io.MatrixInfo;
import no.uib.cipr.matrix.io.MatrixSize;
import no.uib.cipr.matrix.io.MatrixVectorReader;
import org.netlib.blas.BLAS;
/**
* Compressed row storage (CRS) matrix
*/
public class CompRowMatrix extends AbstractMatrix {
/**
* Matrix data
*/
double[] data;
/**
* Column indices. These are kept sorted within each row.
*/
int[] columnIndex;
/**
* Indices to the start of each row
*/
int[] rowPointer;
/**
* Constructor for CompRowMatrix
*
* @param r
* Reader to get sparse matrix from
*/
public CompRowMatrix(MatrixVectorReader r) throws IOException {
// Start with a zero-sized matrix
super(0, 0);
// Get matrix information. Use the header if present, else just assume
// that the matrix stores real numbers without any symmetry
MatrixInfo info = null;
if (r.hasInfo())
info = r.readMatrixInfo();
else
info = new MatrixInfo(true, MatrixInfo.MatrixField.Real,
MatrixInfo.MatrixSymmetry.General);
// Check that the matrix is in an acceptable format
if (info.isPattern())
throw new UnsupportedOperationException(
"Pattern matrices are not supported");
if (info.isDense())
throw new UnsupportedOperationException(
"Dense matrices are not supported");
if (info.isComplex())
throw new UnsupportedOperationException(
"Complex matrices are not supported");
// Resize the matrix to correct size
MatrixSize size = r.readMatrixSize(info);
numRows = size.numRows();
numColumns = size.numColumns();
// Start reading entries
int numEntries = size.numEntries();
int[] row = new int[numEntries];
int[] column = new int[numEntries];
double[] entry = new double[numEntries];
r.readCoordinate(row, column, entry);
// Shift the indices from 1 based to 0 based
r.add(-1, row);
r.add(-1, column);
// Find the number of entries on each row
ListA
must be a CompRowMatrix
*/
public CompRowMatrix(Matrix A, boolean deep) {
super(A);
construct(A, deep);
}
/**
* Constructor for CompRowMatrix
*
* @param A
* Copies from this matrix. The copy will be deep
*/
public CompRowMatrix(Matrix A) {
this(A, true);
}
/**
* Returns the column indices
*/
public int[] getColumnIndices() {
return columnIndex;
}
/**
* Returns the row pointers
*/
public int[] getRowPointers() {
return rowPointer;
}
/**
* Returns the internal data storage
*/
public double[] getData() {
return data;
}
@Override
public Matrix mult(Matrix B, Matrix C) {
checkMultAdd(B, C);
C.zero();
// optimised a little bit to avoid zeros in rows, but not to
// exploit sparsity of matrix B
for (int i = 0; i < numRows; ++i) {
for (int j = 0; j < C.numColumns(); ++j) {
double dot = 0;
for (int k = rowPointer[i]; k < rowPointer[i + 1]; ++k) {
dot += data[k] * B.get(columnIndex[k], j);
}
if (dot != 0) {
C.set(i, j, dot);
}
}
}
return C;
}
@Override
public Vector mult(Vector x, Vector y) {
// check dimensions
checkMultAdd(x, y);
// can't assume this, unfortunately
y.zero();
if (x instanceof DenseVector) {
// DenseVector optimisations
double[] xd = ((DenseVector) x).getData();
for (int i = 0; i < numRows; ++i) {
double dot = 0;
for (int j = rowPointer[i]; j < rowPointer[i + 1]; j++) {
dot += data[j] * xd[columnIndex[j]];
}
if (dot != 0) {
y.set(i, dot);
}
}
return y;
}
// use sparsity of matrix (not vector), as get(,) is slow
// TODO: additional optimisations for mult(ISparseVector, Vector)
// note that this would require Sparse BLAS, e.g. BLAS_DUSDOT(,,,,)
// @see http://www.netlib.org/blas/blast-forum/chapter3.pdf
for (int i = 0; i < numRows; ++i) {
double dot = 0;
for (int j = rowPointer[i]; j < rowPointer[i + 1]; j++) {
dot += data[j] * x.get(columnIndex[j]);
}
y.set(i, dot);
}
return y;
}
@Override
public Vector multAdd(double alpha, Vector x, Vector y) {
if (!(x instanceof DenseVector) || !(y instanceof DenseVector))
return super.multAdd(alpha, x, y);
checkMultAdd(x, y);
double[] xd = ((DenseVector) x).getData();
double[] yd = ((DenseVector) y).getData();
for (int i = 0; i < numRows; ++i) {
double dot = 0;
for (int j = rowPointer[i]; j < rowPointer[i + 1]; ++j)
dot += data[j] * xd[columnIndex[j]];
yd[i] += alpha * dot;
}
return y;
}
@Override
public Vector transMult(Vector x, Vector y) {
if (!(x instanceof DenseVector) || !(y instanceof DenseVector))
return super.transMult(x, y);
checkTransMultAdd(x, y);
double[] xd = ((DenseVector) x).getData();
double[] yd = ((DenseVector) y).getData();
y.zero();
for (int i = 0; i < numRows; ++i)
for (int j = rowPointer[i]; j < rowPointer[i + 1]; ++j)
yd[columnIndex[j]] += data[j] * xd[i];
return y;
}
@Override
public Vector transMultAdd(double alpha, Vector x, Vector y) {
if (!(x instanceof DenseVector) || !(y instanceof DenseVector))
return super.transMultAdd(alpha, x, y);
checkTransMultAdd(x, y);
double[] xd = ((DenseVector) x).getData();
double[] yd = ((DenseVector) y).getData();
// y = 1/alpha * y
y.scale(1. / alpha);
// y = A'x + y
for (int i = 0; i < numRows; ++i)
for (int j = rowPointer[i]; j < rowPointer[i + 1]; ++j)
yd[columnIndex[j]] += data[j] * xd[i];
// y = alpha*y = alpha*A'x + y
return y.scale(alpha);
}
@Override
public void set(int row, int column, double value) {
check(row, column);
int index = getIndex(row, column);
data[index] = value;
}
@Override
public void add(int row, int column, double value) {
check(row, column);
int index = getIndex(row, column);
data[index] += value;
}
@Override
public double get(int row, int column) {
check(row, column);
int index = no.uib.cipr.matrix.sparse.Arrays.binarySearch(columnIndex,
column, rowPointer[row], rowPointer[row + 1]);
if (index >= 0)
return data[index];
else
return 0;
}
/**
* Finds the insertion index
*/
private int getIndex(int row, int column) {
int i = no.uib.cipr.matrix.sparse.Arrays.binarySearch(columnIndex,
column, rowPointer[row], rowPointer[row + 1]);
if (i != -1 && columnIndex[i] == column)
return i;
else
throw new IndexOutOfBoundsException("Entry (" + (row + 1) + ", "
+ (column + 1) + ") is not in the matrix structure");
}
@Override
public CompRowMatrix copy() {
return new CompRowMatrix(this);
}
@Override
public IteratoromegaF=1
and
* omegaR=1.85
, while in the postsmoothing,
* omegaF=1.85
and omegaR=1
. Sets
* nu1=nu2=gamma=1
, has a smallest matrix size of 40, and
* sets omega=2/3
.
*/
public AMG() {
this(1, 1.85, 1.85, 1, 1, 1, 1, 40, 2. / 3);
}
public Vector apply(Vector b, Vector x) {
u[0].set(x);
f[0].set(b);
transpose = false;
cycle(0);
return x.set(u[0]);
}
public Vector transApply(Vector b, Vector x) {
u[0].set(x);
f[0].set(b);
transpose = true;
cycle(0);
return x.set(u[0]);
}
public void setMatrix(Matrix A) {
Listcycle(0)
*/
private void cycle(int k) {
if (k == m - 1)
directSolve();
else {
// Presmoothings
preRelax(k);
u[k + 1].zero();
// Compute the residual
A[k].multAdd(-1, u[k], r[k].set(f[k]));
// Restrict to the next coarser level
I[k].transMult(r[k], f[k + 1]);
// Recurse to next level
for (int i = 0; i < gamma; ++i)
cycle(k + 1);
// Add residual correction by prolongation
I[k].multAdd(u[k + 1], u[k]);
// Postsmoothings
postRelax(k);
}
}
/**
* Solves directly at the coarsest level
*/
private void directSolve() {
int k = m - 1;
u[k].set(f[k]);
DenseMatrix U = new DenseMatrix(u[k], false);
if (transpose)
lu.transSolve(U);
else
lu.solve(U);
}
/**
* Applies the relaxation scheme at the given level
*
* @param k
* Multigrid level
*/
private void preRelax(int k) {
for (int i = 0; i < nu1; ++i)
if (transpose)
preM[k].transApply(f[k], u[k]);
else
preM[k].apply(f[k], u[k]);
}
/**
* Applies the relaxation scheme at the given level
*
* @param k
* Multigrid level
*/
private void postRelax(int k) {
for (int i = 0; i < nu2; ++i)
if (transpose)
postM[k].transApply(f[k], u[k]);
else
postM[k].apply(f[k], u[k]);
}
/**
* Creates aggregates. These are disjoint sets, each of which represents one
* node at a coarser mesh by aggregating together a set of fine nodes
*/
private static class Aggregator {
/**
* The aggregates
*/
private List