net.sf.tweety.math.opt.solver.ApacheCommonsCMAESOptimizer.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.tweety.math.opt.solver.ApacheCommonsCMAESOptimizer.java

Source

/*
 *  This file is part of "Tweety", a collection of Java libraries for
 *  logical aspects of artificial intelligence and knowledge representation.
 *
 *  Tweety is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License version 3 as
 *  published by the Free Software Foundation.
 *
 *  This program 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 program. If not, see <http://www.gnu.org/licenses/>.
 *
 *  Copyright 2016 The Tweety Project Team <http://tweetyproject.org/contact/>
 */
package net.sf.tweety.math.opt.solver;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.math3.analysis.MultivariateFunction;
import org.apache.commons.math3.optim.InitialGuess;
import org.apache.commons.math3.optim.MaxEval;
import org.apache.commons.math3.optim.PointValuePair;
import org.apache.commons.math3.optim.SimpleBounds;
import org.apache.commons.math3.optim.SimplePointChecker;
import org.apache.commons.math3.optim.nonlinear.scalar.GoalType;
import org.apache.commons.math3.optim.nonlinear.scalar.ObjectiveFunction;
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.CMAESOptimizer;
import org.apache.commons.math3.random.JDKRandomGenerator;

import net.sf.tweety.math.GeneralMathException;
import net.sf.tweety.math.opt.ConstraintSatisfactionProblem;
import net.sf.tweety.math.opt.OptimizationProblem;
import net.sf.tweety.math.opt.Solver;
import net.sf.tweety.math.term.FloatConstant;
import net.sf.tweety.math.term.Term;
import net.sf.tweety.math.term.Variable;

/**
 * This class is a wrapper for the Apache Commons Math3 CMAES optimizer.
 * See https://commons.apache.org/proper/commons-math/  
 * @author Matthias Thimm
 */
public class ApacheCommonsCMAESOptimizer extends Solver {

    /** population size */
    private int populationSize;
    /** Maximal number of iterations.*/
    private int maxIterations;
    /** Whether to stop if objective function value is smaller than stopFitness. */
    private double stopFitness;
    /** Chooses the covariance matrix update method. */
    private boolean isActiveCMA;
    /** Number of initial iterations, where the covariance matrix remains diagonal. */
    private int diagonalOnly;
    /** Determines how often new random objective variables are generated in case they are out of bounds. */
    private int checkFeasableCount;
    /** the precision of the optimization*/
    private double precision;

    /**
     * Parameters from org.apache.commons.math3.optim.nonlinear.scalar.noderiv.CMAESOptimizer:
     * @param maxIterations Maximal number of iterations.
     * @param stopFitness Whether to stop if objective function value is smaller than stopFitness.
     * @param isActiveCMA Chooses the covariance matrix update method.
     * @param diagonalOnly Number of initial iterations, where the covariance matrix remains diagonal.
     * @param checkFeasableCount Determines how often new random objective variables are generated in case they are out of bounds.
     * @param precision the precision of the optimization
     */
    public ApacheCommonsCMAESOptimizer(int populationSize, int maxIterations, double stopFitness,
            boolean isActiveCMA, int diagonalOnly, int checkFeasableCount, double precision) {
        this.populationSize = populationSize;
        this.maxIterations = maxIterations;
        this.stopFitness = stopFitness;
        this.isActiveCMA = isActiveCMA;
        this.diagonalOnly = diagonalOnly;
        this.checkFeasableCount = checkFeasableCount;
        this.precision = precision;
    }

    /* (non-Javadoc)
     * @see net.sf.tweety.math.opt.Solver#solve(net.sf.tweety.math.opt.ConstraintSatisfactionProblem)
     */
    @Override
    public Map<Variable, Term> solve(ConstraintSatisfactionProblem problem) throws GeneralMathException {
        // only optimization problems
        if (!(problem instanceof OptimizationProblem))
            throw new IllegalArgumentException("Only optimization problems allowed for this solver.");
        OptimizationProblem p = (OptimizationProblem) problem;
        // only box constraints allowed (so far)
        if (!p.isEmpty())
            throw new IllegalArgumentException(
                    "Only optimization problems with box constraints on variables allowed for this solver (no other constraints.");
        final List<Variable> vars = new ArrayList<Variable>(p.getTargetFunction().getVariables());
        double[] lb = new double[vars.size()];
        double[] ub = new double[vars.size()];
        double[] s = new double[vars.size()];
        double[] sigma = new double[vars.size()];
        for (int i = 0; i < vars.size(); i++) {
            lb[i] = vars.get(i).getLowerBound();
            ub[i] = vars.get(i).getUpperBound();
            s[i] = (lb[i] + ub[i]) / 2;
            sigma[i] = ub[i] - lb[i];
        }
        final Term targetFunction = p.getTargetFunction();
        MultivariateFunction target = new MultivariateFunction() {
            @Override
            public double value(double[] arg0) {
                return targetFunction.replaceAllTerms(arg0, vars).doubleValue();
            }
        };
        // construct solver
        CMAESOptimizer optimizer = new CMAESOptimizer(this.maxIterations, this.stopFitness, this.isActiveCMA,
                this.diagonalOnly, this.checkFeasableCount, new JDKRandomGenerator(), false,
                new SimplePointChecker<PointValuePair>(this.precision, this.precision));
        PointValuePair val = optimizer.optimize(new CMAESOptimizer.Sigma(sigma), new ObjectiveFunction(target),
                new InitialGuess(s),
                p.getType() == OptimizationProblem.MAXIMIZE ? GoalType.MAXIMIZE : GoalType.MINIMIZE,
                new MaxEval(this.maxIterations), new SimpleBounds(lb, ub),
                new CMAESOptimizer.PopulationSize(this.populationSize));
        Map<Variable, Term> result = new HashMap<Variable, Term>();
        for (int i = 0; i < vars.size(); i++)
            result.put(vars.get(i), new FloatConstant(val.getPoint()[i]));
        return result;
    }

    /**
     * Returns the variable assignment that maximizes/minimizes the given term
     * (which only contains variables with defined upper and lower bounds).
     * @param t the term to be evaluated
     * @param optimization_objective one of OptimizationProblem.MAXIMIZE, OptimizationProblem.MINIMIZE 
     * @return the optimal variable assignment
     * @throws GeneralMathException 
     */
    public Map<Variable, Term> solve(Term t, int optimization_type) throws GeneralMathException {
        OptimizationProblem p = new OptimizationProblem(optimization_type);
        p.setTargetFunction(t);
        return this.solve(p);
    }

    /* (non-Javadoc)
     * @see net.sf.tweety.math.opt.Solver#isInstalled()
     */
    public static boolean isInstalled() throws UnsupportedOperationException {
        // as this is a native implementation it is always installed
        return true;
    }

}