0

I am trying to implement IDA* algorithm to solve 15 puzzle problem in objective C, I have implemented the algorithm very well but not getting the exact result. Here is my code-

- (TreeNode *)IDAStarSolution:(TreeNode *)startState {
int limit = 5;//2*[startState fx];

appDelegate.CN=[NSNumber numberWithInt:limit];

TreeNode *result=nil;

while (result==nil) {
    [appDelegate.closedList addObject:startState];
    newLimit = 99999;
    result = [self depthLimitSearch:startState costLimit:limit];
    limit = newLimit;
    appDelegate.CN=[NSNumber numberWithInt:newLimit];
    [appDelegate.closedList removeAllObjects];
}
return result;
}

- (TreeNode*)depthLimitSearch:(TreeNode *)current costLimit:(int)currentCostBound {
NSArray *neighbors =[current expandNodeToChilds];
for (TreeNode *s in neighbors) {
    if ([s.puzzleBox isFinalStateBox]) {
        appDelegate.result=s.moveString;
        return s;
    }

    if (![self closedSetContains:s]) {

        int currentCost = [s.cost intValue] + [s.puzzleBox.manhattanDistance intValue];
        if (currentCost <= currentCostBound) {
            [appDelegate.closedList addObject:s];
            [s.puzzleBox displayPuzzleBox];

            TreeNode *solution = [self depthLimitSearch:s costLimit:currentCostBound];
            if (solution!=nil&& (bestSolution ==nil|| [solution.cost intValue] < [bestSolution.cost intValue])) {
                bestSolution = solution;
                //return solution;
            }
        }else {
            if (currentCost < newLimit) {
                NSLog(@"new limit %d", currentCost);
                newLimit = currentCost;
            }
        }
    }
}
return bestSolution;
}


-(BOOL)closedSetContains:(TreeNode *)node{
for (TreeNode *tNode in appDelegate.closedList) {
    if (tNode==node) {
        return YES;
    }
}
return NO;
}

The depthLimitedSearch always returning null, and then expand the same node again and again. So what i have done wrong please suggest.

Implementation is similar to java code given at : Iterative Deepening A Star (IDA*) to solve n-puzzle (sliding puzzle) in Java

As i am returning bestSolution now, if i set the limit more than optimum cost then it returns the first solution it found, which is not optimum. What to do now?

Community
  • 1
  • 1
Ravi Gupta
  • 175
  • 2
  • 11
  • The final return from your depthLimitSearch is nil, so as you back out of your recursion you are always going to get nil. Your other return is commented – Paulw11 May 23 '14 at 12:15
  • That is commented because i am not utilising that one, i replaced return nil to return bestSolution. Is this okay according to IDA* algorithm? – Ravi Gupta May 23 '14 at 12:22
  • That should help. The way it was unless your solution was found immediately you would get nil – Paulw11 May 23 '14 at 12:25
  • Now getting an error as <__NSArrayM: 0x8c38820> was mutated while being enumerated.' . I think it is for neighbours, but why? – Ravi Gupta May 23 '14 at 12:30
  • As i am returning bestSolution now, if i set the limit more than optimum cost then it returns the first solution it found, which is not optimum. What to do now? – Ravi Gupta May 29 '14 at 07:49

1 Answers1

1

I think your mutation/enumeration problem is caused by the structure of your closedSetContains method. You are enumerating appDelegate.closedList but return from the middle of the enumeration. I suspect that when you then modify appDelegate.closedList it causes the error, because it looks like the enumeration is still active. You should be able to confirm this by checking the array reference from the exception with the array appDelegate.closedList in the debugger.

Changing your closedSetContains to this -

-(BOOL)closedSetContains:(TreeNode *)node{
  BOOL ret=NO;
  for (TreeNode *tNode in appDelegate.closedList) {
    if (tNode==node) {
      ret=YES;
      break;
    }
  }

  return ret;
}

may help. But if appDelegate.closedList is an NSMutableArray you can replace the whole method with [appDelegate.closedList containsObject:node]

Paulw11
  • 108,386
  • 14
  • 159
  • 186