/*
GeoGebra - Dynamic Mathematics for Everyone
http://www.geogebra.org
This file is part of GeoGebra.
This program 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.
*/
package org.geogebra.common.kernel.advanced;
import org.apache.commons.math3.analysis.UnivariateFunction;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.algos.AlgoElement;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.kernel.geos.GeoNumberValue;
import org.geogebra.common.kernel.optimization.ExtremumFinderI;
/**
* AlgoOptimize: Abstract class for AlgoMaximize and AlgoMinimize Command
* Minimize[ <dependent variable>, <independent variable> ] (and Minimize[] )
* which searches for the independent variable which gives the smallest/largest
* result for the dependent variable.
*
* Packages the relationship as a UnivariateFunction for the ExtremumFinder.
*
* @author Hans-Petter Ulven
* @version 20.02.2011
*
* ToDo: -Bug: Intermediate steps in searching produces traces in
* Graphic view -Find a better way to avoid all the recursive calls,
* even if they are not executed all the way
*
*/
public abstract class AlgoOptimize extends AlgoElement {
/** optimization types */
public enum OptimizationType {
/** minimize */
MINIMIZE,
/** maximize */
MAXIMIZE
}
private Construction optCons = null;
private ExtremumFinderI extrFinder = null; // Uses ExtremumFinder for the
// dirty work
private UnivariateFunction i_am_not_a_real_function = null;
private GeoElement dep = null;
private Optimizer indep = null;
private GeoElement result = null;
private OptimizationType type = OptimizationType.MINIMIZE;
private boolean isrunning = false; // To stop recursive calls. Both Maximize
// and Minimize.
/**
* Constructor for optimization algos
*
* @param cons
* construction
* @param label
* label for output
* @param dep
* dependent value
* @param indep
* independent number
* @param type
* maximize or minimize
*/
public AlgoOptimize(Construction cons, String label, GeoNumberValue dep,
Optimizer indep, OptimizationType type) {
super(cons);
this.optCons = cons;
this.dep = dep.toGeoElement();
this.indep = indep;
this.type = type;
extrFinder = kernel.getExtremumFinder();
i_am_not_a_real_function = indep;
result = indep.getGeo().copy();
setInputOutput();
compute();
result.setLabel(label);
}// Constructor for Maximize
/** Implementing AlgoElement */
@Override
protected void setInputOutput() {
/*
* input = new GeoElement[1]; input[0] = geoList;
*
* output = new GeoElement[1]; output[0] = max;
*/
input = new GeoElement[2];
input[0] = dep;
input[1] = indep.getGeo();
super.setOutputLength(1);
super.setOutput(0, result);
setDependencies(); // done by AlgoElement
}// setInputOutput()
/** Implementing AlgoElement */
@Override
public final void compute() {
double old = 0.0d, res = 0.0;
if (isrunning) {
return;
} // do nothing return as fast as possible
old = indep.getValue();
isrunning = true;
if (!indep.hasBounds()) {
result.setUndefined();
return;
}
if (type == OptimizationType.MINIMIZE) {
res = extrFinder.findMinimum(indep.getIntervalMin(),
indep.getIntervalMax(), i_am_not_a_real_function, 5.0E-8); // debug("Minimize
// ("+counter+")
// found
// "+res);
} else {
res = extrFinder.findMaximum(indep.getIntervalMin(),
indep.getIntervalMax(), i_am_not_a_real_function, 5.0E-8); // debug("Maximize
// ("+counter+")
// found
// "+res);
}
indep.setValue(res);
result.set(indep.getGeo());
indep.setValue(old);
// indep.updateCascade();
optCons.updateConstruction();
isrunning = false;
}
/**
* @return optimal value of independent number
*/
public GeoElement getResult() {
return result;
}// getMinimized()
}// abstract class AlgoOptimize