/* GeoGebra - Dynamic Mathematics for Schools Copyright Markus Hohenwarter and GeoGebra Inc., 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.algos; import org.apache.commons.math3.analysis.UnivariateFunction; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.commands.Commands; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoFunction; import org.geogebra.common.kernel.geos.GeoFunctionable; import org.geogebra.common.kernel.geos.GeoNumberValue; import org.geogebra.common.kernel.geos.GeoPoint; import org.geogebra.common.kernel.optimization.ExtremumFinderI; /** * Command: Min[<function>,left-x,right-x] * * Numerically calculates Extremum point for <function> in closed interval * [left-x,right-x] without being dependent on being able to find the derivate * of <function>. * * Restrictions for use: <function> should be continuous and only have one * extremum in the interval [left-x,right-x] * * Breaking restrictions will give unpredictable results: -Will usually find the * first minimum if more than one extremums -Unpredictable results if * discontinuous in interval * * Uses Brent's algorithm in geogebra.kernel.optimization.ExtremumFinder; * * @author Hans-Petter Ulven * @version 2011-02.20 */ public class AlgoFunctionMinMax extends AlgoElement { private GeoFunctionable function; // input private GeoFunction f; private GeoNumberValue left; // input private GeoNumberValue right; // input private GeoPoint E; // output private ExtremumFinderI extrFinder = null; private boolean isMin; /** * Constructor for Extremum[f,l,r] * * @param cons * construction * @param label * label * @param function * function to maximize * @param left * left boundary * @param right * right boundary * @param isMin * true for min, false for max */ public AlgoFunctionMinMax(Construction cons, String label, GeoFunctionable function, GeoNumberValue left, GeoNumberValue right, boolean isMin) { super(cons); this.function = function; this.f = function.getGeoFunction(); this.left = left; this.right = right; this.isMin = isMin; E = new GeoPoint(cons); // Put an extremum point in the user interface // from the very start E.setCoords(0.0, 0.0, 1.0); setInputOutput(); compute(); E.setLabel(label); }// constructor @Override public Commands getClassName() { return this.isMin ? Commands.Min : Commands.Max; } @Override protected void setInputOutput() { input = new GeoElement[3]; input[0] = function.toGeoElement(); input[1] = left.toGeoElement(); input[2] = right.toGeoElement(); setOutputLength(1); setOutput(0, E); setDependencies(); // done by AlgoElement } /** * @return resulting point */ public GeoPoint getPoint() { return E; }// getNumericalExtremum() @Override public final void compute() { double l = left.getDouble(); double r = right.getDouble(); double min = 0.0d; if (!function.toGeoElement().isDefined() || !left.isDefined() || !right.isDefined() || (right.getDouble() <= left.getDouble())) { E.setUndefined(); return; } // if input is ok? // Brent's algorithm extrFinder = kernel.getExtremumFinder(); UnivariateFunction fun = f.getUnivariateFunctionY(); min = isMin ? extrFinder.findMinimum(l, r, fun, 5.0E-8) : extrFinder.findMaximum(l, r, fun, 5.0E-8); E.setCoords(min, f.value(min), 1.0); E.updateRepaint(); }// compute() }