2

I'm looking at the pseudocode on Wikipedia for this and trying to use it to write the algorithm in java. My question comes in a difference in how the result is returned. On wikipedia, one result is returned, and this breaks out of the search. In mine, everytime a relevant node is found, it is added to a list, and that list is to be returned when the tree has been processed. How would I detect the end of the tree in order to break out and return the list?

Wikipedia:

IDDFS(root, goal)
{
  depth = 0
  repeat
  {
    result = DLS(root, goal, depth)
    if (result is a solution)
      return result
    depth = depth + 1
  }
}

DLS(node, goal, depth) 
{
  if (depth == 0 and node == goal)
    return node
  else if (depth > 0)
    for each child in expand(node)
      DLS(child, goal, depth-1)
  else
    return null
}

Mine:

    public List<String> dfid(Tree t, String goal)
    {
        List<String> results = new ArrayList<String>();
        String result;

        int depth = 0;
        while (true) //obviously not the way to go here
        {
            result = dls(t.root, goal, depth);
            if (result.contains(goal))
                results.add(result);
            depth += 1;
        }
        return results; //unreachable return
    }

    public String dls(Node node, String goal, int depth)
    {
        if (depth == 0 && node.data.contains(goal))
        {
            return node.data;
        }
        else if (depth > 0)
        {
            for(Node child : node.children)
            {
                dls(child, goal, depth-1);
            }
        }
        return null;
    }

Edit: After changes:

//depth first iterative deepening
        //control variables for these methods
        boolean maxDepth = false;
    List<String> results = new ArrayList<String>();

    public List<String> dfid(Tree t, String goal)
    {
        int depth = 0;

        while (!maxDepth)
        {
            maxDepth = true;
            dls(t.root, goal, depth);
            depth += 1;
        }
        return results;
    }

    public void dls(Node node, String goal, int depth)
    {
        if (depth == 0 && node.data.contains(goal))
        {
            //set maxDepth to false if the node has children
            maxDepth = maxDepth && children.isEmpty();
            results.add(node.data);
        }
        for(Node child : node.children)
        {
            dls(child, goal, depth-1);
        }
    }
zakparks31191
  • 919
  • 2
  • 21
  • 42

1 Answers1

2

I think you can accomplish this with a boolean maxDepth = false instance variable. On each iteration of your while loop, if maxDepth == true then exit, else set maxDepth = true. In dls when you reach depth == 0 then set maxDepth = maxDepth && children.isEmpty(), i.e. set maxDepth to false if the node has any children.

Also, change dls to a void method. Replace return node.data with results.add(node.data), where results is an ArrayList or HashSet depending on whether you want to filter out duplicates.

If you always want to visit every node in the tree, then modify dls as follows

public void dls(ArrayList<String> results, Node node, String goal)
{
    if (node.data.contains(goal))
    {
        results.add(node.data);
    }
    for(Node child : node.children)
    {
        dls(child, goal, depth-1);
    }
}
Zim-Zam O'Pootertoot
  • 17,888
  • 4
  • 41
  • 69
  • wouldnt this still break at the first instance of a result? I'm looking to collect all results in the tree – zakparks31191 Apr 15 '13 at 00:59
  • I misunderstood, see my edit - put your results in a collection instead of returning them. – Zim-Zam O'Pootertoot Apr 15 '13 at 01:06
  • hm ok. So basically this search would technically return nothing, it would just be populating a set of data elsewhere – zakparks31191 Apr 15 '13 at 01:11
  • That's correct. You can either have the results collection as an instance variable, or you can pass it as another parameter to `dls` – Zim-Zam O'Pootertoot Apr 15 '13 at 01:13
  • by doing it this way, is the `maxdepth` still needed? – zakparks31191 Apr 15 '13 at 01:16
  • What is your exit condition, i.e. when is your algorithm finished? I get the impression that you want to visit every node in the tree, in which case you don't want an iterative deepening depth first search - you just want a regular depth first search. See my edit for the code for this. – Zim-Zam O'Pootertoot Apr 15 '13 at 01:23
  • well, the exit condition is indeed when the whole tree is processed. I realize this isn't the intended purpose of the algorithm, but i'm doing this in a program that times this and other search algorithms doing the same thing. I already have depth first and breadth first algorithms that process the whole tree (which again isn't the point of them, i'm just doing it to see.) – zakparks31191 Apr 15 '13 at 01:25
  • Gotcha. In that case you'll still need `maxDepth` so you'll know when the algorithm is finished - your while loop would be `while(!maxDepth)` – Zim-Zam O'Pootertoot Apr 15 '13 at 01:28
  • hm ok let me try this and see what happens – zakparks31191 Apr 15 '13 at 01:28
  • I'm not sure I implemented your suggestions right, it gets stuck in an infinite loop. I've updated the OP with what I put in – zakparks31191 Apr 15 '13 at 01:44
  • Go back to passing in `depth` as a parameter to `dls` like you were before - I think the thing causing your infinite loop is the `depth -= 1;` statement in your for-each loop, this is decrementing the depth variable more than you want to. – Zim-Zam O'Pootertoot Apr 15 '13 at 01:48
  • Precede the call to `dls` in your while loop with `maxDepth = true`. The idea is that unless a `dls` call changes `maxDepth = false` then you terminate the while loop, so for this to work you need to reset it to true on each iteration. Also, something I just thought of is that you don't need an ArrayList of results, you just need an `int resultCount` - replace `results.add` with `resultCount++`. No sense keeping an ArrayList of duplicate strings. – Zim-Zam O'Pootertoot Apr 15 '13 at 01:59
  • I also inverted the update logic - it should be `maxDepth = maxDepth && children.isEmpty()`. If `children.isEmpty == false` then you're not at maxDepth and so maxDepth should be false. – Zim-Zam O'Pootertoot Apr 15 '13 at 02:01
  • Ok, so that fixes the infinite loop, yet now it returns an empty list when anything is entered as a search query. As for the ArrayList that I'm returning, changing that at this stage would mean i'd have to change a bunch of stuff elsewhere. I know its not efficient how it is, but this wont be used at a scale where it matters for now – zakparks31191 Apr 15 '13 at 02:29
  • Put the `else if (depth > 0)` back in - I was premature in telling you to take it out. What is a sample `goal` string and a sample `node.data` that you would expect to return true to `node.data.contains(goal)`? I'm guessing that you have a malformed `goal`. To debug it, add the block `if (depth == 0) { if(node.data.contains(goal)) System.out.println("MATCH - " + node.data + " " + goal); else System.out.println("NOMATCH - " + node.data + " " + goal);}` – Zim-Zam O'Pootertoot Apr 15 '13 at 02:37
  • Hm even with that its still returning an emtpy list. For now I'll accept this as an answer since the orginal question was answered. Thanks for all your help! I'll post the rest of it as a seperate question since SO keeps yelling at me to stop having a conversation in comments haha – zakparks31191 Apr 15 '13 at 15:15
  • continued here: http://stackoverflow.com/questions/16018896/depth-first-iterative-deepening-algorithm-returning-no-results-in-java – zakparks31191 Apr 15 '13 at 15:25