
com.thesett.aima.search.util.backtracking.BacktrackingAlgorithm Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of search Show documentation
Show all versions of search Show documentation
Search code developed from 'Artificial Intelligence a Modern Approach', Prentice Hall.
The newest version!
/*
* Copyright The Sett Ltd, 2005 to 2014.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.thesett.aima.search.util.backtracking;
import java.util.Collection;
import java.util.Queue;
import com.thesett.aima.search.SearchNode;
import com.thesett.aima.search.SearchNotExhaustiveException;
import com.thesett.aima.search.impl.BaseQueueSearchAlgorithm;
import com.thesett.aima.search.spi.QueueSearchState;
import com.thesett.common.util.logic.UnaryPredicate;
/**
* Implements a back-tracking search algorithm. This algorithm is mentioned but not explained on page 84 of "Artificial
* Intelligence, A Modern Approach".
*
* There are a number of different approaches to implementing back-tracking of which this is only one. All searches
* are back-tracking in the sense that they explore a search space, retreating from fruitless paths and trying to direct
* effort towards potential solution paths. This back-tracking algorithm is more explicit in that it walks over search
* nodes in a forward direction, calling the {@link ReTraversable#applyOperator()} method on them as it advances, then
* when retreating from exhausted search paths, back-tracks over search nodes in the reverse order that it moved
* forwards over them, calling the {@link ReTraversable#undoOperator()} method as it goes.
*
* For example, in the constraint search described on page 84, as the search moves forward it binds variables, as it
* back-tracks it unbinds them. The same effect can be achieved without using an explicitly back-tracking search by
* passing a fresh copy of the variable state to each child search state created. When the search changes direction to a
* different area of the search space, the abandoned states can simply be forgotten (garbage collected) without being
* undone. This has the disadvantage of having to replicate a potentially large amount of shared data, but the advantage
* that the search ordering can be more free without coming up with a way of sharing state.
*
* When the search order is depth first, operators on shared state can be applied cumulatively to the shared state
* built up by their predecessors. For example, in the constraint search, each new variable binding builds on those
* already set up. Each undone operator undoes a single variable binding to revert to the binding set of a predecessor.
* When using a depth first ordering only the states between the root of the search and the state being currently
* examined will be 'active' in the sense that they have had their operator applied and not undone. That is to say that,
* under depth first orderings only one search path is active at any one time.
*
* This search algorithm can be used usefully with orderings other that depth first. Consider a search where each
* child is given a state composed of the parent state plus one more element. The parent state is shared and not
* replicated. For example, its a linked list, with the child nodes extra element linked into the end in such a way that
* it is only visible to that child node and not other nodes sharing earlier parts of the same list. The search is now
* free to move in whatever order it likes. Upon backtracking over exhausted areas of the search child nodes clean up
* their local piece of the state, so it can be garbage collected. In the constraint search example, each new state can
* add its variable binding onto the linked list in such a way that it is only visible on search paths from that state
* onwards. If the search order moves to a completely different search path, the bindings will not be visible there, and
* the same variable could be bound to a different value on another path. Some degree of indirection in looking up the
* value of a variable must be introduced to achieve this. With general search orderings multiple search paths may be
* active at once.
*
* To summarize, a backtracking search with depth first ordering should be used when shared state can be built
* cumulatively, the space or time requirements of replicating shared state is prohibitive, where the complexity of
* representing state with path-local visibility is not needed, or where the search ordering of depth first is not an
* inconvenience. A backtracking search with other orderings can be used where path-local visibility of state can be
* achieved.
*
*
CRC Card
* Responsibilities Collaborations
* Search based on the queue ordering until a goal node is found or the maximum allowed number of steps is
* reached.
* Apply operators to establish states when searching forwards.
* Undo operators on states in exact reverse order when back-tracking over states.
*
*
* @author Rupert Smith
* @todo This can also be used with depth bounded and iterative deepening. Can those algorithms be generified to work
* over this and max steps interchangeably? They may even work unchanged.
*/
public class BacktrackingAlgorithm© 2015 - 2025 Weber Informatics LLC | Privacy Policy