Jump to content
Sign in to follow this  
EAIP

Posting seed value

Recommended Posts

Here is a suggestion for posting the random seed value used by a function.

When using Open Music way back in time I remember that you could "lock" a random function if you liked the result, which IMO was a great workflow feature.

Perhaps a similar thing could be achived in Opusmodus if the random seed used for a function was posted to the post window in addition to the result of the evaluation.

If you like the result of a particular seed you could then manually "lock" the randomization using the :seed keyword for the function:

 

; first try different randomizations
(setf bin-rhythm (gen-binary-rnd 5 5 2 1))
=> gen-binary-rnd :seed 752

(setf bin-rhythm (gen-binary-rnd 5 5 2 1))
=> gen-binary-rnd :seed 234

; then lock seed if you like the result
(setf bin-rhythm (gen-binary-rnd 5 5 2 1) :seed 234)

 

Perhaps if possible also with the variable name as a label to keep track of things when using several random functions in complex code:

 

(setf bin-rhythm (gen-binary-rnd 5 5 2 1))
=> bin-rhytm gen-binary-rnd :seed 37

 

I think that this or a similar approach would be a really powerful way of trying different results when working with randomization in Opusmodus.

 

Share this post


Link to post
Share on other sites

INIT-SEED can be used at the start of algorithmic compositions employing high degrees of randomness in order to create consisted results, without having to worry about supplying seed N values to all the other functions which may also use random generation.


Example:

(setf init-seed (init-seed (rnd1 :low 1 :high 99999)))

init-seed
=> 3467

This way you can recover the initial seed if needed.

Share this post


Link to post
Share on other sites

Yes, I know about init-seed, it's great for setting the overall seed in a complete score context, I guess you mean something like this:

 

(setf seed (rnd-range 1 999999))
(init-seed seed)

(setf pitch (rnd-sample 5 '(c4 e4 g4 b4)))
(setf len (rnd-sample 5 '(s e)))

(setf phrase (make-omn
              :pitch pitch
              :length len
              ))

(def-score flute
           (
            :key-signature 'chromatic
            :time-signature '(4 4)
            :tempo 112
            :layout (flute-layout 'flt)
            )

(flt
 :omn phrase
 :channel 1
 :sound 'gm
 :program 'flute
 )
)

 

If you are happy with the result you can then evaluate the seed variable and paste the posted number into the :seed keyword in one or both of the forms including random functions and thus achieve locking one or several parameters.

 

However, if you just want to evaluate for example the 3rd line over and over again untill you find a pitch line you like, this is quite a cumbersome method.

It would be great to somehow get a report of the current internal state of a single random function, or at least be able to after evaluation get the current random state or seed used. Perhaps I'm misunderstanding something crucial regarding the way the seed functionality is implemented in OM.

Share this post


Link to post
Share on other sites

Also you can't use the method above for a single line if you want to evaluate OMN Notation (cmd + 3 or ctrl + cmd + N) at the same time (or at least I don't know how to do that).

 

(setf seed (rnd-range 1 999999))
(init-seed seed)
(setf pitch (rnd-sample 5 '(c4 e4 g4 b4)))

; Select all then Evaluate and Notation (ctrl + 3)
=> Error: The value 793536 is not of the expected type list.

 

Share this post


Link to post
Share on other sites

With snippet:

(setf pitch (rnd-sample 5 '(c4 e4 g4 b4) :seed (setf seed (rnd-range 1 999999))))
=> (g4 e4 c4 b4 b4)

Test:

(rnd-sample 5 '(c4 e4 g4 b4) :seed 675029)
=> (g4 e4 c4 b4 b4)

 

Note: ctrl-3 is not for displaying numbers.

 

Share this post


Link to post
Share on other sites

Yes, of course, but in terms of workflow it isn't very practical, I think you would like to keep things separated when trying out individual lines of a score.

Is there a way of somehow getting the seed or random state used under the hood when not providing one yourself?

 

(Sorry about the typo, I meant to write Cmd + 3 in the code example, as in "OMN notation")

Share this post


Link to post
Share on other sites

If we use random function without a seed then there is nothing to retrieve because there is no seed of any kind in random pick at any stage. 

Share this post


Link to post
Share on other sites
(defun doseed (&key seed)
        (setf seed (init-seed (rnd-range 1 999999)))
        (print seed))


(rnd-sample 5 '(c4 e4 g4 b4) :seed (doseed))

This works for me.

 

/Lasse

Share this post


Link to post
Share on other sites

Thanks for the patience and clarification Janusz, and thanks also to Lasse for the useful lisp function. :smile:

Share this post


Link to post
Share on other sites

> Perhaps if possible also with the variable name as a label to keep track of things when using several random functions in complex code:

(setf bin-rhythm (gen-binary-rnd 5 5 2 1))
=> bin-rhytm gen-binary-rnd :seed 37

This should be easy to do with a revision of the macro do-verbose, but as users, we have no access to its definition to change it. (The macro would check the value of the variable seed in its environment.)

Side remark: If anyone revises do-verbose, it would be highly welcome to be able to switch off its effect altogether, because Common Lisp offers much better builtin debugging facilities than what this macro does. 

 

Anyway, here is an easy workaround for your particular situation. 

 

(setf bin-rhythm (gen-binary-rnd 5 5 2 1 :seed (print 123)))
; printed: 123 gen-binary-rnd
=> ((0 0 1 0 0) (1 0 1 0 1) (0 1 1 0 1) (1 1 0 1 1) (0 1 0 1 1))


See also the discussion in the thread linked below.

 

Best,

Torsten

 

 

Share this post


Link to post
Share on other sites
On 3/31/2018 at 7:40 PM, lviklund said:

(defun doseed (&key seed)
        (setf seed (init-seed (rnd-range 1 999999)))
        (print seed))


(rnd-sample 5 '(c4 e4 g4 b4) :seed (doseed))

This works for me.

 

/Lasse

 

Below is a more secure variant of that function, which does not overwrite the seeds of all other functions. Calling init-seed is not needed here... 

 

I avoided using do in the function name, as functions/macros named such are by convention looping constructs. 

 

Best,

Torsten

 

(defun mk-seed (&optional seed)
  "Generates a random seed value, prints and returns it. Useful for exploring different results of random processes, but then keeping a found solution.

  Args:
  - seed (int): optionally fixes generated seed.

  Examples:

  (rnd-sample 3 '(c4 d4 e4) :seed (mk-seed))
  ; 405621 rnd-sample
  => (c4 e4 d4) 

  (rnd-sample 3 '(c4 d4 e4) :seed (mk-seed 13))
  ; 13 rnd-sample
  => (e4 d4 e4) 
  "
  (print (if seed seed (rnd-range 1 999999))))

 

Share this post


Link to post
Share on other sites
1 hour ago, torstenanders said:

Calling init-seed is not needed here... 

 

I guess it is, if you want to see what value init-seed gives you... :thinking:. Or...?

That was anyway why I did it this way.

 

Anyway, thank you again for your interesting knowledge.

 

/lasse

Share this post


Link to post
Share on other sites

Citing the documentation: "INIT-SEED can be used at the start of algorithmic compositions employing high degrees of randomness in order to create consisted results, without having to worry about supplying seed N values to all the other functions which may also use random generation."

 

The function init-seed does not give you any new value actually (it just returns its argument), but in the background as a side-effect initialises the random generation of all Opusmodus random functions, so that their results are consistent on re-evaluation. 

 

Just try removing it in your function :)

 

Besides, programs that reduce any changes to global states and side effects to the absolute minimum (which is most often using no stateful programming at all) are more easy to maintain and expand. Your little function introduces two stateful operations that are not needed here: setf (better use a local let) and init-seed. (This is even more important when writing concurrent code, which can be necessary when doing real-time stuff, e.g., when you have multiple processes running in parallel changing the same global variables without further precaution.)   

 

Best,

Torsten

Share this post


Link to post
Share on other sites

I found a way to display an internal seed if seed is nil (random process).

 

Example without a seed (each time different result):

(rnd-number 12 1 10)
? rnd-number :seed 678732
=> (10 6 10 6 1 9 5 6 10 2 4 2)

 

Now the same function with a manually "lock" using the :seed

(rnd-number 12 1 10 :seed 678732)
? rnd-number :seed 678732
=> (10 6 10 6 1 9 5 6 10 2 4 2)

 

(rnd-pick '((q c4 p d4 ff s a4 stacc) (s e4 app q c5 d5 pp)))
? rnd-pick :seed 598336
=> (q c4 p d4 ff s a4 stacc)

 

Screen Shot 2018-04-07 at 10.30.22.png

 

I hope everybody will be happy with the solution  :-)

To add this functionality to all the functions using random seed will take some time to do.

Hopefully tomorrow :-)

 

Best,

Janusz

Share this post


Link to post
Share on other sites

Thanks Janusz, this was exactly was what I was wishing for, really useful I think!

Share this post


Link to post
Share on other sites
Quote

Is it possible to implement the same when doing audition-omn-snippet?

This would very complicated. The snippet (section) is rewritten from all kind of selections into def-score.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

×