title: 8-Puzzle Solution executes infinitely
body: <p>I am looking for a solution to <a href="http://www.cs.princeton.edu/courses/archive/fall12/cos226/assignments/8puzzle.html" rel="nofollow noreferrer">8-puzzle</a> problem using the <code>A* Algorithm</code>. I found <a href="http://code.google.com/p/a-star-eight-puzzle/source/browse/trunk/+a-star-eight-puzzle/420proj1/src/?r=10" rel="nofollow noreferrer"><strong>this</strong></a> project on the internet.  Please see the files - <code>proj1</code> and <code>EightPuzzle</code>. The proj1 contains the entry point for the program(the <code>main()</code> function) and EightPuzzle describes a particular state of the puzzle. Each state is an object of the 8-puzzle. <br>I feel that there is nothing wrong in the logic.  But it loops forever for these two inputs that I have tried : <code>{8,2,7,5,1,6,3,0,4}</code> and <code>{3,1,6,8,4,5,7,2,0}</code>. Both of them are valid input states. What is wrong with the code?<br></p>
  <hr />
  <p><strong>Note</strong></p>
  <ul>
  <li>For better viewing copy the code in a Notepad++ or some other text
  editor(which has the capability to recognize java source file)
  because there are lot of comments in the code.</li>
  <li>Since A* requires a heuristic, they have provided the option of using
  manhattan distance and a heuristic that calculates the number of
  misplaced tiles. And to ensure that the best heuristic is executed
  first, they have implemented a <code>PriorityQueue</code>. The <code>compareTo()</code>
  function is implemented in the <code>EightPuzzle</code> class.</li>
  <li>The input to the program can be changed by changing the value of <code>p1d</code> in the <code>main()</code> function of <code>proj1</code> class.</li>
  <li>The reason I am telling that there exists solution for the two my above inputs is because the applet <a href="http://www.brian-borowski.com/Software/Puzzle/" rel="nofollow noreferrer">here</a> solves them. Please ensure that you select 8-puzzle from the options in the applet.
  <br><br>
  <strong>EDIT1</strong><br>I gave this input <code>{0,5,7,6,8,1,2,4,3}</code>. It took about <code>10 seconds</code> and gave a result with <strong>26 moves</strong>. But the applet gave a result with <code>24 moves</code> in <code>0.0001 seconds</code> with <code>A*</code>.
  <br><br>
  <strong>EDIT2</strong><br>
  While debugging I noticed that as nodes are expanded, the new nodes, after sometime, all have a heuristic - <code>f_n</code> as <code>11</code> or <code>12</code>. They never seem to decrease. So after sometime all the states in the <code>PriorityQueue(openset)</code> have a heuristic of 11 or 12. So there is not much to choose from, to which node to expand. As the least is 11 and the highest is 12. Is this normal?<br><br>
  <strong>EDIT3</strong><br>
  This is the snippet(in <strong>proj1-astar()</strong>) where the infinite looping happening. <strong>openset</strong> is the PriorityQueue containing unexpanded nodes and <strong>closedset</strong> is the LinkedList containing expanded nodes.<br></li>
  </ul>
  <p>while(openset.size() &gt; 0){</p>
  <pre><code>                    EightPuzzle x = openset.peek();
  
  
                      if(x.mapEquals(goal))
                      {
  
                               Stack&lt;EightPuzzle&gt; toDisplay = reconstruct(x);
                               System.out.println(&quot;Printing solution... &quot;);
                               System.out.println(start.toString());
                               print(toDisplay);
                               return;
                               
                      }          
                      closedset.add(openset.poll());
                      LinkedList &lt;EightPuzzle&gt; neighbor = x.getChildren();              
                      while(neighbor.size() &gt; 0)
                      {
                              EightPuzzle y = neighbor.removeFirst();
                              if(closedset.contains(y)){
                                      continue;
                              }          
                              if(!closedset.contains(y)){
                                      openset.add(y);
                              }              
                      }
                 
              }
  </code></pre>
  <p><br><br></p>
  <hr />
  <p><strong>EDIT4</strong><br><br>
  <strong>I have got the cause of this infinite loop</strong>. See my answer. But it takes about <strong>25-30 seconds</strong> to execute, which is quite a long time. A* should do much faster than this. the applet does this in <strong>0.003 seconds</strong>. <strong>I will award the bounty for improving the performance.</strong></p>
  <hr />
  <p><strong>For</strong> quick reference I have pasted the the two classes without the comments : <br></p>
  <h2>EightPuzzle</h2>
    <br>
  <pre><code> import java.util.*;
      
      public class EightPuzzle implements Comparable &lt;Object&gt; {
             
             
              int[] puzzle = new int[9];
              int h_n= 0;
              int hueristic_type = 0;
              int g_n = 0;
              int f_n = 0;
              EightPuzzle parent = null;
      
             
              public EightPuzzle(int[] p, int h_type, int cost)
              {
                      this.puzzle = p;
                      this.hueristic_type = h_type;
                      this.h_n = (h_type == 1) ?  h1(p) : h2(p);
                      this.g_n = cost;
                      this.f_n = h_n + g_n;
              }
              public int getF_n()
              {
                      return f_n;
              }
              public void setParent(EightPuzzle input)
              {
                      this.parent = input;
              }
              public EightPuzzle getParent()
              {
                      return this.parent;
              }
      
              public int inversions()
              {
                      /*
                       * Definition: For any other configuration besides the goal,
                       * whenever a tile with a greater number on it precedes a
                       * tile with a smaller number, the two tiles are said to be inverted
                       */
                      int inversion = 0;
                      for(int i = 0; i &lt; this.puzzle.length; i++ )
                      {
                              for(int j = 0; j &lt; i; j++)
                              {
                                      if(this.puzzle[i] != 0 &amp;&amp; this.puzzle[j] != 0)
                                      {
                                      if(this.puzzle[i] &lt; this.puzzle[j])
                                              inversion++;
                                      }
                              }
      
                      }
                      return inversion;
                     
              }
              public int h1(int[] list)
              // h1 = the number of misplaced tiles
              {
                      int gn = 0;
                      for(int i = 0; i &lt; list.length; i++)
                      {
                              if(list[i] != i &amp;&amp; list[i] != 0)
                                      gn++;
                      }
                      return gn;
              }
              public LinkedList&lt;EightPuzzle&gt; getChildren()
              {
                      LinkedList&lt;EightPuzzle&gt; children = new LinkedList&lt;EightPuzzle&gt;();
                      int loc = 0;
              int temparray[] = new int[this.puzzle.length];
              EightPuzzle rightP, upP, downP, leftP;
                      while(this.puzzle[loc] != 0)
                      {
                              loc++;
                      }
                      if(loc % 3 == 0){
                              temparray = this.puzzle.clone();
                              temparray[loc] = temparray[loc + 1];
                              temparray[loc + 1] = 0;
                              rightP = new EightPuzzle(temparray, this.hueristic_type, this.g_n + 1);
                              rightP.setParent(this);
                              children.add(rightP);
      
                      }else if(loc % 3 == 1){
                      //add one child swaps with right
                              temparray = this.puzzle.clone();
                              temparray[loc] = temparray[loc + 1];
                              temparray[loc + 1] = 0;
                             
                              rightP = new EightPuzzle(temparray, this.hueristic_type, this.g_n + 1);
                              rightP.setParent(this);
                              children.add(rightP);
                              //add one child swaps with left
                              temparray = this.puzzle.clone();
                              temparray[loc] = temparray[loc - 1];
                              temparray[loc - 1] = 0;
                             
                              leftP = new EightPuzzle(temparray, this.hueristic_type, this.g_n + 1);
                              leftP.setParent(this);
                              children.add(leftP);
                      }else if(loc % 3 == 2){
                      // add one child swaps with left
                              temparray = this.puzzle.clone();
                              temparray[loc] = temparray[loc - 1];
                              temparray[loc - 1] = 0;
                             
                              leftP = new EightPuzzle(temparray, this.hueristic_type, this.g_n + 1);
                              leftP.setParent(this);
                              children.add(leftP);
                      }              
                     
                      if(loc / 3 == 0){
                      //add one child swaps with lower
                              temparray = this.puzzle.clone();
                              temparray[loc] = temparray[loc + 3];
                              temparray[loc + 3] = 0;
                             
                              downP = new EightPuzzle(temparray, this.hueristic_type, this.g_n + 1);
      
                              downP.setParent(this);
      
                              children.add(downP);
                     
                             
                      }else if(loc / 3 == 1 ){
                              //add one child, swap with upper
                              temparray = this.puzzle.clone();
                              temparray[loc] = temparray[loc - 3];
                              temparray[loc - 3] = 0;
                             
                              upP = new EightPuzzle(temparray, this.hueristic_type, this.g_n + 1);
                              upP.setParent(this);
      
                              children.add(upP);
                              //add one child, swap with lower
                              temparray = this.puzzle.clone();
                              temparray[loc] = temparray[loc + 3];
                              temparray[loc + 3] = 0;
                             
                              downP = new EightPuzzle(temparray, this.hueristic_type, this.g_n + 1);
                              downP.setParent(this);
      
                              children.add(downP);
                      }else if (loc / 3 == 2 ){
                              //add one child, swap with upper
                              temparray = this.puzzle.clone();
                              temparray[loc] = temparray[loc - 3];
                              temparray[loc - 3] = 0;
                             
                              upP = new EightPuzzle(temparray, this.hueristic_type, this.g_n + 1);
                              upP.setParent(this);
      
                              children.add(upP);
                      }
      
                      return children;
              }
              public int h2(int[] list)
              // h2 = the sum of the distances of the tiles from their goal positions
              // for each item find its goal position
              // calculate how many positions it needs to move to get into that position
              {
                      int gn = 0;
                      int row = 0;
                      int col = 0;
                      for(int i = 0; i &lt; list.length; i++)
                      {
                              if(list[i] != 0)
                              {
                                      row = list[i] / 3;
                                      col = list[i] % 3;
                                      row = Math.abs(row - (i / 3));
                                      col = Math.abs(col - (i % 3));
                                      gn += row;
                                      gn += col;
                              }
                             
                      }
                      return gn;
              }
      
              public String toString()
              {
                      String x = &quot;&quot;;
                      for(int i = 0; i &lt; this.puzzle.length; i++){
                              x += puzzle[i] + &quot; &quot;;
                              if((i + 1) % 3 == 0)
                                      x += &quot;\n&quot;;
                      }
                      return x;
              }
              public int compareTo(Object input) {
                     
                     
                      if (this.f_n &lt; ((EightPuzzle) input).getF_n())
                              return -1;
                      else if (this.f_n &gt; ((EightPuzzle) input).getF_n())
                              return 1;
                      return 0;
              }
             
              public boolean equals(EightPuzzle test){
                      if(this.f_n != test.getF_n())
                              return false;
                      for(int i = 0 ; i &lt; this.puzzle.length; i++)
                      {
                              if(this.puzzle[i] != test.puzzle[i])
                                      return false;
                      }
                      return true;
              }
              public boolean mapEquals(EightPuzzle test){
                      for(int i = 0 ; i &lt; this.puzzle.length; i++)
                      {
                              if(this.puzzle[i] != test.puzzle[i])
                                      return false;
                      }
                      return true;
              }
      
      }
  </code></pre>
  <h2>proj1</h2>
  <pre><code>import java.util.*;
  
  public class proj1 {
  
          /**
           * @param args
           */
         
          public static void main(String[] args) {
                 
                 
                  int[] p1d = {1, 4, 2, 3, 0, 5, 6, 7, 8};
                  int hueristic = 2;
                  EightPuzzle start = new EightPuzzle(p1d, hueristic, 0);
                  int[] win = { 0, 1, 2,
                                            3, 4, 5,
                                            6, 7, 8};
                  EightPuzzle goal = new EightPuzzle(win, hueristic, 0);
                 
                  astar(start, goal);
  
                 
  
          }
         
          public static void astar(EightPuzzle start, EightPuzzle goal)
          {
                  if(start.inversions() % 2 == 1)
                  {
                          System.out.println(&quot;Unsolvable&quot;);
                          return;
                  }
  //              function A*(start,goal)
  //           closedset := the empty set                 // The set of nodes already evaluated.
                  LinkedList&lt;EightPuzzle&gt; closedset = new LinkedList&lt;EightPuzzle&gt;();
  //           openset := set containing the initial node // The set of tentative nodes to be evaluated. priority queue
                  PriorityQueue&lt;EightPuzzle&gt; openset = new PriorityQueue&lt;EightPuzzle&gt;();
  
                  openset.add(start);
                 
  
                  while(openset.size() &gt; 0){
  //               x := the node in openset having the lowest f_score[] value
                          EightPuzzle x = openset.peek();
  
  //               if x = goal
                          if(x.mapEquals(goal))
                          {
  //                   return reconstruct_path(came_from, came_from[goal])
                                   Stack&lt;EightPuzzle&gt; toDisplay = reconstruct(x);
                                   System.out.println(&quot;Printing solution... &quot;);
                                   System.out.println(start.toString());
                                   print(toDisplay);
                                   return;
                                   
                          }
  //               remove x from openset
  //               add x to closedset
                          closedset.add(openset.poll());
                          LinkedList &lt;EightPuzzle&gt; neighbor = x.getChildren();
  //               foreach y in neighbor_nodes(x)                
                          while(neighbor.size() &gt; 0)
                          {
                                  EightPuzzle y = neighbor.removeFirst();
  //                   if y in closedset
                                  if(closedset.contains(y)){
  //                       continue
                                          continue;
                                  }
  //                   tentative_g_score := g_score[x] + dist_between(x,y)
  //      
  //                   if y not in openset
                                  if(!closedset.contains(y)){
  //                       add y to openset
                                          openset.add(y);
  //                      
                                  }
  //                 
                          }
  //               
                  }
          }
  
          public static void print(Stack&lt;EightPuzzle&gt; x)
          {
                  while(!x.isEmpty())
                  {
                          EightPuzzle temp = x.pop();
                          System.out.println(temp.toString());
                  }
          }
  
          public static Stack&lt;EightPuzzle&gt; reconstruct(EightPuzzle winner)
          {
                  Stack&lt;EightPuzzle&gt; correctOutput = new Stack&lt;EightPuzzle&gt;();
                 
                  while(winner.getParent() != null)
                  {
                  correctOutput.add(winner);
                  winner = winner.getParent();
                  }
  
                  return correctOutput;
          }
         
          }
     
  </code></pre>