Let's formalize the problem!
In order to solve our problem with this library, we need to formalize it using the following three concepts:
This all sounds very abstract, so I recommend checking out some examples from the Problem.Example module.
That's it! Once we have specified all these parameters, the algorithms from Problem.Search will solve our problem for us (or at least try their best).
We use the
Problemtype to formalize our problem. We can then use the search algorithms inProblem.Searchto search for a solution to theProblem.First, we need to think of a suitable data structure to represent the states that can occur in our problem. Then, we can think of the parameters that are necessary to formalize our problem:
initialStateSimply the initial state from where we start exploring solutions.
actionsActions explain which states are reachable from any given state. Each action consists of a
result, that is the state which is reached by the action, and of astepCostbetween the current state and the result state.For example, in some route-finding problem there might exist direct connections from Abuja to Accra (933 kilometers) and from Abuja to Lagos (536 kilometers). We could formalize these facts like so:
For toy problems, the step cost of every step will often be
1; Any action takes some effort, but the effort is always the same:Sometimes, we do not care at all about how many steps are taken to solve a problem:
You might be worrying about avoiding redundant states. That is very reasonable, but don't worry! The search algorithms will avoid them automatically, in a smart way.
goalTestDescribes under which conditions a state is a solution to the problem.
Sometimes we know exactly which state is a solution. Thus, if our goal state is Abidjan:
But at other times we only know which conditions to pose, so we will write a more sophisticated function here.
heuristicA heuristic is an estimate about the path cost (the sum of step costs of all actions involved) between a state and the nearest goal state.
If we can think of such an estimate, this is great, because we can then use faster search algorithms —
greedySearchandbestFirstSearch!Often, however, we do not know a heuristic. In that case:
(Or choose any other arbitrary fixed value instead of
0).stateToStringA function that uniquely (!) converts any state to a string. It will be used for some optimizations.
For prototyping, we can just use:
Otherwise, we will need to come up with a custom function. JSON encoders might be helpful for coverting more complex states to strings.
This parameter may appear a bit tedious, but it is necessary for two different kinds of optimizations:
Using keyed nodes in visualizations. This needs a
Stringstate representation.Storing states in dictionaries to access them in logarithmic rather than linear time. This needs a
comparablestate representation. As aStringhappens to becomparable, there is no need for a separatestateToComparablefunction.There are reasons why
Debug.toStringcannot be part of published packages, so the stringification needs to be done by the library user, sorry.