Why isn't my algorithm for find the biggest and smallest inputs working?

Posted by Matt Ellen on Stack Overflow See other posts from Stack Overflow or by Matt Ellen
Published on 2010-05-15T09:19:48Z Indexed on 2010/05/15 9:24 UTC
Read the original article Hit count: 332

Filed under:
|
|

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):

  1. Set the input parameter to a good guess
  2. Start collecting data
  3. When data is available stop collecting find the highest point
  4. 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.
  5. 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?

© Stack Overflow or respective owner

Related posts about ironpython

Related posts about beginner