Music 680, Fall 2005: Special Topics in Music Theory - Algorithmic Composition
Lecture 9: November 7, 2005 - minimalism (and its allies)
minimalism, concept, perception, and process
Tom Johnson Rational Melodies
and Rosalind Krauss on Sol LeWitt - how rational is rational really?
and is perception all it's cracked up to be?
Failing as a conceptual process rather than an audible one
Pauline Oliveros Alien Bog
tape loops as canon revisited; improvising within a highly limiting system
repetition and memory
Alvin Lucier Navigations for Strings
algorithm as a paring away of content to reveal concept: minimizing decisions
(LeWitt as a collaborator)
Georges Aperghis Recitations
complex interactions between simple structures and simple (but disparate) content
deterministic finite automata in Scheme
#|
statemachine.lisp
updated 2.06.2001 lcb (changes to documentation only)
translated to scheme 11.03.2005
The function state-machine implements a generic deterministic state machine.
The machine is specified with an association list. Each element of the list
should be of the form:
(state-name . ((input-1 . (target-state-a . output-a))
(input-2 . (target-state-b . output-b))
...
(input-n . (target-state-n . output-n)))
There can be any number of states and any number of inputs for each state.
(get-next-state) and (get-next-output) are associated functions which traverse
the machine data structure using (assoc). Note that there wasn't any particular
reason to make target-state and output a dotted pair -- it just seemed
convenient at the time.
state-machine takes a list of inputs and returns a list of outputs -- which can
then be applied in any way.
|#
(define (state-machine input current-state machine-structure)
(if input
(let* ((current-input (car input))
(remaining-input (cdr input))
(target-state (get-next-state current-input current-state machine-structure))
(next-output (get-next-output current-input current-state machine-structure)))
(append (list next-output)
(state-machine remaining-input target-state machine-structure)))))
(define (get-next-state input state machine-structure)
(car (cdr (assoc input (cdr (assoc state machine-structure))))))
(define (get-next-output input state machine-structure)
(cdr (cdr (assoc input (cdr (assoc state machine-structure))))))
#|
simple "does it work?" example:
(setf machine-1 '((state-1 . ((0 . (state-1 . 0))
(1 . (state-2 . 1))))
(state-2 . ((0 . (state-1 . 1))
(1 . (state-2 . 1))))))
(state-machine (list 0 0 1 1 0) 'state-1 machine-1)
|#
indeterministic finite automata
#|
probmachine.lisp: a generic nondeterministic state machine in Common Lisp
last modified 02.04.2001 lcb
translated to scheme 11.03.2005
The function state-machine implements a generic nondeterministic state machine.
The machine is specified with an association list. Each element of the list
should be of the form:
(state-name . ((input-1 . ((probability-1 . (target-state-a . output-a))
(probability-2 . (target-state-b . output-b))
...
(probability-n . (target-state-n . output-n))))
...
(input-n . ((probability-n . (target-state-n . output-n))))))
There can be any number of states, any number of inputs per state, and any
number of possible target-states per input. Note that probabilities must be
specified as fractions of one (1/5 or 0.2) and that all probabilities must
sum to one. (This is a wart -- it would be easier to modify the statemachine
on the fly if this requirement did not exist).
(select-next) is an associated function which generates a random value and tests
it against the first (state, input, probability) triple look for the next target
and output. (select-next) calls (try-next-selection) to do the recursive "hard
work" of testing additional triples if the first probability is less than the
random value generated.
(get-current-probability), (get-next-pstate), and (get-next-poutput) are associated
functions which traverse the probability-machine data structure. Notice that these
are more complicated than their companions for the state-machine (and that I've
changed the names of the state and output functions so that the deterministic
and nondeterministic machines may be run side by side). In general, this code is
not so elegant!
probability-machine takes a list of inputs and returns a list of outputs -- which can
then be applied in any way.
|#
(define (probability-machine input current-state machine-structure)
(if input
(let* ((current-input (car input))
(remaining-input (cdr input))
(next-choice (select-next current-input current-state machine-structure))
(target-state (get-next-pstate next-choice current-input current-state machine-structure))
(next-output (get-next-poutput next-choice current-input current-state machine-structure)))
(append (list next-output)
(probability-machine remaining-input target-state machine-structure)))))
(define (select-next input state machine-structure)
(let* ((random-value (random 1.0))
(first-probability (get-current-probability 0 input state machine-structure)))
(if (> random-value first-probability)
(try-another-selection random-value first-probability 1 input state machine-structure)
0)))
(define (try-another-selection random-value lower-bound index input state machine-structure)
(let* ((current-probability (+ lower-bound (get-current-probability index input state machine-structure))))
(if (> random-value current-probability)
(try-another-selection random-value current-probability (+ index 1) input state machine-structure)
index)))
(define (get-current-probability index input state machine-structure)
(car (nth index (cdr (assoc input (cdr (assoc state machine-structure)))))))
(define (get-next-pstate index input state machine-structure)
(car (cdr (nth index (cdr (assoc input (cdr (assoc state machine-structure))))))))
(define (get-next-poutput index input state machine-structure)
(cdr (cdr (nth index (cdr (assoc input (cdr (assoc state machine-structure))))))))
#|
simple "does it work?" example:
(setf pmachine-1 '((state-1 . ((0 . ((0.5 . (state-2 . 0))
(0.5 . (state-2 . 1))))
(1 . ((0.2 . (state-2 . 2))
(0.3 . (state-2 . 3))
(0.5 . (state-2 . 4))))))
(state-2 . ((0 . ((0.5 . (state-2 . 5))
(0.5 . (state-2 . 6))))
(1 . ((0.5 . (state-1 . 7))
(0.5 . (state-1 . 8))))))))
(probability-machine (list 0 0 1 1 0) 'state-1 pmachine-1)
note that multiple calls to probability-machine with the same
input, start-state and machine-structure should produce
different results; if you want the same results every time, stick with
the deterministic state machine....
|#