eu.crisis_economics.abm.algorithms.optimization.NonLinearExtremizer.java Source code

Java tutorial

Introduction

Here is the source code for eu.crisis_economics.abm.algorithms.optimization.NonLinearExtremizer.java

Source

/*
 * This file is part of CRISIS, an economics simulator.
 * 
 * Copyright (C) 2015 John Kieran Phillips
 *
 * CRISIS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * CRISIS 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with CRISIS.  If not, see <http://www.gnu.org/licenses/>.
 */
package eu.crisis_economics.abm.algorithms.optimization;

import org.apache.commons.math3.linear.ArrayRealVector;
import org.apache.commons.math3.exception.NullArgumentException;

public abstract class NonLinearExtremizer {
    public final static class ImmutableExtremumResult {
        double[] startingCoordinate, extremalCoordinate, derivativeAtExtremum;
        double extremalEvalutation, normOfDerivativeAtExtremum;

        private ImmutableExtremumResult() {
        }; // Immutable

        /** Get the opimisation seed coordinate. */
        public double[] getStartingCoordinate() {
            return startingCoordinate.clone();
        }

        /** Get the coordinate result of the optimisation. */
        public double[] getExtremumCoordinate() {
            return extremalCoordinate.clone();
        }

        /** Get the derivative of the merit function at the extremum. */
        public double[] getDerivativeVectorAtExtremum() {
            return derivativeAtExtremum.clone();
        }

        /** Get the evaluation of the merit function at the extremum. */
        public double getMeritFunctionAtExtremum() {
            return extremalEvalutation;
        }

        /** Get the (Euclidean) norm of the derivative at the extremum. */
        public double getNormOfDerivativeAtExtremum() {
            return normOfDerivativeAtExtremum;
        }

        @Override
        public String toString() {
            String result = "";
            final int n = startingCoordinate.length;
            for (int i = 0; i < n; ++i)
                result += String.format("x[%d] = %16.10g\n", i, extremalCoordinate[i]);
            result += String.format("evaluation at extremum:         %16.10g\n", getMeritFunctionAtExtremum());
            result += String.format("L2 derivative norm at extremum: %16.10g\n", getNormOfDerivativeAtExtremum());
            return result;
        }
    }

    protected final ImmutableExtremumResult createImmutableExtremumResult(double[] startingCoordinate,
            double[] extremalCoordinate, double[] derivativeAtExtremum, double extremalEvalutation) {
        if (startingCoordinate == null || extremalCoordinate == null || derivativeAtExtremum == null)
            throw new NullArgumentException();
        if (Double.isNaN(extremalEvalutation))
            throw new IllegalArgumentException();
        final int n = startingCoordinate.length;
        if (n == 0 || extremalCoordinate.length != n || derivativeAtExtremum.length != n)
            throw new IllegalArgumentException();
        ImmutableExtremumResult result = new ImmutableExtremumResult();
        result.startingCoordinate = startingCoordinate.clone();
        result.extremalCoordinate = extremalCoordinate.clone();
        result.derivativeAtExtremum = derivativeAtExtremum.clone();
        result.extremalEvalutation = extremalEvalutation;
        result.normOfDerivativeAtExtremum = (new ArrayRealVector(derivativeAtExtremum)).getNorm();
        return result;
    }

    public interface OnceDifferentiableMeritFunction {
        public double evaluateAt(double[] x);

        public double[] partialDerivativesAt(double[] x);
    }

    private OnceDifferentiableMeritFunction meritFunction;

    private double solutionToleranceDemand;

    public NonLinearExtremizer(OnceDifferentiableMeritFunction meritFunction, double solutionToleranceDemand) {
        if (meritFunction == null)
            throw new NullArgumentException();
        if (solutionToleranceDemand <= 0.)
            throw new IllegalArgumentException("NonLinearExtremizer: solution tolerance (value"
                    + solutionToleranceDemand + ")" + " is negative or zero.");
        this.meritFunction = meritFunction;
        this.solutionToleranceDemand = solutionToleranceDemand;
    }

    /** Perform the optimisation. Returns null if the merit function cannot be optimised. */
    abstract public ImmutableExtremumResult performOptimization(double[] startingCoordinate);

    /** Get the merit function for this optimisation. */
    public final OnceDifferentiableMeritFunction getMeritFunction() {
        return meritFunction;
    }

    /** Get the acceptable solution tolerance (epsilon) for this optimisation. */
    public final double getSolutionToleranceDemand() {
        return solutionToleranceDemand;
    }
}