# Listening to Chaos

July 07, 2023

I spent the past four months based in Montréal for a semester program in Geometric Group Theory. During that time, Abdul Zalloum, Mariam Al-Hawaj and Giulio Tiozzo organized a special session at the annual meeting of the Canadian Mathematical Society and invited me to give a talk. The purpose of this post is to recap a couple of cool things I learned at the special session and to share an application of that stuff, a "sonification," if you will, as code for monome crow, a Eurorack synth module that runs Lua code.

## 1. The code

I'll lead with the crow code, since it's maybe more accessible to readers of this post coming from the orbit of lines. As I mentioned above, this code is designed to be run on monome's crow, and you can copy it into a file and upload it via druid. I recommend the following setup: set public.min = 0, public.max = 2 and output.scale({0,2,3,5,7,8,11}). Patch a clock source to crow input 1, an attenuated (bipolar) random voltage source to input 2, patch output 1 to the pitch CV of an oscillator, and patch outputs 2 through 4 (maybe slewed and/or attenuated) to timbral controls.

public { min = { -5, -5, -5, -5 } }:range(-5, 10)
public { max = { 5, 5, 5, 5 } }:range(-5, 10)
public { divisions = { 1 / 8, 1 / 8, 1 / 8, 1 / 8 } }
public { vals = { 0.48, 0.49, 0.51, 0.52 } }:range(0, 1)
param = 0
lambda = 0.25 * (1 + math.sqrt(13) + math.sqrt(2 * (math.sqrt(13) - 1)))
crit = 1 / lambda
function transform(x)
if <= crit then return 1 - lambda * x else return lambda * x - 1 end
end

function do_tick(i)
while true do
clock.sync(public.divisions[i])
public.vals[i] = transform(public.vals[i] ^ math.exp(-param)) ^ math.exp(param)
output[i].volts = public.min[i] + public.vals[i] * (public.max[i] - public.min[i])
end
end

function init()
input.mode = 'clock'
input { mode = 'stream', time = 0.2, stream = function(x) param = x end }
for i = 1, 4 do clock.run(do_tick, i) end
end


### 1.1. What the code does

The code applies a particular chaotic dynamical system, a post-critically finite interval map, to the (internal state of) the four output CVs. In smaller words, the module stores four pieces of data, public.vals, which are numbers between 0 and 1. Every tick of the $$i$$th clock (which is set with the public.divisions values), we update the $$i$$th value by applying the following transformation:

$f(x) = \begin{cases} 1 - \lambda x & 0 \le x \le \frac{1}{\lambda} \\ \lambda x - 1 & \frac{1}{\lambda} \le x \le 1, \end{cases}$

where $$\lambda$$ is the largest (real) root of the polynomial $$x^4 - x^3 - x^2 - x + 1$$, and is about $$1.7$$. The module then uses the rest of the data to transform the internal state of public.vals to the CV you can use to control your patch.

CV to input 2 applies a topological conjugacy to the map, specifically it conjugates by the map that raises everything to the power of $$e^p$$, where $$-5 \le p \le 10$$ is the CV input to input 2. Thus negative CV will tend to concentrate things towards the "top" of the range, while positive CV will push things towards the "bottom".

## 2. The math

### 2.1. Sharkovsky's theorem

One very cool theorem I learned about (possibly for the second time, but I don't really know) is Sharkovsky's Theorem, which in one formulation says

Theorem (Sharkovsky). If $$f\colon I \to I$$ is a continuous map of a closed interval with a periodic point of period $$3$$, then $$f$$ has periodic points of every period. More generally, there is an ordering $$\prec$$ on the natural numbers such that if $$f$$ has a periodic point of period $$m$$ and $$m \prec n$$, then $$f$$ has a periodic point of period $$n$$.

The order goes as follows: all the odd natural numbers greater than $$1$$ in increasing order, followed by $$2$$ times all the odd natural numbers greater than $$1$$ in increasing order, then $$4$$ times, $$8$$ times, and so on. Then the powers of $$2$$ in decreasing order, ending with $$4$$, then $$2$$, then $$1$$.

### 2.2. The map in my code

has one critical point at $$x = \frac{1}{\lambda} = 1 + \lambda + \lambda^2 - \lambda^3$$. This critical point turns out to have period $$5$$, as the following sketch attempts to illustrate. As you can see from the definition, the forward image of the critical point is $$0$$, then $$1$$, then $$\lambda - 1$$, then (the sketch lies) $$\lambda^2 - \lambda - 1$$, then $$1 + \lambda + \lambda^2 - \lambda^3 = \frac{1}{\lambda}$$. Sharkovsky's theorem says therefore that the map $$f$$ has a periodic point of every period except possibly period $$3$$. I do not know whether this map has a point of period three. I suspect it does.

### 2.3. Pseudo-Anosov maps

Another cool thing I learned about at this conference is forthcoming work of Ethan Farber and Karl Winsor given a train-track-y proof of a theorem of Boissy and Laneau, which says that within a certain hyperelliptic stratum of the moduli space of quadratic differentials on the Teichmüller space of a surface of genus $$g$$, the shortest periodic flow line under the Teichüller geodesic flow has length at least $$\frac{\log 2}{2}$$, independent of $$g$$. This stands in sharp contrast to Penner's result that $$\log$$ of the least dilatation of elements of the mapping class group tends to zero as $$g$$ increases.

Farber and Winsor's proof uses classical results in one-dimensional dynamics that say that interval maps like the one I describe above satisfy a uniform lower bound on their topological entropy of $$\frac{\log 2}{2}$$. It follows that if a pseudo-Anosov map of a surface has the same topological entropy as such an interval map, its entropy is also bounded below by $$\frac{\log 2}{2}$$. By using tight splittings, which Farber introduced in an earlier (very very cool) paper with coauthors, they show that in the situation of Boissy and Laneau's theorem, every pseudo-Anosov map (or really, the pseudo-Anosov braid to which it is closely related) may be realized as a train track map on a train track whose real edges (where the action happens) form a graph homeomorphic to an interval. Isn't that so cool?