Now it is time to take another go at the concept language.

What is a concept? A concept represents a subset of the space of possible phrases. It describes this subset in the abstract, using mathematical rules, rather than by enumerating all of its members. Concepts represent compositionally useful patterns that appear in music. They let the AI think abstractly about music.

There are at least two things you can do with a concept. You can use it to “analyze” a phrase: to say, of an existing phrase, whether or not the phrase is an example of the concept. You can use it “synthesize” a phrase: to create a new phrase which is an example of the concept.

These operations will be more complex than that in practice, because we’ll likely need to do things like take an existing phrase and modify it to satisfy an additional concept, and somehow merge the set of concepts into an aggregate structure to check a phrase against many concepts simultaneously.

Also, we will have to evolve concepts, varying them semi-randomly and measuring them against a fitness function.

Concepts are defined using a “concept language.” This language is based on the analytic/synthetic concept language which I developed previously for natural numbers. We are simply extending that language from concepts of natural numbers to concepts of phrases.

We shall reiterate the definition of a phrase. A phrase is a set of notes, which are grouped in a topological fashion into sub-phrases. The phrase as a whole, and each sub-phrase, can satisfy various concepts. A phrase has the following components:

1. N: a set of notes, each of which has pitch, velocity, position, and duration.

2. T: a topology over N.

3. For every set t in T, a set C(t) of concepts which t satisfies. (Prune members of t which satisfy no concepts.)

4. A record of N’s minimum position; its maximum position; its duration; its minimum pitch; its maximum pitch; and its pitch range.

And we shall reiterate the definition of our concept language over natural numbers. A number concept is:

* Y or N, one of the primitive concepts.

* The sequence operation, [C1, C2, …].

* The repetition operation, (C * n).

The repetition operation has a numerical argument (n) which is defined using a restricted function language, with the following syntax:

* Numerical constants: 0, 1, 2, …

* Variables: a, b, c, …

* Operators: +, -, *, /, %.

* Conditionals: if (P1) { E1 } else if (P2) { E2 } … else { Em }.

The Ei in the conditionals are written in the function language. The Pj are written in the condition language, which consists of comparisons (=, <, <=) joined by boolean operators (and, or, xor, not). The arguments of the comparisons are written in the function language.

The variables which are available depend on the surrounding context. We shall define what variables are available in number concepts when they are part of phrase concepts.

A phrase concept consists of a score concept, a topology concept, and a set of free variable definitions. The score concept says what notes the phrase contains. The topology concept says how these are grouped into sub-phrases.

The free variables are numbers whose values are defined by number concepts. These variables can be referenced in the functions of repetition operators within the score concept and the topology concept. The free variables are named f1, f2, ….

The score concept language has the following elements:

* Note concepts: note(P, V, T, D)

* Sequencing: [C1, C2, …]

* Repetition: (C * n)

A note concept specifies a note, in the abstract. P, V, T, and D are number concepts constraining the pitch, velocity, position, and duration of the note, respectively.

The sequencing and repetition operations have slightly different meanings than they do in the number concepts. The sequencing operation means, “the notes yielded by C1, C2, … are all in the score.” The repetition operation means, “the score contains the notes yielded by repeating C n times.”

In the score, each note has a number, such that they are in a sequence counting up from zero. The notes are computed in order, from first to last. The functions in a given note concept have access to the following variables:

* f1, f2, …: The free variables.

* r1, r2, …: The index numbers in each of the repetitions that this function is inside. r1 is the innermost repetition, r2 is the one outside that, etc.^

* i: The index number of the note that this function is part of.

* p1, p2, …, p{i-1}: The pitches of all preceding notes.

* v1, v2, …, v{i-1}: The velocities of all preceding notes.

* t1, t2, …, t{i-1}: The positions of all preceding notes.

* d1, d2, …, d{i-1}: The durations of all preceding notes.

^ So for instance, the expression ([N, (Y * r1)] * 4) yields NNYNYYNYYY.

The functions in the score concept, but not in a note concept, have access to r1, r2, …, and f1, f2, ….

The topology concept language has the following elements:

* Sub-phrase concepts: sub(D, C1, C2, …)

* Sequencing: [C1, C2, …]

* Repetition: (C * n)

A sub-phrase concept specifies a subset of the notes (D), and a set of concepts (C1, C2, …) which that subset satisfies. D is a number concept which is supposed to range over [0, n); it is the set of numbers which satisfy that concept. C1, C2, … are phrase concepts.

Sequencing and repetition have the same meaning that they have in score concepts.

The variables to which functions in the topology concept have access are r1, r2, …, f1, f2, …, and n, the total number of notes in the score.

So there it is. It’s rather complex, but I think it’s complex in the right way, and that’s what counts.