State Space Search
If each state is represented by a node, and each possible change is represented by a link, then a "problem" can be represented as a graph (the "state space"), with a "solution" corresponding to a path from the initial state to a final state.
In this way, a solution consists of a sequence of operations, each of which changes one state into another one, and the whole sequence changes the initial state into a final state in multiple steps.
Examples:
The search strategy should be correct, complete, and efficient. Sometimes we also want it to be able to find the optimal solution (such as the shortest path). A generic searching algorithm provides a framework for the relevant algorithms, which repeatedly expands a node in frontier. The direction of search can be forward (data-driven), backward (goal-driven), or bidirectional. Common search algorithms include Breadth-First and Depth-First, where the "frontier" data structure is a queue and a stack, respectively.
In depth-first search, if it is possible to move on both directions in a link, search can be done without the stack. The program can start at the root, then go all the way done, then back up, i.e. "backtrack" to the previous node to try another possibility.
path(Z, Z). path(X, Y) :- move(X, W), not(been(W)), assert(been(W)), path(W, Y). move(a, b). move(b, a). move(a, c). move(c, d). move(a, e). move(d, f).We can have the following sample run:
?- assert(been(a)), path(a,f). true. ?- listing(been). :- dynamic been/1. been(a). been(b). been(c). been(d). been(f). ?- retractall(been(_)). true. ?- assert(been(a)), path(a, X). X = a ; X = b ; X = c ; X = d ; X = f ; X = e ; false. ?- assert(been(a)), path(a, X). X = a ; false.The assert(been(a)) is used to prevent SWI-Prolog from complaining "undefined predicate" when not(been(W)) is called before any been fact is inserted.
From the result of trace, we can see that the search is depth-first.
The last call path(a, X) only gives one answer, because all the "been" facts inserted during the previous run are still in the database. To remove them, use retractall(been(_)).
Another program (path/3) that does not use "global variables" but a "local variable" to keep the visited node list is given here:
path(Z, Z, _). path(X, Y, L) :- move(X, W), not(member(W, L)), path(W, Y, [W|L]).Try it as the following in SWISH:
?- path(a, X, [a]).and ask for all the answers. The result should be the same as above. If the goal is repeated, the result will be repeated, too, because this program does not change the database.