/*
* Copyright 2011-2013 JOptimizer
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.joptimizer.util;
import java.util.Random;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.math3.linear.Array2DRowRealMatrix;
import org.apache.commons.math3.linear.CholeskyDecomposition;
import org.apache.commons.math3.linear.LUDecomposition;
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.QRDecomposition;
import org.apache.commons.math3.linear.RealMatrix;
import org.apache.commons.math3.linear.SingularMatrixException;
import cern.colt.matrix.DoubleFactory2D;
import cern.colt.matrix.DoubleMatrix2D;
import cern.colt.matrix.linalg.Algebra;
/**
* @author alberto trivellato (alberto.trivellato@gmail.com)
*/
public class Utils {
private static Double RELATIVE_MACHINE_PRECISION = Double.NaN;
private static Log log = LogFactory.getLog(Utils.class);
public static DoubleMatrix2D randomValuesMatrix(int rows, int cols, double min, double max) {
return randomValuesMatrix(rows, cols, min, max, null);
}
public static DoubleMatrix2D randomValuesMatrix(int rows, int cols, double min, double max, Long seed) {
Random random = (seed != null) ? new Random(seed) : new Random();
double[][] matrix = new double[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
matrix[i][j] = min + random.nextDouble() * (max - min);
}
}
return DoubleFactory2D.dense.make(matrix);
}
/**
* @TODO: check this!!!
* @see "http://mathworld.wolfram.com/PositiveDefiniteMatrix.html"
*/
public static DoubleMatrix2D randomValuesPositiveMatrix(int rows, int cols, double min, double max, Long seed) {
DoubleMatrix2D Q = Utils.randomValuesMatrix(rows, cols, min, max, seed);
DoubleMatrix2D P = Algebra.DEFAULT.mult(Q, Algebra.DEFAULT.transpose(Q.copy()));
return Algebra.DEFAULT.mult(P, P);
}
/**
* Residual conditions check after resolution of A.x=b.
*
* eps := The relative machine precision
* N := matrix dimension
*
* Checking the residual of the solution.
* Inversion pass if scaled residuals are less than 10:
* ||Ax-b||_oo/( (||A||_oo . ||x||_oo + ||b||_oo) . N . eps ) < 10.
*
* @param A not-null matrix
* @param x not-null vector
* @param b not-null vector
*/
// public static boolean checkScaledResiduals(DoubleMatrix2D A, DoubleMatrix1D x, DoubleMatrix1D b, Algebra ALG) {
// //The relative machine precision
// double eps = RELATIVE_MACHINE_PRECISION;
// int N = A.rows();//matrix dimension
// double residual = -Double.MAX_VALUE;
// if(Double.compare(ALG.normInfinity(x), 0.)==0 && Double.compare(ALG.normInfinity(b), 0.)==0){
// return true;
// }else{
// residual = ALG.normInfinity(ALG.mult(A, x).assign(b, Functions.minus)) /
// ((ALG.normInfinity(A)*ALG.normInfinity(x) + ALG.normInfinity(b)) * N * eps);
// log.debug("scaled residual: " + residual);
// return residual < 10;
// }
// }
/**
* The smallest positive (epsilon) such that 1.0 + epsilon != 1.0.
* @see http://en.wikipedia.org/wiki/Machine_epsilon#Approximation_using_Java
*/
public static final double getDoubleMachineEpsilon() {
if(!Double.isNaN(RELATIVE_MACHINE_PRECISION)){
return RELATIVE_MACHINE_PRECISION;
}
synchronized(RELATIVE_MACHINE_PRECISION){
if(!Double.isNaN(RELATIVE_MACHINE_PRECISION)){
return RELATIVE_MACHINE_PRECISION;
}
double eps = 1.;
do {
eps /= 2.;
} while ((double) (1. + (eps / 2.)) != 1.);
log.debug("Calculated double machine epsilon: " + eps);
RELATIVE_MACHINE_PRECISION = eps;
}
return RELATIVE_MACHINE_PRECISION;
}
/**
* @see http://en.wikipedia.org/wiki/Machine_epsilon#Approximation_using_Java
*/
// public static final float calculateFloatMachineEpsilon() {
// float eps = 1.0f;
// do {
// eps /= 2.0f;
// } while ((float) (1.0 + (eps / 2.0)) != 1.0);
// log.debug("Calculated float machine epsilon: " + eps);
// return eps;
// }
public static RealMatrix squareMatrixInverse(RealMatrix M) throws SingularMatrixException{
if(!M.isSquare()){
throw new IllegalArgumentException("Not square matrix!");
}
// try commons-math cholesky
try {
CholeskyDecomposition cd = new CholeskyDecomposition(M);
return cd.getSolver().getInverse();
} catch (SingularMatrixException e) {
throw e;
} catch (Exception e) {
log.debug(e.getMessage());
}
// try joptimizer cholesky
try {
CholeskyFactorization cd = new CholeskyFactorization(M.getData());
double[][] MInv = cd.getInverse();
return MatrixUtils.createRealMatrix(MInv);
} catch (Exception e) {
log.debug(e.getMessage());
}
// try LU
try{
LUDecomposition ld = new LUDecomposition(M);
return ld.getSolver().getInverse();
} catch (SingularMatrixException e) {
throw e;
} catch (Exception e) {
log.debug(e.getMessage());
}
// try QR
try {
QRDecomposition qr = new org.apache.commons.math3.linear.QRDecomposition(M);
return qr.getSolver().getInverse();
} catch (SingularMatrixException e) {
throw e;
} catch (Exception e) {
log.debug(e.getMessage());
}
return null;
}
/**
* Get the index of the maximum entry.
*/
public static int getMaxIndex(double[] v){
int maxIndex = -1;
double maxValue = -Double.MAX_VALUE;
for(int i=0; imaxValue){
maxIndex = i;
maxValue = v[i];
}
}
return maxIndex;
}
/**
* Get the index of the minimum entry.
*/
public static int getMinIndex(double[] v){
int minIndex = -1;
double minValue = Double.MAX_VALUE;
for(int i=0; i
Ads help maintain this website.