I have started a new job, and with it comes a new language: Ironpython. Thankfully a good language :D
Before starting I got to grips with Python on the whole, but that was only a week's worth of learning. Now I'm writing actual code.
I've been charged with writing an algorithm that finds the best input parameter to collect data with.
The basic algorithm is (as I've been instructed):
Set the input parameter to a good guess
Start collecting data
When data is available stop collecting find the highest point
If the point before this (i.e. for the previous parameter value) was higher and the point before that was lower then we've found the max otherwise the input parameter is increased by the initial guess.
goto 2
If the max is found then the min needs to be found. To do this the algorithm carries on increasing the input, but by 1/10 of the max, until the current point is greater than the previous point and the point before that is also greater.
Once the min is found then the algorithm stops.
Currently I have a simplified data generator outputting the sin of the input, so that I know that the min value should be PI and the max value should be PI/2
The main Python code looks like this (don't worry, this is just for my edification, I don't write real code like this):
import sys
sys.path.append(r"F:\Programming Source\C#\PythonHelp\PythonHelp\bin\Debug")
import clr
clr.AddReferenceToFile("PythonHelpClasses.dll")
import PythonHelpClasses
from PHCStruct import Helper
from System import Math
helper = Helper()
def run():
b = PythonHelpClasses.Executor()
a = PythonHelpClasses.HasAnEvent()
b.Input = 0.0
helper.__init__()
def AnEventHandler(e):
b.Stop()
h = helper
h.lastLastVal, h.lastVal, h.currentVal = h.lastVal, h.currentVal, e.Number
if h.lastLastVal < h.lastVal and h.currentVal < h.lastVal and h.NotPast90:
h.NotPast90 = False
h.bestInput = h.lastInput
inputInc = 0.0
if h.NotPast90:
inputInc = Math.PI/10.0
else:
inputInc = h.bestInput/10.0
if h.lastLastVal > h.lastVal and h.currentVal > h.lastVal and h.NotPast180:
h.NotPast180 = False
if h.NotPast180:
h.lastInput, b.Input = b.Input, b.Input + inputInc
b.Start(a)
else:
print "Best input:", h.bestInput
print "Last input:", h.lastInput
b.Stop()
a.AnEvent += AnEventHandler
b.Start(a)
PHCStruct.py:
class Helper():
def __init__(self):
self.currentVal = 0
self.lastVal = 0
self.lastLastVal = 0
self.NotPast90 = True
self.NotPast180 = True
self.bestInput = 0
self.lastInput = 0
PythonHelpClasses has two small classes I wrote in C# before I realised how to do it in Ironpython.
Executor runs a delegate asynchronously while it's running member is true. The important code:
public void Start(HasAnEvent hae)
{
running = true;
RunDelegate r = new RunDelegate(hae.UpdateNumber);
AsyncCallback ac = new AsyncCallback(UpdateDone);
IAsyncResult ar = r.BeginInvoke(Input, ac, null);
}
public void Stop()
{
running = false;
}
public void UpdateDone(IAsyncResult ar)
{
RunDelegate r = (RunDelegate)((AsyncResult)ar).AsyncDelegate;
r.EndInvoke(ar);
if (running)
{
AsyncCallback ac = new AsyncCallback(UpdateDone);
IAsyncResult ar2 = r.BeginInvoke(Input, ac, null);
}
}
HasAnEvent has a function that generates the sin of its input and fires an event with that result as its argument. i.e.:
public void UpdateNumber(double val)
{
AnEventArgs e = new AnEventArgs(Math.Sin(val));
System.Threading.Thread.Sleep(1000);
if (null != AnEvent)
{
AnEvent(e);
}
}
The sleep is in there just to slow things down a bit.
The problem I am getting is that the algorithm is not coming up with the best input being PI/2 and the final input being PI, but I can't see why. Also the best and final inputs are different each time I run the programme. Can anyone see why? Also when the algorithm terminates the best and final inputs are printed to the screen multiple times, not just once. Can someone explain why?