“Art of Science” competition

Justin Pearson
2015-02-19

Competition organized through the Center for Science and Engineering Partnerships at the University of California at Santa Barbara.

Summary

We stream movies, send pictures to friends, and video-chat with distant loved ones, all digitally, and all without a second thought. Empowering this revolution behind the scenes is Information Theory, which provides a mathematical framework to quantify, compress, and transmit information.

This picture illustrates an important theorem in Information Theory: the Asymptotic Equipartition Property. It formalizes and generalizes the intuitive notion that if you flip a fair coin many times, you would expect about 50% heads. In the image, each square represents a string of coinflips (with 0=tails and 1=heads), with smaller squares representing longer strings of flips. Like a family tree, each square recursively generates 4 squares below it by appending one of 4 suffixes: 00, 01, 10, or 11. Each square is black, but is made transparent depending on how close to “50% heads” its corresponding string of coinflips is. We see that the vast majority of the tiny squares at the bottom are nearly 50% heads and hence transparent, allowing the underlying Swiss pasture scene to show through.

Final picture

index_1.gif

index_2.gif

How it’s made

Basic idea

Each square represents a bitstring. Every ‘child’ square inherits the parent’s bitstring with +00, +01, +10, or +11 added.

index_3.gif

index_4.gif

Define object: ‘square’

We represent a bitstring as a ‘square’ object square[ bitstring, position, color ].

This defines a bunch of functions on a ‘square’ object:

index_5.gif

Example square:

index_6.gif

index_7.gif

index_8.gif

index_9.gif

Child squares.

Each bitstring can generate 4 ‘child’ bitstrings by append 00, 01, 10, or 11. Each of these bitstrings’ squares has a position based on the parent’s.

Here is a square for the bitstring “000” at position {0,0} with color Red:

index_10.gif

index_11.gif

The possible suffixes:

index_12.gif

index_13.gif

Append each suffix to form the child squares:

index_14.gif

index_15.gif

Child squares’ positions are based on their parent position. They’re shifted over horizontally and then shifted around based on their suffix.

index_16.gif

index_17.gif

For now, child colors are just lighter versions of the parent square:

index_18.gif

index_19.gif

Create the children:

index_20.gif

index_21.gif
index_22.gif
index_23.gif
index_24.gif

The ‘graphics’ function we defined for squares is listable, so can be called on a list of children. Here is what the children look like:

index_25.gif

index_26.gif

Wrap into a function.

index_27.gif

Example use:

index_28.gif

index_29.gif
index_30.gif
index_31.gif
index_32.gif
index_33.gif
index_34.gif
index_35.gif
index_36.gif

index_37.gif

index_38.gif

index_39.gif

Set opacity as function of “how close is 1/0 fraction to 50%?”

Now we decide how opaque to make a square, as a function of its fraction of 1’s and 0’s. The idea is that an equal proportion of 1’s and 0’s should result in an clear square (Opacity 0), whereas a bitstring with all 1’s or all 0’s should be totally opaque (Opacity 1). This amounts to choosing a function that takes the bitstring, computes the fraction of 1’s, and is 0 at 0.5 (50%) and 1 at 0 (0%) and 1 (100%).

index_40.gif

index_41.gif

You can see that although the functions agree at 0, 0.5, and 1.0, they vary a little in their gray-levels in between:

index_42.gif

bitstring fabs fcos fentropy
{0,0,0,0,0} index_43.gif index_44.gif index_45.gif
{0,0,0,0,1} index_46.gif index_47.gif index_48.gif
{0,0,0,1,0} index_49.gif index_50.gif index_51.gif
{0,0,0,1,1} index_52.gif index_53.gif index_54.gif
{0,0,1,0,0} index_55.gif index_56.gif index_57.gif
{0,0,1,0,1} index_58.gif index_59.gif index_60.gif
{0,0,1,1,0} index_61.gif index_62.gif index_63.gif
{0,0,1,1,1} index_64.gif index_65.gif index_66.gif
...
{1,1,0,0,0} index_67.gif index_68.gif index_69.gif
{1,1,0,0,1} index_70.gif index_71.gif index_72.gif
{1,1,0,1,0} index_73.gif index_74.gif index_75.gif
{1,1,0,1,1} index_76.gif index_77.gif index_78.gif
{1,1,1,0,0} index_79.gif index_80.gif index_81.gif
{1,1,1,0,1} index_82.gif index_83.gif index_84.gif
{1,1,1,1,0} index_85.gif index_86.gif index_87.gif
{1,1,1,1,1} index_88.gif index_89.gif index_90.gif

Fabs is a little darker, which makes the final image look more dramatic. But Shannon’s entropy is more thematically fitting.

index_91.gif

Override the graphics function to use opacity instead of the parent’s color:

index_92.gif

index_93.gif

index_94.gif

Use as image mask

index_95.gif

index_96.gif

index_97.gif

Turn off the text of the bitstring:

index_98.gif

index_99.gif

There are a lot of squares. Each square turns into 4 squares in the next “generation”, starting with 8 squares and lasting 7 generations.

index_100.gif

index_101.gif

index_102.gif

index_103.gif

index_104.gif

index_105.gif

index_106.gif

index_107.gif

index_108.gif

index_109.gif

index_110.gif

(Now add the numbers manually (I did it in Mac’s Preview.))

Created with the Wolfram Language