/*
 * 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.solvers;

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.ArrayRealVector;
import org.apache.commons.math3.linear.CholeskyDecomposition;
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealMatrix;
import org.apache.commons.math3.linear.RealVector;

import cern.colt.matrix.DoubleFactory2D;
import cern.colt.matrix.DoubleMatrix2D;

/**
 * H.v + [A]T.w = -g, 
* A.v = -h,
* * (H is square) * * @see "S.Boyd and L.Vandenberghe, Convex Optimization, p. 542" * @author alberto trivellato (alberto.trivellato@gmail.com) */ public abstract class KKTSolver { protected RealMatrix H; protected RealMatrix A; protected RealMatrix AT; protected RealVector g; protected RealVector h; protected double toleranceKKT; protected boolean checkKKTSolutionAccuracy; private DoubleFactory2D F2 = DoubleFactory2D.dense; private Log log = LogFactory.getLog(this.getClass().getName()); /** * Returns two vectors v and w. */ public abstract double[][] solve() throws Exception; public void setHMatrix(double[][] HMatrix) { this.H = new Array2DRowRealMatrix(HMatrix, false); } public void setAMatrix(double[][] AMatrix) { if (AMatrix != null && AMatrix.length > 0) { this.A = new Array2DRowRealMatrix(AMatrix, false); } } public void setATMatrix(double[][] ATMatrix) { if (ATMatrix != null && ATMatrix.length > 0) { this.AT = new Array2DRowRealMatrix(ATMatrix, false); } } public void setGVector(double[] gVector) { this.g = new ArrayRealVector(gVector); } public void setHVector(double[] hVector) { if (hVector != null && hVector.length > 0) { this.h = new ArrayRealVector(hVector); } } /** * Acceptable tolerance for system resolution. */ public void setToleranceKKT(double tolerance) { this.toleranceKKT = tolerance; } public void setCheckKKTSolutionAccuracy(boolean b) { this.checkKKTSolutionAccuracy = b; } /** * Solve the KKT system as a whole. * Useful only if A not null. * @see "S.Boyd and L.Vandenberghe, Convex Optimization, p. 547" */ protected double[][] solveFullKKT(KKTSolver kktSolver) throws Exception{ log.debug("solveFullKKT"); //if the KKT matrix is nonsingular, then H + [A]T.A > 0. RealMatrix HATA = H.add(AT.multiply(A)); try{ CholeskyDecomposition cFact = new CholeskyDecomposition(HATA); cFact.getSolver().getInverse(); }catch(Exception e){ throw new Exception("singular KKT system"); } kktSolver.setHMatrix(HATA.getData());//this is positive kktSolver.setAMatrix(A.getData()); kktSolver.setATMatrix(AT.getData()); kktSolver.setGVector(g.toArray()); if(h!=null){ RealVector ATQh = AT.operate(MatrixUtils.createRealIdentityMatrix(A.getRowDimension()).operate(h)); RealVector gATQh = g.add(ATQh); kktSolver.setGVector(gATQh.toArray()); kktSolver.setHVector(h.toArray()); } return kktSolver.solve(); } protected boolean checkKKTSolutionAccuracy(RealVector v, RealVector w) { // build the full KKT matrix double norm; DoubleMatrix2D M = F2.make(this.H.getData()); if (this.A != null) { if(h!=null){ DoubleMatrix2D[][] parts = { { F2.make(this.H.getData()), F2.make(this.AT.getData()) }, { F2.make(this.A.getData()), null } }; M = F2.compose(parts); RealMatrix KKT = new Array2DRowRealMatrix(M.toArray()); RealVector X = v.append(w); RealVector Y = g.append(h); // check ||KKT.X+Y||

Ads help maintain this website.