[comp.lang.lisp] random numbers in Franzlisp

amres@uvaee.ee.virginia.EDU (Ali Minai) (08/07/87)

I have been using Franzlisp to develop a program that involves genetic
algorithms. Much to my dismay, I have found that the (random) function
is far from random, and generates the identical list of numbers every
time I run the program. Is there some way I can give it a "seed", or
perhaps get around the problem in some other way? I could conceivably
use something like the (time) function, but surely, there must be a
better way. Thanks in advance.

                                Ali Minai,
                                EE, University of Virginia,

                                amres@uvaee.ee.virginia.edu

jeff@aiva.ed.ac.uk (Jeff Dalton) (08/10/87)

In article <179@uvaee.ee.virginia.EDU> amres@uvaee.ee.virginia.EDU
(Ali Minai) writes:
>I have been using Franzlisp to develop a program that involves genetic
>algorithms. Much to my dismay, I have found that the (random) function
>is far from random, and generates the identical list of numbers every
>time I run the program. 

I can answer this only for Opus 38 on VAX 4.2BSD and Sun OS 2&3.  And,
because of the extra delay to and from Europe, my answer may look silly
by the time it arrives (but I'll try anyway).  Apologies also to those
who already know all this.

As you've noticed, there are two problems: (1) Because Franz calls the
C library routine rand, the random numbers are not very random: in fact,
the low-order bits are cyclic.  (2) The same sequence is produced each
time.

These problems can be solved by using random and srandom, again from
the C library.  Ch 8 of the Franz Manual describes one way to do this.
Random could be extracted from the C library and loaded as a foreign
function of discipline "integer-function".  Srandom would have to be
called by an interface routine (written in C) that passed the int
argument in the form expected by srandom.  The interface routine would
be given discipline "function" or "subroutine".

The problem with this method is that functions with these disciplines
can't be called directly by compiled code (as in sstatus translink on):
they have to be called through the interpreter so that the arguments
will be put on the C stack.  A built-in function would be faster.

It is possible, however, to define C functions that are "just like"
built-in ones, load them, and give them discipline lambda.  Compiled
code can then call them directly.

Here is the code for more-random and set-more-random which call random and
srandom respectively:

--- more-random.c ----------------------------------------------------
/* Franz interface to random and srandom */

/* Jeff Dalton, AIAI, University of Edinburgh */

#include "global.h"

extern long random();
extern srandom();

lispval
Mrandom()
{
    chkarg(0, "more-random");
    return(inewint(random()));
}

lispval
sMrandom()
{
    chkarg(1, "set-more-random");
    if (TYPE(lbot->val) != INT)
	errorh1(Vermisc,"set-more-random: arg must be int",
		nil,FALSE,0,lbot->val);
    else
    {
	srandom(lbot->val->i);
	return(nil);
    }
}
----------------------------------------------------------------------

Once compiled, this file would be loaded by something like:
   (if (not (getd 'more-random))
       then (cfasl "more-random.o" '_Mrandom 'more-random 'lambda "")
            (getaddress '_sMrandom 'set-more-random 'lambda))

Unfortunately, compiling the code is not necessarily straightforward:
you have to use the same method used to compile the Franz interpreter
and on the VAX this is rather complex:

--- VAX Makefile -----------------------------------------------------
LispRoot = /usr/src/local/lisp
Liszt = liszt
CFLAGS = -O -I${LispRoot}/franz/h
CCOM = /lib/ccom
COPT = /lib/c2
FIXMASK = ${LispRoot}/franz/vax/fixmask
FIXPBIG = ${LispRoot}/franz/vax/fixpbig.e

.c.o:
	cc -E ${CFLAGS} $< | ${CCOM} | ${FIXMASK} | sed -f ${FIXPBIG} \
		| ${COPT} | as -o $@
----------------------------------------------------------------------

The -I option tells the compiler where to find global.h.  Fixmask
and fixpbig improve the C compiler's by putting some values in global
registers, etc.  This doesn't normally happen on the Sun and so the
.c.o method is simply:

.c.o:
        cc -c ${CFLAGS} $*.c

Jeff Dalton,                          JANET: J.Dalton@uk.ac.ed             
AI Applications Institute,            ARPA:  J.Dalton%uk.ac.ed@cs.ucl.ac.uk
Edinburgh University.                 UUCP:  ...!ukc!ed.ac.uk!J.Dalton