Demonstration 4 provided the practical component for Chapter 6: “Conditional Selection I — Markov Chains” of my unpublished textbook on composing programs. It illustrates how Markov Chains can be employed to compose a piece of music. Markov chains are consistent with the selection pattern of G.M. Koenig's Project Two, to the extent that there is a sequence of events such as phrases or notes, and that even attributes such as duration and pitch are being drawn from a supply. In Markov's scenario, supply elements are called “states”, and there is an additional aspect of conditionality: The likelihood of selecting state i for event j depends on the state previously selected for event j-1.
A Markov transition matrix is a two-dimensional array of probabilities:
Where N is the number of states, where each pi,j ≥ 0, and where for each row of the matrix (that is, for each j),
The fact that each row sums to unity is why I use the term probability in favor of the less restrictive term weight.
Expanding from a one-dimensional distribution to a two-dimensional transition matrix adds a full order of complexity into the designer's task. Exercising control over the succession of choices means that among the multiplicity of available sequences, the matrix designer can use high probabilities to emphasize some sequences, use low probabilities to deemphasize other sequences, or use null probabilities to exclude still other sequences entirely.
Another feature is the ability to control the propensity for the chain to linger on one specific state. Such control is exercised through waiting probabilities, which are positioned along the diagonal of the matrix. Thus the waiting probability pi,i controls how often state i transitions to itself. Each waiting probability has an associated waiting count Ci,i. This waiting count gives the average number of times the chain will locally repeat state i before moving away. The two values pi,i and Ci,i have the following relationship:
The structure of Demonstration 4 is simpler than in previous demonstrations because there is no level of organization intervening between the individual notes and the piece as a whole. Each of the four attributes characterizing a unit — duration, articulation, register, and degree — proceeds independently of the others.
Articulation is controlled through a percentage indicating the probability that an iteration of the composing loop will produce a note instead of a rest. There are four values: 10%, 17%, 29%, 50%. The waiting counts in each case will be 91%, which means the chain will linger upon one of these values for an average of
notes and rests before transitioning to a different state.
Transitions to new states emphasize the sequence 10% → 50% → 17% → 29% → 10%. On-track transitions have 5% probability, while off-track transitions have 2% probability. Since
the requirement of summing to unity is confirmed.
There are four average durations available to any note. Expressed in sixteenths, the averages for notes are D1=2, D2=3, D3=5, and D4=9; the averages for rests are half as much: 1, 1.5, 2.5, and 4.5.
Thus we can make each average duration persist over a whole-note duration by selecting Ci,i so that Ci,iDi=16, or
|pi,i = 1 - ||Di
The waiting probabilities for all four values have been calculated so that the chain lingers on each value for approximately two measures before moving on to a new value. Table 1 illustrates how the average length over which a value holds sway may be computed as the product of the average duration itself and of the waiting count, which is the reciprocal of the waiting probability. We should recognize that control over how long an average duration holds sway is very loose, since both the waiting count and the individual durations are random. The number of random mechanisms affecting a process is often known as the degrees of freedom. The more degrees of freedom, the more the individual states of the process deviate from the norm.
Figure 1 graphs the evolutions of average duration, articulation, and register in Demonstration 4. The rates of these evolutions directly result from the waiting probabilities controlling how individual states transition to themselves. Since waiting probabilities for articulations are high in Figure 1 (a), articulations evolve very slowly; by contrast, the waiting probabilities associated with the unison in Figure 1 (d)) are consistently zero, so no two consecutive notes repeat the same degree.
Also pertinent to the medium-term behavior are the stationary probabilities shown in Figures 2 (a-c). Stationary probabilities1 appear for average duration in Figure 2 (a); for articulation in Figure 2 (b); and for register in Figure 2 (c).
|Figure 2 (a): Stationary probabilities for average durations.||Figure 2 (b): Stationary probabilities for articulations.||Figure 2 (c): Stationary probabilities for registers.|
The Markov chains controlling average note durations, articulations, and registers produced graphs which lingered for some numbers loop iterations before transitioning to the next value. This happened because the waiting probabilities — those located along the diagonal of the matrix — were nonzero. By comparison, the process used to decide whether a loop iteration should generate a note or a rest prescribes total certainty that a rest will never transition away to another rest but only a level of probability that a note will transition to another note. The process is in fact a two-state Markov chain, where the probability of transitioning from a note to another note is determined by the articulation percentage described above.
Note durations are selected according to the negative exponential distribution, but applying John Myhill's procedure to limit the ratio of maximum to minimum durations to 8.
The progression of chromatic degrees reduces from a second-order Markov chain of chromatic positions to a first-order Markov chain of chromatic intervals. Figure 3 details the relative weights associated with each consecutive pair of intervals. Though intervals range from 1 to 11 (unisons are excluded), ‘wrap-around’ arithmetic keeps the current degree always within the range from 1 to 12.
The approach just described resembles the INTERVAL feature of G.M. Koenig's Project Two. Such matrices will be frequently employed in subsequent Demonstrations, where they will be designated as stylistic matrices. The current matrix acts both to enforce absolute constraints and to promote desirable tendencies, in this case to encourage a consistently dissonant style.
The language of constraints is inherently dogmatic. Practices are either correct or incorrect. Just bear in mind that the dogma applies only to this particular composing program. These Demonstrations in no way suggest that adherence to universal standards will improve the quality of your music. Artusi lost that argument to Monteverdi centuries ago. Rather, the take-away lesson from these Demonstrations is that if there certain patterns run contrary to the style your program is intended to generate, and if you are able to formulate constraints forbidding these patterns, then there are methods which you can use to enforce such constraints, that some methods are more efficient than others, and that where these methods occur in the decision-making logic can also make a difference.
A transcription of the musical product appears in Figure 5.
The explanations to follow focus variously on four attributes of musical texture: average note duration, articulation, register, and chromatic degree. The purpose is to tease out the strands of code that affect a particular attribute, and thus to illustrate Markov chaining in play. The explanations are peppered with line numbers, but you are are by no means expected to chase down every line of code. Rather, you should follow through with line numbers only when you have a specific question that the narrative is not answering.
The source code for program
DEMO4 appears as Listing 1.
This program implements the one-tiered structure described above as a single
composing loop (lines 56-81) which iterates for each note or rest and which continues until sixty measures
of 2/4 time have been filled out (line 78). At the beginning of an iteration, the program chooses an average duration, expressed
in sixteenths, and a rest/play probability. Line 59 executes a random branch to determine whether to compose a note
(lines 61-69) or a rest (lines 71-75).
Variables and arrays pertaining to average duration of notes (equivalently, average tempo) have names ending with
The average duration of rests is half as large.
MAVGfixes the number of average note durations at 4 (line 5); line 16 populates specific values into array
VALAVG. The integer variable
IDXAVGtracks the current state of the average-duration chain.
TRNAVGwith transition probabilities. Stationary probabilities derived from this matrix are shown in Figure 2 (a).
IDXAVGwith uniform randomness by calling the library function
MARKOVexecutes the next transition in the average-duration chain, reselecting
IDXAVGand then dereferencing
VALAVG(IDXAVG)into the variable
AVGDUR. The values selected for
AVGDURare shown in the uppermost graph of Figure 1.
AVGDURbecomes the first argument in a call to the library function RANX. Rest durations are generated similarly in line 72, except that here the value of
AVGDURis scaled down by half.
Variables and arrays pertaining to articulation have names ending with
Articulations are expressed as the probability that a rhythmic unit will serve as a rest.
MARTfixes the number of articulation-probabilities at 4 (line 5); line 11 populates specific values into array
VALART. The integer variable
IDXARTtracks the current state of the articulation chain.
TRNARTwith transition probabilities. Stationary probabilities derived from this matrix are shown in Figure 2 (b).
IDXARTwith uniform randomness by calling the library function
MARKOVexecutes the next transition in the articulation chain, reselecting
IDXARTand then dereferencing
VALART(IDXART)into the variable
ARTIC. The values selected for
ARTICare shown in the central graph of Figure 1.
ARTIC.2. In line 59, the variable
RESTdetermines whether row 1 (Rest) or row 2 (Note) of Table 1 applies. If
RESTis true, then the choice becomes determinate: generate a note. Otherwise, a call to function
SUCCESsettles the note/rest decision through a Bernoulli trial.
Variables and arrays pertaining to register have names ending with
Registers are expressed as the lowest position in a twelve-semitone gamut.
MREGfixes the number of registral gamuts at 7 (line 5); line 33 populates specific values into array
VALREG. The integer variable
IDXREGtracks the current state of the register chain.
TRNREGwith transition probabilities. Stationary probabilities derived from this matrix are shown in Figure 2 (c).
IDXREGwith uniform randomness by calling the library function
MARKOVexecutes the next transition in the register chain, reselecting
IDXREGand then dereferencing
VALREG(IDXREG)into the variable
IREG. The values selected for
IREGare shown in the lowermost graph of Figure 1. This variable is consumed in line 80 with a the call to
Variables and arrays pertaining to chromatic intervals have names ending with
Chromatic intervals are expressed as integers from 1 (minor second) to 11 (major seventh).
MTVLfixes the number of intervals at 11 (line 5); line 21 populates specific values into array
VALTVL. This redundant setup is done for compatibility with subroutine
MARKOV. The integer variable
IDXTVLtracks the current state of the register chain.
TRNTVLwith the transition probabilities detailed in Figure 4. Stationary probabilities derived from this matrix are shown in Figure 2 (d).
IDXTVLwith uniform randomness by calling the library function
MARKOVexecutes the next transition in the register chain, reselecting
IDXTVLand then dereferencing
VALTVL(IDXTVL)into the variable
ITVL. This variable is wrapped into the range from 1 to 11 and consumed in line 80 with a the call to
The loop completes in line 80 with a call to subroutine
WNOTE. This version of
WNOTE takes as argument #5
the note/rest flag
REST is true, register (argument #3) and degree (argument #4) are ignored.
REST is false,
WNOTE uses the library subroutine
IDEG in the register indicated by
The library subroutine
MARKOV3 implements random
selection with probabilities conditioned by previous choices.
MARKOV require five arguments:
MARKOVselects a state (supply value) and returns the value in this location.
VALUE— Supply of state values. Duplicate values are not permitted.
VALUEmust be an array whose dimension in the calling program is
NUM(argument #5 below).
TRANS— Array of transition probabilities. Trans must be a real array in the calling program whose duration is
NUM. The probabilities must be non-negative, and every row of the array must sum to unity.
IDX— Index to previously-selected state.
IDXmust be an integer in the calling program. This argument provides the element of feedback. Since FORTRAN passes subroutine arguments by address, each call to
IDXto the newly selected state.
NUM— Number of states.
NUMmust be an integer in the calling program.
MARKOV first calculates a row offset
I=NUM*(IDX-1). This means that the
upcoming state selection will be governed by the probabilities
TRANS(I+NUM). According to the restrictions given for array
TRANS above, these probabilities
must sum to unity.
MARKOV then uses the methods of the library subroutine
SELECT to select the new value of
IDX, where the
R= is unscaled.
MARKOV completes by setting
MARKOVis presented in Automated Composition, Chapter 6, pp. 6-16 to 6-18.
|© Charles Ames||Original Text: 1984-11-01||Page created: 2017-03-12||Last updated: 2017-03-12|