My not very clever code

Chapter: Magic Square
...Section: My not very clever code

MagicSquareSolver.java is the workhorse.

        private static final int SIZE = 3;
        private int numCells = SIZE * SIZE;
These specify that it will be a 3*3 magic square. You can try larger ones (but good luck waiting for a result if you're bigger than 3!).
        private Stack candidates;
        private PartialSquare candidate;
PartialSquare is another class we'll define later. candidates is a collection of PartialSquares under consideration.

The other instance variables

        private Panel myPanel;           // for graphic display
        private JButton[] myButtons;     // for graphic display
are for use in displaying our progress in the applet window and have nothing to do with the backtracking.

        public void init() {
                candidates = new Stack();
                candidate = new PartialSquare(SIZE);
                candidates.add(candidate);
                setUpDisplay();
                (new Thread(this)).start();
        }
I'm initializing a stack of candidates. I'm making the first candidate (an empty square) and adding it to the pool. setUpDisplay gets the graphic display ready to roll, but has nothing to do with the backtracking. I'm running this whole thing as a thread, because later in the lab we're going to want to be able to control the speed of our animations; so we may as well start in the way we intend to continue!

Now we get to the working part of backtracking:

        public void run() {
                while (!candidates.isEmpty()) {
                        candidate = candidates.pop();
                        updateDisplay();
                        if (candidate.success()) break;
                        for (PartialSquare ps : candidate.successors())
                                candidates.push(ps);
                }
                System.out.println("done");
        }
I've put the while loop in a run method for the sake of animation. Otherwise the loop could just as easily reside in the init method. Compare this with the pseudocode backtracking algorithm I gave in class and at the start of this lab. I'll repeat it here for convenience: Start by placing the in node into your pool;
Node thisCandidate;
while (!pool.isEmpty()) {
  thisCandidate = pool.remove();
  mark thisCandidate as "already visited"
  if (thisCandidate is the target node) {
     declare success and print information;
  }
  else {
     add the unmarked successors of thisCandidate to the pool;
  }
}
Apart from the changes in variable names, and the lack of "marking", you should see that I've basically implemented the backtracking algorithm.

Q. 7
Why don't you need the marking?


The rest of the code in MagicSquareSolver is to do with maintaining the animation and you can study it at your leisure.

While MagicSquareSolver is pretty standard generic backtracking code, the other class we need is very specific to the Magic Square problem. Download your own copy of my PartialSquare.java.

        private static int size;  // size of magic square. 
        private static int numCells; // number of cells in magic square (size*size)
There's an interesting reason I made these static. Because each partial square gives rise to many successors, all of the same size, I can specify the dimensions once and for all in the class specification. There is no need for the individual partial square objects to have their own copy of these variables.
        private Vector myNums;
myNums is where we keep the numbers in a partial square. For example the numbers in the Vector for

9 6 2
6 0 0
0 0 0
are 9, 6, 2 and 6 again.

Q. 8
Why not make the vector myNums static also? That would save a lot of memory would it not?


The public constructor

        public PartialSquare(int theSize) {
                // create an empty partial square 
                size = theSize;
                numCells = size * size;
                myNums = new Vector();
        }
is straightforward. But how often do you see a private constructor:
        private PartialSquare(Vector itsNums) {
                myNums = new Vector();
                for (int i:itsNums) extend(i);
        }
I made it private because it's only ever called within this class, and I don't want anybody else calling it. It basically returns a clone of this current PartialSquare for use in deriving all of its successors. As discussed in the question earlier, I clone new copies of partial squares and add cells to them, leaving the parent unmodified, to ease the backtracking process: Instead of having to write code to undo the changes wrought since the last choice point, I just revert to the partial square that originally existed at that choice point. All the changes occurred in nodes that are now available for recycling by the garbage collector.

We need to be able to generate all the successors of q partial square:

        public Vector successors() {
                Vector retValue = new Vector();
                if (myNums.size() != numCells)  { // generate all the successors
                        PartialSquare aCandidate;
                        for (int i=1; i
 and you'll see how I make several copies, each with exactly one additional
 cell but with a different value
 in that new cell.

It is important to note, as you prepare to do Exercise 1, that this is the only method that the clever programmer (you) needs to make different from mine. If you skipped this paragraph you will regret it when you start on Exercise 1.

The longest method is boolean success(). It needs to check:

  • that the square is full (myNums.size() == numCells)
  • That there are no repeated integers in the complete square. I do this via (new TreeSet<Integer>(myNums)).size() == myNums.size(). See how that works?
  • That all the rows have the same sum as the first row.
  • That all the columns have the same sum as the first row.
  • That each diagonal has the same sum as the first row.
        private void extend(int i) {  // Note private!
                myNums.add(i);  
        }
        
        public Vector getNums() { // so the caller can display me
                return myNums;
        }
extend is a help method for constructing the successors of a partial square by extending it with one number. getNums is used by the other class for obtaining the current candidate's numbers for displaying in the animation.


rhyspj@gwu.edu