# This works to optimise for the last value of models runs.
# The model is run for a set period (SetExecuteFor) and a parameter is set 
# to a given value at the start of the run.
# 

# this script depends on math::optimize and uses the Plotchart for a
# simple plot of the function output for a regular series of inputs
# the easiest way to get these package is probably to install ActiveTcl
# http://www.activestate.com/products/activetcl/

# MODIFY FOR YOUR CASE
lappend auto_path {c:/program files/tcl/lib}; # where the extra libraries live
package require math::optimize
package require Plotchart

# Simulistics provided package
package require SimileAutoObj; # not actually needed in Windows using SimileScript.exe


# Create a Tcl object/command (modelWin) with which to control that instance of Simile
similescript::ModelWindow modelWin

# Tell Simile not to use the single window Model Run Environment
# We are not going to use any helper anyway here.
# We then load the model and build it using C++
modelWin UseMRE false
# MODIFY FOR YOUR CASE      MUST BE FORWARD SLASHES EVEN UNDER WINDOWS!
modelWin Open "C:/Documents and Settings/Jonathan/My Documents/Program Files/ExampleModels/Optimise/MathOptimize/mathOptimize.sml"
modelWin Run



# Create a runControl command/object with which to control
# (as you might expect) the run control.
similescript::RunControl runControl

runControl SetExecuteFor 1
runControl SetTimeStep 1 1

# Create proc to run model and return value of variable to optimize
proc func {x} {
    runControl SetValue /x $x
    runControl Reset
    runControl Start
    # multiply the value by -1 as we want the maximum value using a minimising optimiser
    set y [runControl GetValue /y]
    return [expr -1*$y]
}

package require Plotchart

toplevel .t
canvas .t.c -background white -width 400 -height 200
pack   .t.c -fill both

#
# Create the plot with its x- and y-axes
#
set s [::Plotchart::createXYPlot .t.c {0.0 20.0 2.0} {0.0 0.05 0.01}]
$s title "Shape of function we are evaluating"

# evalute the model output for a range of input values ()
# by plotting the output value for a series of input values
# # multiply the value by -1 to get the original sign
puts "Function shape"
for {set i 0} {$i<=20} {incr i } {
    set x [expr {$i/2.0}]
    set y [expr {-1*[func $x]}]
    puts "$x $y"
    $s plot series1 $x $y
}

#puts "Maximum at(negative y value): [::math::optimize::min_bound_1d func 0.0 10.0]"
set results [::math::optimize::min_bound_1d func 0.0 10.0 -trace on]
set x [lindex $results 0]
set y [expr {-1*[lindex $results 1]}]
puts #####################################################
puts {::math::optimize::min_bound_1d func 0.0 10.0}
puts "Maximum at: $x = $y"
puts #####################################################
puts ""

set results [::math::optimize::min_unbound_1d func 0.2 0.7 -trace on]
set x [lindex $results 0]
set y [expr {-1*[lindex $results 1]}]
puts {::math::optimize::min_unbound_1d func 0.2 0.7}
puts #####################################################
puts "Maximum at: $x = $y"
puts #####################################################
