Lab 2.0 – Simple Fredkin

 

Goals:

    w Implement Fredkin cellular automaton

    w Learn the importance of detective work in using today’s software.

 

__1. Begin a new project and place a 13 x 13 flexgrid on its form.

          w Begin a new VB project, naming and saving it and its form.

          w Place a flexgrid, fgdCA, onto the form.

          w Give it 13 rows and columns, no fixed rows or columns and no scroll

              bars.

          w And give the GridLines property a value of 0.

 

__2. Write the initialization code.

          w Where should the main initialization be done?

          w Declare a constant, Gridsize, and give it a value of 4000.

          w Declare a module level variable, Numrows.

          w Do you also need a variable, Numcols?  Why, or why not?

          w Set the height and the width of the grid to be Gridsize.

          w Declare a local variable, cellsize, of type Single, and set it to

             be Gridsize/Numrows.

          w Use the value of cellsize to set the size of the cells in the grid.

          w For future use, declare a module level array, hue, 0 to 4, of type Long.

          w Initialize hue with the code below.  Where should this code be

             placed?

                         hue(0) = vbWhite

                         hue(1) = vbBlue

                         hue(2) = vbRed

                         hue(3) = vbGreen

                         hue(4) = vbYellow

                         hue(5) = vbMagenta

 

__3. Put on your Sherlock Holmes hat.

          w Test out this portion of your program to see if it is working correctly.

          w Begin by temporarily resetting Gridlines to 1, so that you can see

             whether all cells are the correct size.

          w Run the program.  What do you see?

          w To determine whether the “crowding” along the right edge and

             bottom is due to room taken up by gridlines, do the following:

   ?v Reset the Gridlines property of fgdCA to 0.

   ?v Place the code below into your initialization section, following the

                    initialization of the array, hue.

                         Dim ro As Integer

                         Dim col As Integer

                         Dim color As Integer

                         For ro = 0 To 12

                          fgdCA.Row = ro

                          For col = 0 To 12

                           fgdCA.col = col

                           color = (color + 1) Mod 6

                           fgdCA.CellBackColor = hue(color)

                          Next col

                         Next ro

   ?v Run the program.  Do you see any improvement to the crowding

                    problem?

          w Now, to find out what actually happened . . .

   ?v Place the code below into your initialization section.

                    Note: You should already have some of that code.  Place the

                    rest around it, as appropriate.

 cellsize = Gridsize / NumRows

 Debug.Print "Cellsize = "; cellsize

 Debug.Print "Total gridwidth = "; cellsize * NumRows

 For i = 0 To NumRows - 1

  fgdCA.ColWidth(i) = cellsize

  Debug.Print "Cellsize = "; cellsize

  Debug.Print "Actual column width in twips = "; fgdCA.ColWidth(i)

  fgdCA.RowHeight(i) = cellsize

  Debug.Print "Actual row height in twips = "; fgdCA.RowHeight(i)

 Next i

   ?v Run the program again, and study the results presented in the

                    Immediate Window.  What do we learn from that?

 

__4. Some more sleuthing.

          w Declare cellsize of type Integer, instead of Single.

          w Substitute the code below for the code you have.

                        cellsize = Int(Gridsize / NumRows)

                         fgdCA.Height = cellsize * NumRows

                         fgdCA.Width = cellsize * NumRows

          w Run the program.  Look at the grid.  Does it look like we’ve solved

             the problem?

          w Now study the results in the Immediate Window.  Does it still look

             like we’ve solved the problem?

          w Start up a brand new VB project.  Place a grid, fgdTest, on it, giving

             it only 1 row and 1 column.

          w Give your program the code below.

Option Explicit

 Const Gridsize = 500

 

Private Sub Form_Load()

Dim cellsize As Integer

Dim i As Integer

 fgdTest.Height = Gridsize

 fgdTest.Width = Gridsize

 Open App.Path & "\TestResults" For Output As #1

 For i = 1 To 500

  cellsize = i

  fgdTest.ColWidth(0) = cellsize

  Print #1, "Cellsize = "; cellsize

  Print #1, "Actual column width in twips = "; fgdTest.ColWidth(0)

  fgdTest.RowHeight(0) = cellsize

  Print #1, "Actual row height in twips = "; fgdTest.RowHeight(0)

 Next i

End Sub

          w Examine the TestResults file.  What have we learned?

          w Can you think of a way to get an exact match between the size of

              the individual cells and the overall size of the grid?

 

__5. An unresolved mystery.

          w Close the second project.  Go back to the first one.

          w Add the function below to your code.  Was is its purpose?

Public Function Round15(ByVal num As Integer) As Integer

 num = Round(num / 15)

 Round15 = num * 15

End Function

          w Write code to test this function.  Verify that it works for all integers

             between 1 and 100.

          w Use this function to calculate the size of the grid exactly, using the

              code below.

 cellsize = Round15(Int(Gridsize / NumRows))

 fgdCA.Height = cellsize * NumRows

 fgdCA.Width = cellsize * NumRows

          w Run the program again.  Has the problem been resolved?

          w At this point we have, at least temporarily, exhausted our resources. 

             And we invoke the Kenny Rodgers Principle of programming - “You

             have to know when to hold them, you have to know when to fold

             them, you have to know when to walk away and when to run.”

          w Having reached the point of diminishing returns, we leave the

             resolution to another day.

 

__6. So, what do we do now?

          w Since we have no analytical way to determine the exact height and

             width required by our cells, we do some experimentation and find

             that the following code works fairly well for grids ranging from 1 x 1

             to 39 x 39.

                         cellsize = Round15(Int(Gridsize / NumRows))

                         fgdCA.Height = cellsize * NumRows + NumRows * Log(NumRows)

                         fgdCA.Width = cellsize * NumRows + NumRows * Log(NumRows)

 

__7. It’s time to move on.

          w Change the number of rows and columns of fgdCA to 39.

          w Add the following module level declarations:

   ?v casize as type Integer.

   ?v Two dimensional arrays old and nu as type Integer, with indices

                    running from 0 to 38.

   ?v Why do you think the second one was given the name nu instead

                    of the name new?

          w Place a command button, cmdRunIt, onto the form.  Give it the code

             below.

                        Private Sub cmdRunIt_Click()

                        Dim row As Integer

                        Dim col As Integer

                         casize = 39

                         For row = 0 To casize - 1

                          For col = 0 To casize - 1

                           old(row, col) = 1

                          Next col

                         Next row

                         Call DisplayCA

                        End Sub

          w Add the general procedure, DisplayCA, to your program and give it

             the code below.

                        Public Sub DisplayCA()

                        Dim row As Integer

                        Dim col As Integer

                         For row = 0 To casize - 1

                          fgdCA.row = row

                          For col = 0 To casize - 1

                           fgdCA.col = col

                           fgdCA.CellBackColor = hue(old(row, col))

                          Next col

                         Next row

                        End Sub

          w Now run the program.  Notice how slow it runs.

          w Do speed it up, do the following:

   ?v Place the line of code below just after the declarations.

                         fgdCA.Visible = False

   ?v Place the line of code below just after the For loops.

                         fgdCA.Visible = True

          w Run the program again.  What is the difference?

 

__8. And now implement the Fredkin rule for cellular automata.

          w In the code for cmdRunIt, change the line in the midst of the nested

             for loops to read:

                    old(row, col) = 0

          w Following the nested for loops, add these 3 lines of code.

                         old(casize \ 2, casize \ 2) = 1

                         old(casize \ 2 + 1, casize \ 2) = 1

                         old(casize \ 2, casize \ 2 + 1) = 1

          w Run the program.  What has changed?

          w Add a general procedure, DoOneIter, and give it this code:

                        Public Sub DoOneIter()

                        Dim row As Integer

                        Dim col As Integer

                         For row = 1 To NumRows - 2

                          For col = 1 To NumRows - 2

                           nu(row, col) = MakeTran(row, col)

                          Next col

                         Next row

                         For row = 1 To NumRows - 2

                          For col = 1 To NumRows - 2

                           old(row, col) = nu(row, col)

                          Next col

                         Next row

                        End Sub

          w Add a function, MakeTran, and give it this code:

Public Function MakeTran(ByVal row As Integer, ByVal col As Integer) As Integer

Dim sum As Integer

 sum = old(row - 1, col) + old(row + 1, col) + old(row, col - 1) + old(row, col + 1)

 MakeTran = sum Mod 2

End Function

          w And now add these lines of code to the very end of cmdRunIt_Click:

                         For iter = 1 To 10

                          Call DoOneIter

                          Call DisplayCA

                         Next iter

          w Run the program.  Do you see 10 iterations appearing on the screen?

 

__9. Some final touches.

          w VB is not allowing the individual iterations to be displayed.  So we

              must force its hand.

          w Look up the DoEvents function in the online Help.

          w Place this line of code at the very end of DisplayCA.

                         DoEvents

          w Run the program again.  Do you see 10 iterations appearing on the screen?  Why do think this line of code makes a difference?

          w Finally, change the number of iterations to 100 and run the program

              again.  Do you see any repetition of patterns?

          w Change the values of NumRows and casize to 25.  Run the program.

          w Experiment with a number of different values.

          w Experiment also with various sizes for the grid and the form.  What

             size do you like the best?