Print

Print


Heh. That's amusing, because I was just sitting here thinking about a
scheme like this. Still, well-explained, and well-architected. I think
it's very interesting that you've separated the types of data passed
around completely from the types specified in the parameters of the
functions themselves (in the parameter files). Very interesting stuff.
Thanks!

On Sun, Aug 24, 2008 at 11:37 PM, Sean Luke <[log in to unmask]> wrote:
> On Aug 24, 2008, at 10:26 PM, Andrew Wagner wrote:
>
>> I'm trying to do something similar to this code:
>>   public void eval(final EvolutionState state,
>>                    final int thread,
>>                    final GPData input,
>>                    final ADFStack stack,
>>                    final GPIndividual individual,
>>                    final Problem problem)
>>       {
>>       double result;
>>       DoubleData rd = ((DoubleData)(input));
>>
>>       children[0].eval(state,thread,input,stack,individual,problem);
>>       result = rd.x;
>>
>>       children[1].eval(state,thread,input,stack,individual,problem);
>>       rd.x = result + rd.x;
>>       }
>>   }
>>
>> This comes from tutorial 4, and it's simple enough, taking two nodes
>> that return doubles, adding them together, and putting a new double in
>> the input. In my case, however, I'm actually returning a different
>> type. I have a BoolData class which encapsulates a Boolean value. How
>> would you modify this code, for example, to return a BoolData which
>> indicated whether the result was greater than 100?  The input is final,
>> so I can't replace the reference with a new GPData. What am I missing?
>
> Sure you can replace it.  A final parameter just means that it won't change
> locally.  It's an unnecessary optimization ECJ made in the past (because
> Hotspot ignores 'final' in local variables) and we can get rid of it.
>
> But that's not what you want to do.  The idea here is that ECJ trees
> typically use a SINGLE GPData object and pass it throughout the tree.  It's
> handed from parent to child (when the parent calls eval).  It's where the
> child is expected to add stuff to be returned to the parent.  You probably
> don't want to make multiple GPData objects, it'd be extremely expensive at
> runtime.  Do this:
>
> 1. Create a subclass of GPData which holds a slot for every kind of return
> value you might need, like this maybe:
>
>        public class FooData extends GPData
>                { public double d; public boolean b; }
>
> 2. Let's say you're trying to take two doubles, compare them and return a
> boolean if they're equal.  You'd do:
>
>   public void eval(...)
>       {
>       double result;
>       FooData rd = ((FooData)(input));
>
>       children[0].eval(state,thread,input,stack,individual,problem);
>       result = rd.d;
>
>       children[1].eval(state,thread,input,stack,individual,problem);
>       rd.b = (rd.d == result);
>       rd.d = 0;  // heck, why not zero it out
>       }
>
> 3.  Now you'd declare FooData as your data object in your parameter file.
>
> 4.  If your parent KNOWS that the child will return a boolean, it can just
> look in the boolean slot (b) and we're done.  If the parent can accept
> multiple kinds of return types from children (perhaps you're using set
> typing), then it's best to change this to specify the type of object
> presently stored, something like this:
>
>        public class FooData extends GPData
>                {
>                public double d;
>                public boolean b;
>                public int type;
>                public static final int TYPE_DOUBLE = 0;
>                public static final int TYPE_BOOLEAN = 1;
>                }
>
> 5. Then you'd do something like:
>
>   public void eval(...)
>       {
>       double result;
>       FooData rd = ((FooData)(input));
>
>       children[0].eval(state,thread,input,stack,individual,problem);
>       result = rd.d;
>
>       children[1].eval(state,thread,input,stack,individual,problem);
>       rd.b = (rd.d == result);
>       rd.d = 0;  // heck, why not zero it out
>       rd.type = FooData.TYPE_BOOLEAN;  // so my parent knows I'm giving him
> a boolean
>       }
>
> Sean
>