extended
Class BidirectionalSearch<T>

java.lang.Object
  extended by core.Search<T>
      extended by extended.BidirectionalSearch<T>
Type Parameters:
T - the specific type of all elements in the search domain.
All Implemented Interfaces:
java.lang.Runnable

public class BidirectionalSearch<T>
extends Search<T>

The bidirectional search algorithm is a special blind search able to solve any problem implementing the core.BidirectionalProblem interface.

The bidirectional search tries to find the shortest path by running a forward search from the initial state and a backward search from the goal state. The search succeeds if a state has been found, which is reachable in the forward search and also in the backward search.
This strategy grants completeness and a time and space complexity of O(b^(n/2)) (where b is the branching factor and n the depth of the solution).
An optimal solution can be found only if the path costs between two states are constant or increase by a function of the depth.

This algorithm is only applicable if you have a distinct goal state (instead of a plain description what a goal may look like) and the actions which lead to a successor state can be reversed. Their are only a few real world examples where these two constraints hold. (For Example in a path finding search where no heuristic is known.)

Because the search terminates when ever the same state is reachable in the top down search and in the bottom up search, this search returns two resulting states. One can be obtained by calling BidirectionalSearch#getHitFromTop(), and the other can be obtained by calling BidirectionalSearch#getHitFromBottom(). With the first state you can reconstruct the path from the initial state to the found hit state. With the second state you can reconstruct the path from the found hit state to the goal state by reversing the actions.
In contrast to the other search algorithms this search only allows implicit duplicate handling. This has a plain reason. We have to use a java.util.HashSet to check whether a state in the top down search has also been seen in the bottom up search. There for two important rules for states of type T must be fulfilled to allow proper hashing:


This class is a subclass of core.Search only for convenience, because it can not be used in the following way:

 // creates a new problem
 BidirectionalProblem problem=new MyBidirectionalProblem();
 //creates a new search
 Search search=new BidirectionalSearch(problem);
 // initializes and runs the search 
 search.run() 
 // will not return the goal of this search
 search.getResult() 
 
Instead this class should be used in the following way:

 // creates a new problem
 BidirectionalProblem problem=new MyBidirectionalProblem();
 //creates a new search
 BidirectionSearch search=new BidirectionalSearch(problem);
 // initializes and runs the search 
 search.run() 
 // will return the state reached from the initial state
 Object s = search.getHitFromTop()
 // will return the state reached from the goal state
 Object t = search.getHitFromBottom()
 // the following condition is always true
 (s==null ? t==null : s.equals(t)) 
 

Author:
Eden_06

Field Summary
protected  T coresult
          holding the result of the bottom up search or null if nothing has been found yet
protected  BidirectionalProblem<T> problem
          holds a reference to the problem to be solved
 
Fields inherited from class core.Search
neededSteps, result
 
Constructor Summary
BidirectionalSearch(BidirectionalProblem<T> problem)
          Creates a new bidirectional search, with the given problem.
 
Method Summary
 int branchedNodes()
          This method returns the number of expanded nodes during the search.
protected  boolean canPrepare()
          This method checks if the given problem returns valid initial and goal states.
protected  void finalize()
          Clears and Frees the queues and Hashes used in this search.
 T getHitFromBottom()
          Returns the state where the top down search and the bottom up search hit each other or null if no such state could be found.
 T getHitFromTop()
          Returns the state where the top down search and the bottom up search hit each other or null if no such state could be found.
 BidirectionalProblem<T> getProblem()
          This method returns the problem, with which this search has been created.
protected  void prepare()
          This method clears the hashes and queues to prepare them for a new search run.
protected  void search()
          This method implements the bidirectional search algorithm, which can be described in the following way: add problem.initial() to top down queue add problem.goal() to bottom up queue until top down queue and bottom up queue is not empty do pop first element from top down queue and assign it to upper pop first element from bottom up queue and assign it to lower terminate the search if upper can be found in the bottom up queue terminate the search if lower can be found in the top down queue for each node problem.expand(upper) do add node to top down queue for each node problem.implode(lower) do add node to bottom up queue
 
Methods inherited from class core.Search
getResult, initialize, initialized, neededSteps, run, running, stop
 
Methods inherited from class java.lang.Object
clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

problem

protected BidirectionalProblem<T> problem
holds a reference to the problem to be solved


coresult

protected T coresult
holding the result of the bottom up search or null if nothing has been found yet

Constructor Detail

BidirectionalSearch

public BidirectionalSearch(BidirectionalProblem<T> problem)
Creates a new bidirectional search, with the given problem.

Parameters:
problem - the BidirectionalProblem to be solved
Method Detail

branchedNodes

public final int branchedNodes()
This method returns the number of expanded nodes during the search. Note: This method is no alias for neededSteps() and returns the actual number of branched nodes.

Returns:
the number of branched nodes

getProblem

public BidirectionalProblem<T> getProblem()
This method returns the problem, with which this search has been created.

Returns:
the problem to be solved

getHitFromTop

public T getHitFromTop()
Returns the state where the top down search and the bottom up search hit each other or null if no such state could be found. In Detail this method returns a state which belongs to the top down search.
Please read the class description for further information.

Returns:
the state where top down and bottom up search hit each other or null
See Also:
getHitFromBottom()

getHitFromBottom

public T getHitFromBottom()
Returns the state where the top down search and the bottom up search hit each other or null if no such state could be found. In Detail this method returns a state which belongs to the bottom up search.
Please read the class description for further information.

Returns:
the state where top down and bottom up search hit each other or null
See Also:
getHitFromTop()

canPrepare

protected final boolean canPrepare()
This method checks if the given problem returns valid initial and goal states.

Specified by:
canPrepare in class Search<T>
Returns:
true if the search can be prepared
See Also:
Search.canPrepare()

prepare

protected final void prepare()
This method clears the hashes and queues to prepare them for a new search run.

Specified by:
prepare in class Search<T>
See Also:
Search.prepare()

search

protected final void search()
This method implements the bidirectional search algorithm, which can be described in the following way:

Specified by:
search in class Search<T>
See Also:
Search.search()

finalize

protected final void finalize()
                       throws java.lang.Throwable
Clears and Frees the queues and Hashes used in this search.

Overrides:
finalize in class Search<T>
Throws:
java.lang.Throwable
See Also:
Search.finalize()