Message Boards Message Boards

Schmidt arrangements: Mobius transformation application

Posted 3 years ago

MODERATORS' NOTE: related resource function is available here.

Schmidt Arrangements


The beautiful picture above is a Schmidt Arrangement : the orbit of R under a specific group of Mobius transformations.

The Mobius transformation of a complex z is f(z)=(az+b)/(cz+d)

If the coefficients a,b,c and d are restricted to the integers of a complex quadratic field then we get a Schmidt Arrangement.

To each circle of a Schmidt Arrangement, you can associate a center c, curvature b, and co-curvature b' (curvature of the circle you get with an inversion).

A circle is part of the Schmidt Arrangement if b b'==c conjugate(c) -1

Said differently, if (c conjugate(c) -1) / b is a multiple of Sqrt(d) where Sqrt(d) is used to generate the quadratic field.

The algorithm is iterating on curvature (up to a max) and on position (between some bounds) and checking if the above divisibility condition is true. If it is, the circle is part of the arrangement.

For more details, download the attached Notebook because I can't write maths here.

Schmidt Arrangements were studied by Kate Stange and Daniel E. Martin and a Sage notebook implementation can be found on their websites:

I have tried to implement a function simple to use for generating a few Schmidt Arrangements. All bugs are mine and not from the original authors. For the known limitations, please download the notebook.

The simplest way to start :


and you'll get:


There is an option to control the color:

schmidtArrangements[-1, "color" -> {"colourpool", {1, 0}}] 

enter image description here

The function is providing some palette and a color function which is using the curvature and some scaling. The list {a,b} (here 1,0) are the scaling factors.

The color index is given by (c * a + b) mod n
n is the number of colors in the palette. c is the curvature of the circle expressed as an integer.
You can force a different n if it is smaller than the palette length. Let's use 2 instead of 4. It is the first value of the list when the list has 3 elements:

schmidtArrangements[-1, "color" -> {"colourpool", {2, 1, 0}}] 

enter image description here

We can also use a standard palette using ColorData. Currently only gradient. The value will be 1 for the max curvature used to compute the picture. The circle can be replaced by disks. And the transparency can increase or decrease with the curvature:

schmidtArrangements[-1, "circle" -> False,  "color" -> ColorData["SolarColors"], Background -> White, 
 "transparency" -> "decreasing"] 

enter image description here

It is also possible to use a Radial gradient:

schmidtArrangements[-1, "circle" -> False, 
 "color" -> {"gradient", {"colourpool", {1, 2}}, {"colourpool", {1, 1}}}] 


By default, we keep only a Circle in the plane to display the picture. But we can also restrict to a plane. The option "filter" is used for this. Below example is also showing the option "cmax" for the maximum curvature to test.

schmidtArrangements[-1, "cmax" -> 40, 
 "color" -> {"coloursaul", {2, 1, 1}},  "transparency" -> "increasing", 
 "filter" -> Rectangle[{-0.1, -0.1}, {1.1, 1.1}], PlotRange -> {{0, 1}, {0, 1}}] 

enter image description here

The function is supporting same options as Graphics. In below picture, the root is different (-2) and the background is black:

schmidtArrangements[-2, "cmax" -> 40,  "color" -> {"coloursaul", {2, 1, 1}},
 "transparency" -> "increasing",  "filter" -> Rectangle[{-0.1, -0.1}, {1.1, Sqrt[2.0] + 0.1}],
 PlotRange -> {{0, 1}, {0, Sqrt[2.0]}}, Background -> Black] 

enter image description here

Now, let' s play with - 3.

schmidtArrangements[-3, "cmin" -> 0, "cmax" -> 10,  "color" -> {"coloursaul", {2, 1, 1}},
 "transparency" -> "increasing",  "filter" -> Rectangle[{-2.1, -Sqrt[3.0] - 0.1}, {2.1, 2*Sqrt[3.0] + 0.1}], 
 PlotRange -> {{-2, 2}, {0, Sqrt[3.0]}}, ImageSize -> Large]

enter image description here

The following example will take more time to compute the result because it is scanning a bigger region of the plane to detect circles member of the Schmidt Arrangement. It is specified with the option "xmax" and "ymax" which in addition to "cmax" are controlling where the search for new circles is taking place.

schmidtArrangements[-15, "cmin" -> 0, "cmax" -> 20,  "color" -> {"coloursaul", {1, 0}}, "xmax" -> 10.0, "ymax" -> 2.0,
 "filter" -> Rectangle[{-0.1, -0.1}, {5.1, Sqrt[15.0] + 0.1}], "circle" -> False, PlotRange -> {{0, 5}, {0, Sqrt[15.0]/2.0}}, 
 ImageSize -> Large]

enter image description here

When a function is taking time, it is useful to be able to dissociate the part searching for the circles (long) and the styling part (quick). Because generally we'd like to be able to experiment with styling and regenerate different pictures.

The option "precompute" is used for this.

Note that option "cmax" is reused in the display part (with an additional "cmin"). The display part is filtering the circles and displaying only the one which are in a given geometric area and between two curvature boundaries.

For the color palettes, it is this other "cmax" which is used.

Separating the computation from the styling is allowing to use a different "cmax" for both.
In the example below we remove circle which are contained in another circle. It is the option "containment".

precomputed = schmidtArrangements[-1, "cmax" -> 100, "precompute" -> True]; 

schmidtArrangements[precomputed, "circle" -> False, "containment" -> False, "cmin" -> 2, 
"cmax" -> 100,  "color" -> {"colour24", {1, 4}}]

enter image description here

Another long example because the cmax is quite high.

precomputed2 = 
  schmidtArrangements[-1, "cmax" -> 100, "precompute" -> True]; 

schmidtArrangements[precomputed2, "circle" -> False, 
 "color" -> {"colour92", {0, 0}}, "transparency" -> 0.5, "cmin" -> 2, "cmax" -> 100]

enter image description here

Since we have precomputed the circles, now we can quickly regenerate a new picture with a different styling.

schmidtArrangements[precomputed2, "circle" -> False, 
 "color" -> {"coloura", {0, 0}}, "transparency" -> 0.5, "cmin" -> 2, "cmax" -> 100]


schmidtArrangements[precomputed2, "circle" -> False,   "color" -> {"colour5", {1, 0}},
 "transparency" -> "increasing", "cmin" -> 0, "cmax" -> 75,  "filter" -> Circle[{0., 0.5}, Sqrt[0.25]]]

enter image description here

We can also overlay two pictures generated with different styling from the same computation.

 schmidtArrangements[precomputed2, "circle" -> False, "color" -> Black,
  "transparency" -> 0.5, "cmin" -> 0, "cmax" -> 35, "filter" -> Circle[{0., 0.5}, Sqrt[0.25]]],
 schmidtArrangements[precomputed2,  "color" -> {"colournightlife", {2, 0}},
  "transparency" -> 0.5, "cmin" -> 0, "cmax" -> 35,  "filter" -> Circle[{0., 0.5}, Sqrt[0.25]]]

enter image description here

Another example with - 3

schmidtArrangements[-3, "cmin" -> 0, "cmax" -> 30, "color" -> Blue,
 "filter" -> Rectangle[{-0.1, -0.1}, {1.1, 1.1}], 
 PlotRange -> {{-0.1, 1}, {0, 1.0}}, ImageSize -> Large]

enter image description here

The same example but with a bigger value of cmax.

pre = schmidtArrangements[-3, "cmax" -> 100, "precompute" -> True];

Now you can play with different palettes and filter with different cmax values.

 schmidtArrangements[pre, "cmin" -> 0, "cmax" -> nb, 
  "color" -> ColorData[s], "transparency" -> "increasing",
  "filter" -> Rectangle[{-0.1, -0.1}, {1.1, 1.1}], 
  PlotRange -> {{-0.1, 1}, {0, 1.0}}, ImageSize -> Large, 
  Background -> Black],
 {s, ColorData["Gradients"]}, {{nb, 30}, {10, 20, 30, 40}}

A nice final example :

img = schmidtArrangements[pre, "cmin" -> 0, "cmax" -> 30, 
  "color" -> ColorData["BrightBands"], "transparency" -> "increasing",
  "filter" -> Rectangle[{-0.1, -0.1}, {1.1, 1.1}], 
  PlotRange -> {{-0.1, 1}, {0, 1.0}}, ImageSize -> Large, 
  Background -> Black]


10 Replies

Christophe, Please consider packaging this as a function and submitting it to the Wolfram Function Repository.

File > New > Repository Item > Function Repository Item will bring up a template notebook with all the formatting tools and submission capability.

POSTED BY: Daniel Lichtblau

Ok. I’ll do it as soon as I am a little less busy.

Congratulations! Your post was highlighted on the Wolfram's official social media channels. Thank you for your contribution. We are looking forward to your future posts.

POSTED BY: Moderation Team

Here is an update to the notebook. It is a bit faster and with some bug corrections.


Scrolling down this is mildly...hypnotic.

POSTED BY: Daniel Lichtblau

enter image description here -- you have earned Featured Contributor Badge enter image description here Your exceptional post has been selected for our editorial column Staff Picks and Your Profile is now distinguished by a Featured Contributor Badge and is displayed on the Featured Contributor Board. Thank you!

POSTED BY: Moderation Team

Thank you !

Love the colourpool one! I think it will feel like a retro poster if some grainy texture is added to the gradient regions.

POSTED BY: Silvia Hao

Good idea :-)

Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
or Discard

Group Abstract Group Abstract