= #JxnPortable\docs\programmer_examples\commons_math_examples\JxnUnivariateFunction_SolverOptimizer~Demo.jxn

#import org.apache.commons.math3.analysis.solvers
#import org.apache.commons.math3.optimization.GoalType
#import org.apache.commons.math3.optimization.univariate.BrentOptimizer

bs = @BisectionSolver()
bo = @BrentOptimizer( 0.000_001, 0.000_001)
maxEval = 200


fP3 = @JxnUnivariateFunction( $this, "($x+3)$x($x-3);" )
bs.solve( maxEval, fP3, -10., 10., -8. )  ! f(x) = 0 at x =
bs.solve( maxEval, fP3, -10., 10.,  8. )

result = bo.optimize( maxEval, fP3, GoalType.MAXIMIZE, -4., 4., 0. )
result.getPoint()  ! maximum at x =
result.getValue()  ! maximim value:

result = bo.optimize( maxEval, fP3, GoalType.MINIMIZE, -4., 4., 0. )
result.getPoint()  ! minimum at x =
result.getValue()  ! minimum value:


fCS = @JxnUnivariateFunction( $this, "cos $x;" )
bs.solve( maxEval, fCS, 0., 10., 0. )
$ / PI

fSN = @JxnUnivariateFunction( $this, "Math.sin $x;" )
! <= explicit 'Math.' speeds up
result = bo.optimize( maxEval, fSN, GoalType.MAXIMIZE, -10., 10., -8. )
result.getPoint() / PI
result.getValue()

result = bo.optimize( maxEval, fSN, GoalType.MINIMIZE, -10., 10.,  8. )
result.getPoint() / PI
result.getValue()


! plot result depending on the starting point xi:
xi = 0.94 x.toArray()

bs = @BrentSolver()
start = System.currentTimeMillis()
! the following call takes some time (minimize the command window to speed up):
pf1 = plot( xi / PI, sin xi, bs.solve( maxEval, fSN, -10., 10., xi ) / PI ).setXYLabels( "xi / \#960;", "y / \#960;")
pf1.setPlotFrameTitle( "solution y of sin(y) = 0 for starting points xi" )
( System.currentTimeMillis() - start ) / 1000

start = System.currentTimeMillis()
pf2 = plot( xi / PI, sin xi, bo.optimize( maxEval, fSN, GoalType.MAXIMIZE, -10., 10., xi ).getPoint() / PI )
pf2.setPlotFrameTitle( "find y with maximum sin(y) for starting points xi").setXYLabels( "xi / \#960;", "y / \#960;")
! -3.183 (instead of -3.5) for xi/PI < -2.94 <= finds local maximum at left end of interval (-3.183 = -10/PI)
( System.currentTimeMillis() - start ) / 1000