From: Ryan Holbrook
Subject: Function evaluation problem
Date: 
Message-ID: <iBIy8.2866$c4.124029606@ounews.ou.edu>
I began writing a program to generate pictures using computer graphics 
today when I came upon a problem.

I need to generate a list of three random elements from -1 to 1 that will 
reside in a tree of functions so that the values are the same from each 
call of function-tree but remain different inside of the tree. For example:

(add* (const1) (const2))

would evaluate to 

(add* '(<float11>, <float12>, <float13>) '(<float21>, <float22>, <float23>))

and would remain so for each call to add*.

Here is what I have so far:

(defun spawn (depth)
  (if (= depth 0) (const)
    (let* ((n (length *functions*))
           (r (random n))
           (func (car (nth r *functions*)))
           (nargs (cadr (nth r *functions*)))
           (args '()))
      (cons func (dotimes (i nargs args)
                   (setf args (cons (spawn (- depth 1))
                                    args)))))))

where depth is the maximum depth allowed in the tree and *functions* is a 
list of functions and the number of arguments they take. Each argument is a 
list of three values.

Using this, I can get the following result:

(COS* (-0.2910428 0.40839672 -0.2849133))

which causes an error upon input to eval because it interprets the first 
number as a function.

I think what I need is:

(COS* '(-0.2910428 0.40839672 -0.2849133))

Changing the base case to (if (= depth 0) '(const) ... ) will cause 
different numbers to be created each call, which is not what I want.

* fun1
(NEGATE* (WRAP* (COS* (NEGATE* (YCC->RGB (CONST))))))
* (eval fun1)
(-0.9859393 -0.99917835 -0.85843766)
* (eval fun1)
(-0.9477172 -0.74720377 -0.40922257)
* 

What am I missing?

By the way, this is not homework, though it was inspired by a project in a 
CS class at Rice. http://www.owlnet.rice.edu/~comp314/02spring/Project3/ I 
thought it would be a good way to exercise my Lisping skills.

All the code I've written thus far can be found here:
http://students.ou.edu/H/Ryan.P.Holbrook-1/genetic.lisp

Thank you,
Ryan Holbrook
-- 
http://students.ou.edu/H/Ryan.P.Holbrook-1/

From: Rahul Jain
Subject: Re: Function evaluation problem
Date: 
Message-ID: <87u1pwnx0i.fsf@photino.sid.rice.edu>
Ryan Holbrook <·········@mmcable.com> writes:

> I began writing a program to generate pictures using computer graphics 
> today when I came upon a problem.

I was actually considering converting my code to CL to make it more
flexible and have it as a test app for McCLIM. :)

> I need to generate a list of three random elements from -1 to 1 that will 
> reside in a tree of functions so that the values are the same from each 
> call of function-tree but remain different inside of the tree. For example:
> 
> (add* (const1) (const2))
> 
> would evaluate to 
> 
> (add* '(<float11>, <float12>, <float13>) '(<float21>, <float22>, <float23>))

Our constant function had a parameter (actually an instance varaible,
since it was java) that was the color value to use. Ours actually
created a shade of grey, giving all 3 channels the same color, but it
would be better to give each channel a different parameter. When you
cross and mutate, you can modify and mix these color values.

You can do something similar with the random number seeds for the
noise functions.

-- 
-> -/                        - Rahul Jain -                        \- <-
-> -\  http://linux.rice.edu/~rahul -=-  ············@techie.com   /- <-
-> -/ "Structure is nothing if it is all you got. Skeletons spook  \- <-
-> -\  people if [they] try to walk around on their own. I really  /- <-
-> -/  wonder why XML does not." -- Erik Naggum, comp.lang.lisp    \- <-
|--|--------|--------------|----|-------------|------|---------|-----|-|
   (c)1996-2002, All rights reserved. Disclaimer available upon request.
From: Kenny Tilton
Subject: Re: Function evaluation problem
Date: 
Message-ID: <3CCB870C.9FD9868D@nyc.rr.com>
Ryan Holbrook wrote:
> All the code I've written thus far can be found here:
> http://students.ou.edu/H/Ryan.P.Holbrook-1/genetic.lisp

Dude! Giving us a link so /we/ can go do research to help you with
/your/ problem?! Get into your asbestos suit, fast! It is not so much
having to follow the link as having to sort through all the code to
track down the essentials. So...

What you need to do is chop down the code to the minimum but complete
code necessary to manifest the problem. Nine times out of ten that
distillation exercise will lead you to the solution. If not, at least
folks just look at a very small amount of code to help you.


> Here is what I have so far:
> 
> (defun spawn (depth)
>   (if (= depth 0) (const)
>     (let* ((n (length *functions*))
>            (r (random n))
>            (func (car (nth r *functions*)))
>            (nargs (cadr (nth r *functions*)))
>            (args '()))
>       (cons func (dotimes (i nargs args)
>                    (setf args (cons (spawn (- depth 1))
>                                     args)))))))
> 
> Using this, I can get the following result:
> 
> (COS* (-0.2910428 0.40839672 -0.2849133))
> 
> I think what I need is:
> 
> (COS* '(-0.2910428 0.40839672 -0.2849133))

Right. Food for thought:

> (eval (list 'cos* (cons 'quote (list (list 1 2 3)))))
(0.5403023 -0.41614684 -0.9899925)


-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
"Harvey has overcome not only time and space but any objections."
                                                        Elwood P. Dowd
From: Ryan Holbrook
Subject: Re: Function evaluation problem
Date: 
Message-ID: <uUVy8.2868$c4.124259422@ounews.ou.edu>
Kenny Tilton wrote:

> Ryan Holbrook wrote:
>> All the code I've written thus far can be found here:
>> http://students.ou.edu/H/Ryan.P.Holbrook-1/genetic.lisp
> 
> Dude! Giving us a link so /we/ can go do research to help you with
> /your/ problem?! Get into your asbestos suit, fast! It is not so much
> having to follow the link as having to sort through all the code to
> track down the essentials. So...
> 

You must forgive me as that was not my intention. I provided a link only 
for the curious. I attempted to include all necessary code in the body of 
the message as well as what I had tried so far and the part I was having 
trouble with. I will try to be more concise in the future.

> What you need to do is chop down the code to the minimum but complete
> code necessary to manifest the problem. Nine times out of ten that
> distillation exercise will lead you to the solution. If not, at least
> folks just look at a very small amount of code to help you.
> 
> 
>> Here is what I have so far:
>> 
>> (defun spawn (depth)
>>   (if (= depth 0) (const)
>>     (let* ((n (length *functions*))
>>            (r (random n))
>>            (func (car (nth r *functions*)))
>>            (nargs (cadr (nth r *functions*)))
>>            (args '()))
>>       (cons func (dotimes (i nargs args)
>>                    (setf args (cons (spawn (- depth 1))
>>                                     args)))))))
>> 
>> Using this, I can get the following result:
>> 
>> (COS* (-0.2910428 0.40839672 -0.2849133))
>> 
>> I think what I need is:
>> 
>> (COS* '(-0.2910428 0.40839672 -0.2849133))
> 
> Right. Food for thought:
> 
>> (eval (list 'cos* (cons 'quote (list (list 1 2 3)))))
> (0.5403023 -0.41614684 -0.9899925)
> 
> 

This provided me with what I needed. In retrospect, it was a very simple 
problem that I had become hung-up on. I was attempting to apply an 
unecessarily complex solution at the time, which I imagine would have made 
things much worse. Live and learn.

Thank you for your help.
 
Ryan Holbrook

-- 
http://students.ou.edu/H/Ryan.P.Holbrook-1/
From: Kenny Tilton
Subject: Re: Function evaluation problem
Date: 
Message-ID: <3CCC4894.80DCEB51@nyc.rr.com>
Ryan Holbrook wrote:
> 
> Kenny Tilton wrote:
> 
> > Ryan Holbrook wrote:
> >> All the code I've written thus far can be found here:
> >> http://students.ou.edu/H/Ryan.P.Holbrook-1/genetic.lisp
> >
> > Dude! Giving us a link so /we/ can go do research to help you with
> > /your/ problem?! Get into your asbestos suit, fast! It is not so much
> > having to follow the link as having to sort through all the code to
> > track down the essentials. So...
> >
> 
> You must forgive me as that was not my intention. I provided a link only
> for the curious. I attempted to include all necessary code ...

OK, in retrospect I see you acted in pretty good faith. But does
necessary mean salient or complete? I am guessing you mean salient,
since you left out const, cos*, *functions* and the invocation of spawn.

It turns out the definitions do not matter, but that became clear only
after I realized the problem output you showed came from (spawn
1)--obvious to you perhaps--and that really all it came down to was a
combination of (a) using eval to make this work and (b) the way depth
zero was handled.

Once I had it worked out, I realized you had indeed narrowed the problem
down pretty well for us: you needed (cos* '(f f f)) instead of (cos (f f
f)). 

But i think because the solution overall was a little strange, I found
myself wanting to grok the gestalt, not just how to get a quote in
there. This is where minimal would have helped. 

If you had eliminated excess stuff based on your mastery of the problem,
you might have asked:

;-----------------------------------------------
Given:

(defun random-triple ()
  (list (random 10) (random 10) (random 10)))

(defun cos* (rgb)
  "cos on each value"
  (mapcar 'cos rgb))

I want to generate:

  '(cos* (list 1 2 3)) or '(cos* '(1 2 3)) ;; but with random values, of
course

...so I can pass it to eval repeatedly and get the same result, as
opposed to '(cos* (random-triple)) which would give different results
each time eval'ed.

This does not work:

  (list 'cos* (random-triple))

That gives me: '(cos* (1 2 3)), which won't eval, I need a quote in
there.
;-----------------------------------------------

otoh, in this case maybe it is just as well you over-explained, because
a minimal example would have had us asking anyway, "what are you trying
to do? there might be a simpler way." Sounds like that is the way you
went. I would have questioned the whole approach, but I thought "maybe
this is the preferred way of coding genetic algorithms", so I kept my
mouth shut and addressed the quoting thing.

What's the new code look like?

-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
"Harvey has overcome not only time and space but any objections."
                                                        Elwood P. Dowd
From: Ryan Holbrook
Subject: Re: Function evaluation problem
Date: 
Message-ID: <Sv_y8.2870$c4.124386961@ounews.ou.edu>
Kenny Tilton wrote:
> 
> otoh, in this case maybe it is just as well you over-explained, because
> a minimal example would have had us asking anyway, "what are you trying
> to do? there might be a simpler way." Sounds like that is the way you
> went. I would have questioned the whole approach, but I thought "maybe
> this is the preferred way of coding genetic algorithms", so I kept my
> mouth shut and addressed the quoting thing.
> 

There is little I know about genetic algorithms beyond what was in the 
project description on the Rice page. This isn't much more than randomly 
generating trees of functions though, so while I'm sure there is a better 
way to do such a thing, I just haven't thought of it. 

If my code seems a little odd please understand that I am still new to the 
language and haven't picked up the proper way of doing things yet. I 
ordered PAIP through the library in the hopes that it would expose me to 
some of the idioms of Lisp and am looking forward working through it over 
the summer.

> What's the new code look like?
> 

The change was simple once I saw the example you gave. Instead of:
(...(if (= depth 0) (const)...)
for the zero case, it is:
(...(if (= depth 0) (cons 'quote (list (const)))...)

The function also checks to make sure that if const is chosen from 
*functions* it returns the appropriate expression.

Ryan Holbrook
-- 
http://students.ou.edu/H/Ryan.P.Holbrook-1/