Thursday, May 19, 2022

A Metaphor for Iterative Design: A Livecode Project to Demonstrate the Sierpinski Gasket

I had the good fortune to be invited by the students and faculty of the Learning Sciences and Mathematics and Science Education doctoral programs at Boğaziçi University in Turkey to participate in a seminar on design-based research (DBR). DBR has become a particularly important research approach in the field of learning, design, and technology. I decided to use my 30 minute presentation on May 11, 2022 to focus on the importance of being a designer when engaging in DBR. That is, I think it important to take on the identity of a designer. When this happens, you take on a different view of the world that will influence and support your research.

The Importance of Iteration in Design

An important aspect of all design, including DBR, is iteration. The everyday definition of iteration is simply to repeat a process or procedure. But, I prefer the mathematical definition of iteration because I think it is closer to how iteration needs to be practiced in DBR. According to Wikipedia, iteration in mathematics is "the process of iterating a function, i.e. applying a function repeatedly, using the output from one iteration as the input to the next."

The key idea here is that the output of one iteration is used (at least partially) as the input of the next iteration. I think this distinction is important for DBR because it means you revise your intervention based on what you just learned from trying it out. Implementing this principle well leads to profound insights which a designer can use in the revision process. In this process you stop, reflect, and make explicit - by writing down - what you learned. This is followed by making a conjecture that if the design is revised in such and such a way, then something better will happen the next time the design is tested (e.g. more learning, more motivation, etc.) If no improvement is found, then that conjecture is refuted and a new conjecture must be constructed. All of this is being documented along the way in DBR. These conjectures should be based in the formulation and evolution of a local or "humble" theory generated by the designer/researcher. This is the heart of the DBR process. 

A Fun Example of Iteration

Rather than just talk about this on May 11, I thought I'd show a simple mathematical example as both a literal (it really shows iteration in mathematics) and metaphorical example (within DBR) of iteration. Consider the following:

  1. On a sheet of paper, draw three dots anywhere you like. These become the vertices of a triangle. I've drawn these in red in the figure below.
  2. Pick a random spot on the paper and draw another dot. I've drawn this in black on the left side of the figure below.
  3. Pick one of the three red dots at random. Let's say the bottom-right red dot was chosen.
  4. Draw a dot at the midpoint of the black dot and the randomly chosen red dot.
  5. Repeat steps 3 and 4 using the previously drawn black dot for step 4.


What do you think you will get after lots of dots, say 1000, 5000, or 10,000?

Some people guess that the piece of paper will just get filled with dots. Others guess that the triangle formed by the red dots will just fill up. Another guess is that a circular pattern will emerge.

The actual result is quite surprising. Here is a short video of a LiveCode project I built to demonstrate this example:



(I don't know about you, but I find the erasing of the dots almost as mesmerizing as the emergence of the design.)

Here is the result drawn with 5000 small dots:

This is a special fractal known as the Sierpiński Gasket. It infinitely repeats the triangular shape. That is, if we were able to keep drawing an infinite number of dots with an ever-increasing fine point, the shape would continue to repeat itself to infinity no matter how much we zoomed in or magnified any portion of the figure. It is a most surprising result from such a simple set of rules.

But, my point in the seminar was not to teach anyone about fractals, but rather to use this example in an entertaining way to make some important points, metaphorical though they might be to process of iteration within DBR:

  • The process of iteration, though a seemingly simple idea, leads to insights of otherwise hidden patterns or deep structures for how to revise the design of a learning intervention.
  • The process of iteration can bring order and understanding to the otherwise complex activity of designing for learning.
  • Despite the apparent sense of order, there is still an infinite range of possible outcomes for our designs. That is, the experience of any one person when they use one's design will be unique for that person. 
I could probably come up with lots of more metaphorical lessons given that I never "met-a-phor I didn't like," but like all metaphors, there are limits before the metaphor breaks down. Obviously, iteration within DBR is not a mathematical function, but I hoped this example would pique the audience's curiosity and interest in the principles above.

Building the Project in LiveCode


This is actually a project I built about 30 years ago using HyperCard, the ancestor of LiveCode. My original HyperCard program harnessed the graphics tools to actually draw dots on the screen. That approach still works in LiveCode, but it is frustratingly slow. So, I redesigned the approach to copy and paste the graphical object of a black dot within a loop that follows the rules above.

Here's the LiveCode interface:


On another card titled "resources" I created two graphic objects for the two black dots used in the program (medium and small) using the oval graphic tool:

The three red dots are also drawn with the oval graphic tool and are titled "triangle1," "triangle2," and "triangle3". The "Start" button contains the code to draw the fractal:
1:  global gp,gx,gy,bx,beginy,x,y,  
2:  global varLoops, varPointName  
3:    
4:  on mouseUp  
5:    put 0 into field "counter"  
6:    put field "loops" into varLoops  
7:      
8:      
9:    wait 1 second  
10:      
11:    //Game Board  
12:    --choose first "starting point" at random   
13:    put the random of 1000 into x   
14:    put the random of 500 into y   
15:    copy graphic varPointName on card "resources" to this card  
16:    hide it  
17:      
18:    set the location of it to x,y  
19:    show it  
20:    put x into gx   
21:    put y into gy   
22:      
23:    //Play the Game  
24:    Repeat with i = 1 to varLoops  
25:     if i < 101 then  
26:       put i into field "counter"  
27:     else  
28:       if (i/100)-trunc(i/100)=0 then put i into field "counter"  
29:         
30:     end if  
31:       
32:     --choose one of the three "game points" at random   
33:     put the random of 3 into gp   
34:     if gp = 2 then   
35:       put item 1 of the location of graphic "triangle2" into bx  
36:       put item 2 of the location of graphic "triangle2" into beginy  
37:     end if   
38:       
39:     if gp = 1 then   
40:       put item 1 of the location of graphic "triangle1" into bx  
41:       put item 2 of the location of graphic "triangle1" into beginy  
42:     end if   
43:       
44:     if gp = 3 then   
45:       put item 1 of the location of graphic "triangle3" into bx  
46:       put item 2 of the location of graphic "triangle3" into beginy  
47:        
48:     end if   
49:       
50:     --draw the midpoint of the "starting point" and "game point"   
51:     put (bx+gx)/2 into x   
52:     put (beginy+gy)/2 into y   
53:     put round (x) into x   
54:     put round (y) into y   
55:     copy graphic varPointName on card "resources" to this card  
56:     set the name of it to varPointName&i  
57:     set the location of it to x,y  
58:       
59:     wait 1 ticks  
60:     --make the midpoint the new "start point" and repeat   
61:     put x into gx   
62:     put y into gy   
63:       
64:    end repeat   
65:      
66:  end mouseUp  

Here are brief explanations of key lines of code:

Lines 6 takes the number the user enters and stores this in the variable "varLoops." This determines how many dots will drawn on the screen.

Lines 11-21 draw the first black dot at a random point on the screen. The coordinates of this dot's location are stored in the local variables gx and gy.

Lines 24-64 is the repeating loop that does all of the work.

Lines 24-28 count up the number of dots drawn so far and displays this on the screen. The act of updating the field with this number can slow the whole program down considerably, so I figured out some code to only show the numbers 1-100, then increments of 100 thereafter.

Line 33 chooses a number from 1 to 3 at random. Lines 34-48 takes this random number and chooses one of the three red dots accordingly.

Lines 51-57 figure out the midpoint of the randomly chosen red dot and the last black dot and put a new black dot at that location. Line 55 copies and pastes the black dot from the card "resources" to this card, then moves it to the coordinates of the midpoint. Notice, by the way, that line 56 sets the name of this newly copied and pasted graphic object as "varPointName&i". The local variable i is chosen at the start of the repeating loop in line 24 as the counter for the loop. The "&" is the concatenation symbol which is used to "join" two sets of characters. So, the 56th dot copied and pasted will have the name "varPointName56." This is important because the "Erase" button will use these names to erase each dot in sequence.

Line 59 slows down the drawing of the dots just a little. A "tick" simply 1/60 of a second. I wanted the fractal to "reveal itself" quickly, but not too quickly, so as to keep the audience wondering what was being revealed. Slowing down the drawing of the dots further might be a good idea, depending on the audience and context.

Notice that lines 35-36, 40-41, and 45-46 refer to the location of each of the three vertices. I made each vertex "grabbable" so that I could move each anywhere I wanted on the screen. Here is the simple code embedded in each red dot that makes this possible:

on mousedown
   grab me
end mousedown

Finally, the "Erase" button simply deletes all of the graphics objects containing each of the dots. Here is the code for the button "Erase:"

1:  global varLoops, varPointName  
2:    
3:  on mouseup  
4:    put 0 into field "counter"  
5:       
6:    repeat with i = 1 to varLoops  
7:     put varPointName&i into varName  
8:     delete graphic varName  
9:    end repeat  
10:      
11:    delete graphic varPointName  
12:      
13:  end mouseup  

Lines 6-9 repeat for as many dots were drawn on the screen, except for the very first dot. Each is erased at line 8. Recall that i is the counter for the repeat statement, so if there are 100 dots, dot 56 will get erased on the 56th loop. The dot at that loop would be named "varPointName56" at that point in line 7, which is then stored in the local variable varName. Line 8 commits the deed and deletes that graphical dot. What makes the resulting animation mesmerizing, I think, is that the dots disappear in the same order in which they first appeared.

Final Thoughts


There are lots of possible "next projects" using the above code as a foundation. What would appear if I use 4, 5, or 6 vertices instead of 3? I'm sure the answer is already known and published somewhere by a mathematician and all I have to do is Google it. But, it is fun to "play mathematician" occasionally to find out for myself. I would also like to explore further the idea of using the polygon tool to create this figure. Then, I could play "connect the dots," perhaps with a random color for each line segment. That sounds like a nice blending of mathematics and art.

I end with thanking the students and faculty of the Learning Sciences and Mathematics and Science Education doctoral programs at Boğaziçi University in Turkey for inviting me to share some thoughts about design-based research. It gave me a good excuse to do some computer programming in LiveCode for fun.