Setting Random State in CLISP - lisp

So I was using the function (random 3) to make a random number between I guess 0 and 3 but every time I ran the program it outputted the number 3 every time and when I tried (random 2) it always outputs 1. I looked up what I needed to do and a different post on stack overflow said I needed to initialize the random-state which I assumed I would need to do so I put this code at the top of my program and that's when it went haywire.
(setf *random-state* (current-time))
After I put this code at the top and ran the program I first got an error that looked like this from the console.
*** - Program stack overflow. RESET
I tried running the program again and I got this super wacky error.
*** - handle_fault error2 ! address = 0x137c9500 not in [0x1a920000,0x1aaa7acc) !
SIGSEGV cannot be cured. Fault address = 0x137c9500.
GC count: 0
Space collected by GC: 0 0
Run time: 0 625000
Real time: 0 543820
GC time: 0 0
Permanently allocated: 92512 bytes.
Currently in use: 2734320 bytes.
Free space: 5 bytes.
I then got an error message from Windows that ended lisp.exe and I'm not sure what I did but when the hexadecimal came up I got freaked out. I've looked around the forums and I cannot find a solution to make my random-state code work can someone please help me.
Solution:
Instead of using (current-time) I used (make-random-state t) which works perfectly fine so my problem is fixed.

"... every time I ran the program it outputted the number 3...." Where is the code that calls (random 3)? Calling (random 3) repeatedly should return random numbers between 0 and 2, inclusive, and should never return 3. You will get the same pattern each time you start a new session unless you change the random state used by random.
random accepts an optional random state argument; you don't need to manually set the global *random-state* variable, but it can be convenient. Don't rely on things you know from other languages when learning Common Lisp (or any new language), read the documentation when you have a question. In Common Lisp a random state is not an integer; it is a random state object, and you can create a new one by calling make-random-state.
The posted code calls (current-time) and sets *random-state* to the returned value. Now, current-time is not a Common Lisp function; it is specific to Clisp, where it prints the current time as a side-effect, returning nil. After setting *random-state* to the result of calling current-time (nil), *random-state* is no longer bound to a random state object, and the call to random is no longer valid. This is probably why your program "went haywire."
Here is an example function which returns a list of random numbers between 0 and n (below n):
(defun random-list (n max)
(loop for i from 1 to n
collecting (random max)))
Running this from the REPL to create a list of 10 random numbers between 0 and 2, inclusive, and using the default random state. The first line shows the value of *random-state*:
CL-USER> *random-state*
#S(RANDOM-STATE #*0101001111100011110111001111101110101101110011101101001010001101)
CL-USER> (random-list 10 3)
(2 1 1 0 2 2 0 1 1 0)
CL-USER> (random-list 10 3)
(0 2 2 2 2 1 1 2 0 2)
CL-USER> (random-list 10 3)
(2 0 2 1 0 0 2 2 1 1)
You can see that each time the function is called, a different list is generated. This is because the random state (*random-state*) has not been reset between calls to random. Restarting the REPL and running the program again will produce exactly the same results because the random state is reset to its initial value:
CL-USER> *random-state*
#S(RANDOM-STATE #*0101001111100011110111001111101110101101110011101101001010001101)
CL-USER> (random-list 10 3)
(2 1 1 0 2 2 0 1 1 0)
CL-USER> (random-list 10 3)
(0 2 2 2 2 1 1 2 0 2)
CL-USER> (random-list 10 3)
(2 0 2 1 0 0 2 2 1 1)
Restarting again, we can try setf with make-random-state:
CL-USER> (setf *random-state* (make-random-state))
#S(RANDOM-STATE #*0101001111100011110111001111101110101101110011101101001010001101)
CL-USER> (random-list 10 3)
(2 1 1 0 2 2 0 1 1 0)
CL-USER> (random-list 10 3)
(0 2 2 2 2 1 1 2 0 2)
CL-USER> (random-list 10 3)
(2 0 2 1 0 0 2 2 1 1)
This did not work as expected! We got exactly the same results as when we used the default random state; this is because calling make-random-state with a nil argument or no argument returns a copy of the current random state object. You can call make-random-state with t as its argument to return a new random state object. Note that here Clisp has printed the random state object after the call to setf; doing the same thing in SBCL will result in a very different random state object that takes significantly more lines to print.
CL-USER> (setf *random-state* (make-random-state t))
#S(RANDOM-STATE #*0101101000011011111101010101100110010101010100001011001111101100)
CL-USER> (random-list 10 3)
(0 1 0 0 1 1 1 2 2 1)
CL-USER> (random-list 10 3)
(0 0 2 2 0 2 1 0 2 1)
CL-USER> (random-list 10 3)
(1 2 1 2 0 0 1 0 2 0)
Now you can see that *random-state* has been set to a new random state object, and the resulting lists are different from the previous lists.

Related

Use multinomial-dist to express a distribution

I have to use multinomial-dist in order to express the following distribution:
x
P(x)
red
0.5
blue
0.05
green
0.4
black
0.05
Where P(x) refers to the probability of x.
I implemented the following solution in Dr.Racket using Gamble:
(define color '("red" "blue" "green" "black"))
(define (color-probability color)
(cond
[(equal? "red") 0.5]
[(equal? "blue") 0.05]
[(equal? "green") 0.4]
[else 0.05]))
(define my-color (multinomial-dist color color-probability))
(dist-sample my-color)
But it returns an error:
make-multinomial-dist: contract violation
expected: natural?
given: '("red" "blue" "green" "black")
in: the 1st argument of
(->
natural?
(vectorof (>=/c 0))
multinomial-dist?)
I'm new in Racket and i'm still learning the basics and i don't understand what the compiler didn't like!
Thank you all!
The documentation entry for multinomial-dist, viewed from DrRacket by selecting multinomial-dist, right clicking on it, choosing Search in Help Desk for "multinomial-dist" (do this for each new function in what follows) is:
(struct multinomial-dist (n weights))
n : exact-nonnegative-integer?
weights : (vectorof (>=/c 0))
Represents a multinomial distribution. The support consists of vectors of the same length as weights representing counts of n iterated samples from the corresponding categorical distribution with weights for weights.
So a multinomial-dist can be constructed by an expression, for example, like:
(multinomial-dist 100 (vector 49 51))
(the (vector 49 51) could be the result of 100 iterated samples from a
categorical distribution with weights (vector 50 50) eg representing a coin toss)
The P(x) values in the question are categorical distribution (sometimes called
discrete distribution) weights, so start with this:
#lang racket
(require Gamble)
(define color-dist (categorical-dist (vector 0.5 0.05 0.4 0.05)))
To try this out, sample the distribution a few times in DrRacket's interaction area:
> (sample color-dist)
0
> (sample color-dist)
2
> (sample color-dist)
0
>
One way to construct iterated samples in Racket is with build-list:
(define samples (build-list 100 (lambda (x) (sample color-dist))))
> samples
'(3 0 0 2 2 0 2 0 0 0 0 0 2 0 2 0 1 2 2 2 0 2 0 2 1 0 2 0 2 0 0 0 0 2 1 0 0 2 2 2 0 1 2 0 2 2 2 0 2 0 2 2 0 0 0 0 0 0 0 0 0 2 2 0 2 2 0 0 0 2 2 2 2 1 1 0 3 0 2 2 2 0 0 2 0 2 0 0 0 0 0 2 2 2 0 0 0 2 3 0)
>
Counts of these samples are required (when needing a function, one can just type in a likely name and use "Search in Help Desk"...); try it out:
> (count (lambda (n) (= n 0)) samples)
51
>
The weights are required as a vector, so add:
(define weights
(vector (count (lambda (n) (= n 0)) samples)
(count (lambda (n) (= n 1)) samples)
(count (lambda (n) (= n 2)) samples)
(count (lambda (n) (= n 3)) samples)))
> weights
'#(51 6 40 3)
>
(After learning Scheme/Racket basics, one can eliminate the repetition in the definition above)
And then, finally,
> (multinomial-dist 100 weights)
(multinomial-dist 100 '#(51/100 3/50 2/5 3/100))
>
The distribution you're supposed to represent is not a multinomial distribution, which is a distribution over vectors.
I think you need to use discrete-dist instead.

Change just one position on array Clisp

I'm doing an algorithm that randomizes a TSP (array of citys) based on 1 TSP.
(do ((i 0 (+ i 1)))
((= i n-population))
(setf (aref population i) (shuffle TSP 100))
)
And as far as I know im filling up i positions of the array population with (shuffle TSP 100) that is beeing called each iteration, but the algorithm is setting all array positions and not just i position.
[Note. An earlier version of this answer contained a mistake which would badly alter the statistics of the shuffling: please check below for the corrected version and a note as to what the problem was.]
Given your code, slightly elaborated to turn it into a function:
(defun fill-array-with-something (population n-population TSP)
(do ((i 0 (+ i 1)))
((= i n-population))
(setf (aref population i) (shuffle TSP 100))))
Then each element of population from 0 to (1- n-population) will be set to the result of (shuffle TSP 100). There are then two possibilities:
(shuffle TSP 100) returns a fresh object from each call;
(shuffle TSP 100) returns the same object – probably TSP – from each call.
In the first case, each element of the array will have a distinct value. In the second case, all elements below n-population will have the same value.
Without knowing what your shuffle function does, here is an example of one which will give the latter behaviour:
(defun shuffle (vec n)
;; shuffle pairs of elts of VEC, N times.
(loop with max = (length vec)
repeat n
do (rotatef (aref vec (random max))
(aref vec (random max)))
finally (return vec)))
And we can test this:
> (let ((pop (make-array 10))
(tsp (vector 0 1 2 3 4 5 6 7 8 9 )))
(fill-array-with-something pop (length pop) tsp)
pop)
#(#(2 8 7 1 3 9 5 4 0 6) #(2 8 7 1 3 9 5 4 0 6) #(2 8 7 1 3 9 5 4 0 6)
#(2 8 7 1 3 9 5 4 0 6) #(2 8 7 1 3 9 5 4 0 6) #(2 8 7 1 3 9 5 4 0 6)
#(2 8 7 1 3 9 5 4 0 6) #(2 8 7 1 3 9 5 4 0 6) #(2 8 7 1 3 9 5 4 0 6)
#(2 8 7 1 3 9 5 4 0 6))
As you can see all the elements are mysteriously the same thing, which is because my shuffle simply returned its first argument, having modified it in place.
You can check this by either explicitly checking the result of shuffle, or by, for instance, using *print-circle* to see the sharing. The latter approach is pretty neat:
> (let ((*print-circle* t)
(pop (make-array 10))
(tsp (vector 0 1 2 3 4 5 6 7 8 9 )))
(fill-array-with-something pop (length pop) tsp)
(print pop)
(values))
#(#1=#(4 6 7 0 1 2 5 9 3 8) #1# #1# #1# #1# #1# #1# #1# #1# #1#)
And now it's immediately apparent what the problem is.
The solution is to make sure either that shuffle returns a fresh object, or to copy its result. With my shuffle this can be done like this:
(defun fill-array-with-something (population n-population tsp)
(do ((i 0 (+ i 1)))
((= i n-population))
(setf (aref population i) (shuffle (copy-seq TSP) 100))))
Note that a previous version of this answer had (copy-seq (shuffle TSP 100)): with my version of shuffle this is a serious mistake, as it means that the elements in population are related to each other but get increasingly shuffled as you go along. With (shuffle (copy-seq TSP) 100) each element gets the same amount of shuffling, independently.
And now
> (let ((*print-circle* t)
(pop (make-array 10))
(tsp (vector 0 1 2 3 4 5 6 7 8 9 )))
(fill-array-with-something pop (length pop) tsp)
(print pop)
(values))
#(#(8 3 4 1 6 9 2 5 0 7) #(8 6 5 1 3 0 4 2 9 7) #(5 0 4 7 1 6 9 3 2 8)
#(3 0 7 6 2 9 4 5 1 8) #(8 2 5 1 7 3 9 0 4 6) #(0 5 6 3 8 7 2 1 4 9)
#(4 1 3 7 8 0 5 2 9 6) #(6 9 1 5 0 7 4 2 3 8) #(2 7 5 8 0 9 6 3 4 1)
#(5 4 8 9 6 7 2 0 1 3))
I suspect that the problem is in OP function SHUFFLE which has not yet been shared; my suspicion is that SHUFFLE is shuffling the *TSP* array itself in place instead of creating a shuffled copy of that array. The POPULATION values are then all referencing the same shuffled *TSP* array.
To solve this problem, SHUFFLE should return a shuffled array instead of shuffling the array in place. Here is a function that performs a Fisher-Yates shuffle on a vector:
(defun shuffle-vector (vect)
"Takes a vector argument VECT and returns a shuffled vector."
(let ((result (make-array (length vect) :fill-pointer 0)))
(labels ((shuffle (v)
(if (zerop (length v))
result
(let* ((i (random (length v)))
(x (elt v i)))
(vector-push x result)
(shuffle (concatenate 'vector
(subseq v 0 i)
(subseq v (1+ i))))))))
(shuffle vect))))
Testing in the REPL:
CL-USER> (defvar *TSP* #("Village" "Town" "City" "Metropolis" "Megalopolis"))
*TSP*
CL-USER> (defvar *n-population* 5)
*N-POPULATION*
CL-USER> (defvar *population* (make-array *n-population*))
*POPULATION*
CL-USER> (dotimes (i *n-population*)
(setf (aref *population* i) (shuffle-vector *TSP*)))
NIL
CL-USER> *population*
#(#("Megalopolis" "City" "Metropolis" "Town" "Village")
#("Megalopolis" "Metropolis" "Town" "City" "Village")
#("City" "Megalopolis" "Town" "Village" "Metropolis")
#("City" "Megalopolis" "Village" "Metropolis" "Town")
#("Megalopolis" "Town" "Metropolis" "City" "Village"))

Generate random numbers until every digit [0, 9] is generated

I want to make an experiment where I create a list of many lists of randomly generated sequences that all contain every digit 0 to 9 inclusive, that is, the generation function is to generate random numbers and place them in a list of integers while there is at least 1 digit not found in the list.
The intention for the experiment is to try to make some generalizations about things like expected number # of digits in such a function, how long can a sequence get(can my program loop indefinitely and never find that last digit?), and other interesting things(for me).
I am using PERL for the experiment.
The idea seemed simple at first, I sat down, created a list, and figured I can just make a loop that runs an arbitrary amount of times (I decided to choose 100 times), which calls a function generate_sequence(input: none, output: list of numbers that contains at least 1 of every digit) and adds it to the list.
I quickly realized that I struggle cleanly specifying what it means, pragmatically, to generate a list of numbers that contains one of every digit.
My original attempt was to make a list of digits(0..9), and as I generate numbers, I would search the list for that digit if it is in the list, and remove it. This way, it would generate numbers until the list of digits "still needed" is empty. This approach seems unappealing and can involve a lot of redundant tasks such as checking whether the digit generated is in the list of digits needed every single time a number is generated...
Is there a more elegant solution to such a problem? I am really unhappy with the way I am approaching the function.
In general, I need a function F that accepts nothing, and returns a list of randomly generated numbers that contains every digit 1..9, that is, it stops as soon as every digit from 1 to 9 inclusive is generated.
Thanks ahead of time.
Well, the problem is if you 'roll randomly' you don't actually know how many iterations you're going to need - in theory it could be infinite.
If you're doing it in perl you're probably much better off using the List::Util module and shuffle - feed it a list of elements you want to shuffle.
E.g.
#!/usr/bin/env perl
use strict;
use warnings;
use List::Util qw( shuffle );
my #shuffled = shuffle ( 0..9 );
print #shuffled;
You could reproduce this quite easily, but why bother when List::Util is core as of 5.7.3
However it does sound like you're trying to generate a list, that might contain repeats, until you hit a terminate condition.
I'm not entirely sure why, but that would be best done using a hash, and counting occurences. (And terminate when your 'keys' is complete).
E.g.:
#!/usr/bin/env perl
use strict;
use warnings;
my %seen;
my #list_of_numbers;
while ( keys %seen < 10 ) {
my $gen = int rand ( 10 );
$seen{$gen}++;
push ( #list_of_numbers, $gen );
}
print #list_of_numbers;
Note - there's actually an extremely small chance of this rolling extremely long sequences, because of the nature of 'random' - it means in theory you might have a very long 'streak' of not rolling a 6.
For bonus points in %seen you have a frequency spread of your generated numbers.
A python implementation:
from random import randint
s = set(range(10))
def f():
result = []
t = set()
while 1:
n = randint(0, 9)
result.append(n)
t.add(n)
if t == s:
return result
For example:
for i in range(10):
print(len(f()))
....:
20
34
69
22
23
25
20
29
30
32
This should work (python):
import random
nums = []
while any([ i not in set(nums) for i in range(1,11)]):
nums.append(random.randrange(1, 11, 1))
or more specific to what you are trying to do:
import random
lengths = []
for i in range(1000):
nums = []
while any([ i not in set(nums) for i in set(range(1,11))]):
nums.append(random.randrange(1, 11, 1))
lengths.append(len(nums))
This approach counts the iterations needed to fill a dictionary of digits:
import random
c = 0
d = dict()
while len(d.keys()) <10:
d[random.randint(0,9)] = 1
c += 1
print c
Wrote this before you switched to just Perl...
from random import randrange
def F():
todo = set(range(10))
nums = []
while todo:
r = randrange(10)
nums.append(r)
todo.discard(r)
return nums
>>> F()
[8, 2, 2, 3, 1, 0, 3, 9, 3, 4, 7, 4, 7, 5, 0, 9, 5, 5, 6]
Another:
def F():
done = 0
nums = []
while done < 1023:
r = randrange(10)
nums.append(r)
done |= 1 << r
return nums
In Clojure, I am keeping track of both the random list and the existing values, thus avoiding a search on the growing list.
(defn random-list [ up-to ]
(loop [ n [] tries [] ]
(if (> (count n) (dec up-to))
tries
(let [i (rand-int up-to) n-tries (conj tries i)]
(if (some #{i} n )
(recur n n-tries)
(recur (conj n i) n-tries))))))
We can define similar functions:
(defn random-list-to-10 []
(random-list 10))
(random-list-to-10)
; [3 6 9 0 8 0 5 7 3 8 1 8 4 3 4 2]
We can also take only a few random elements:
(take 5 (random-list 10))
; (6 1 0 9 5)
Here is a possible Perl implementation that counts the iterations needed to fill a hash with the 10 digts:
#!/usr/bin/perl
my $count = 0;
my %dict = ();
while (scalar keys %dict < 10) {
$dict{int(rand(10))} = 1;
$count ++;
}
print $count;
(see online demo)
In clojure (though probably not the most elegant):
(loop [n []
s (set (range 0 10))]
(if (= s (set n))
n
(recur (conj n (rand-int 10)) s)))
Sample output:
user=> (loop [n [] s (set (range 0 10))] (if (= s (set n)) n (recur (conj n (rand-int 10)) s)))
[0 6 2 8 5 2 0 0 9 3 0 3 0 1 7 5 0 4]
user=> (loop [n [] s (set (range 0 10))] (if (= s (set n)) n (recur (conj n (rand-int 10)) s)))
[2 1 7 7 3 2 8 8 4 7 5 0 1 3 0 3 0 4 0 0 3 7 3 4 5 8 1 3 8 5 3 5 5 9 4 0 2 1 2 7 8 3 9 7 8 6]
user=> (loop [n [] s (set (range 0 10))] (if (= s (set n)) n (recur (conj n (rand-int 10)) s)))
[7 1 8 3 1 1 0 6 8 4 9 7 0 0 2 7 4 0 1 1 8 8 4 3 9 8 4 2 8 3 2 8 4 6 0 9 9 7 2 3 0 3 0 4 2 4 0 5]
user=> (loop [n [] s (set (range 0 10))] (if (= s (set n)) n (recur (conj n (rand-int 10)) s)))
[9 1 9 0 9 5 3 0 3 8 4 0 1 6 3 0 1 8 0 3 8 3 5 4 3 9 8 8 8 8 2 2 8 9 9 3 9 2 5 1 1 3 4 6 3 1 4 0 2 6 7]
user=> (loop [n [] s (set (range 0 10))] (if (= s (set n)) n (recur (conj n (rand-int 10)) s)))
[4 1 5 5 5 5 2 2 5 5 3 1 5 3 5 1 4 2 4 2 3 1 4 7 1 9 3 8 0 8 4 0 9 3 4 9 9 1 8 8 0 6]
user=> (loop [n [] s (set (range 0 10))] (if (= s (set n)) n (recur (conj n (rand-int 10)) s)))
[0 4 0 9 1 8 4 8 6 6 6 9 8 4 9 0 9 3 3 7 6 1 4 3 8 1 1 4 9 5 1 4 1 2]
user=>

Get pretty-printed result in Cider-evaluated expression in Emacs

I'd like to insert the result of an evaluated Clojure expression directly in my Emacs buffer, in pretty-printed form.
For example, with something like:
;; [emacs lisp]
(insert (nrepl-dict-get (nrepl-sync-request:eval "(range 30)") "value"))
I get, in the buffer of interest,
;;=>
(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29)
In the past, I've let Clojure pretty-print things for me, as so:
(nrepl-dict-get
(nrepl-sync-request:eval
(format "(clojure.core/let [x %s] (with-out-str (clojure.pprint/pprint x)))"
"(range 30)"))
"value")
;;=>
"(0\n 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9\n 10\n 11\n 12\n 13\n 14\n 15\n 16\n 17\n 18\n 19\n 20\n 21\n 22\n 23\n 24\n 25\n 26\n 27\n 28\n 29)\n"
However, the " and \n are being inserted escaped; I want them to be inserted unescaped. In other words, I want the pretty-printed result to be inserted directly without escaping quotes or newlines. This used to work in earlier versions of Cider and cider-nrepl.
Wrapping:
(nrepl-dict-get
(nrepl-sync-request:eval
(format "(clojure.core/let [x %s] (with-out-str (clojure.pprint/pprint x)))"
"(range 30)"))
"value")
in read should solve this.
I've just added this feature to lispy (it's a Paredit-style
package that uses Cider for Clojure eval):
2E will to a pretty-printed eval-and-insert, while
E will keep doing a plain one.
Here's an example (| represents point):
|(for [x (range 8)] (range x))
After E:
|(for [x (range 8)] (range x))
(() (0) (0 1) (0 1 2) (0 1 2 3) (0 1 2 3 4) (0 1 2 3 4 5) (0 1 2 3 4 5 6))
After 2E:
|(for [x (range 8)] (range x))
(()
(0)
(0 1)
(0 1 2)
(0 1 2 3)
(0 1 2 3 4)
(0 1 2 3 4 5)
(0 1 2 3 4 5 6))
Of course you can still do EjM to accomplish the same thing:
(for [x (range 8)] (range x))
|(()
(0)
(0 1)
(0 1 2)
(0 1 2 3)
(0 1 2 3 4)
(0 1 2 3 4 5)
(0 1 2 3 4 5 6))

Integer division in Common Lisp?

When I do (/ 7 2), what should I do to get the result 3? If I do (/ 7 2.0), I get 3.5, which is as expected.
(floor 7 2)
Ref: http://rosettacode.org/wiki/Basic_integer_arithmetic#Common_Lisp
See FLOOR, CEILING and TRUNCATE in ANSI Common Lisp.
Examples (see the positive and negative numbers):
CL-USER 218 > (floor -5 2)
-3
1
CL-USER 219 > (ceiling -5 2)
-2
-1
CL-USER 220 > (truncate -5 2)
-2
-1
CL-USER 221 > (floor 5 2)
2
1
CL-USER 222 > (ceiling 5 2)
3
-1
CL-USER 223 > (truncate 5 2)
2
1
Usually for division to integer TRUNCATE is used.
You can use the floor function:
(floor 7 2)
3
1
Note that it returns multiple values, and you only need the first one. Since floor returns multiple values, that can be done with multiple-value-bind as follows:
(multiple-value-bind (q r) (floor 7 2) q)
=> 3
Edit: As Rainer notes in his comment, you can just pass the result of floor as an argument if all you need is the quotient.
[1]> (floor 7 2)
3 ;
1
[2]> (+ (floor 7 2) 5)
8
[3]>
I'm leaving the reference to multiple-value-bind in the answer, since it's an important function to be familiar with.
Use the floor function. In SBCL:
* (floor (/ 7 2))
3
1/2
Two values are returned, the integer part and the fractional part.