The whole program is very declarative: we only described initial state, possible actions, and the goal. Main just constructs the initial Pegs hash table, calls the plan predicate from the planner module, and outputs the result. Picat will backtrack and choose a different End hole until the whole plan succeeds or all possibilities are exhausted. Note that the action predicate is non-deterministic (which is denoted by ?=>): put( End, 1), % End is not empty Acion =, % string description of the action Cost = 1. put( Middle, 0), % Middle is empty - the peg has been eliminated NewPegs. put( Begin, 0), % Begin is empty in NewPegs - the peg has moved to End NewPegs. get( Middle) = 1, % Begin and Middle must be non-empty NewPegs = copy_term( Pegs), % NewPegs is a copy of Pegs NewPegs. ( move( Begin, Middle, End) move( End, Middle, Begin) ), % choose a move Begin -> Middle -> End (2 possible directions) Pegs. Here is the action predicate with every line commented:Īction( Pegs, NewPegs, Action, Cost) ? => member( End, Pegs.keys()), % choose a hole, call it End Pegs. The first parameter Pegs – the same as in final – is an input parameter, the other three are output parameters. The action predicate defines the only available type of actions in the puzzle. Use of foreach loop and if-then-else construct if very similar to many modern programming languages. The predicate succeeds if all holes except the center one are empty. The final predicate takes Pegs – a hash map where the keys are letters a–p and the values are 0 (there is no peg in this hole) and 1 (there is a peg) – as a parameter. Note that we are using low-case letters for the holes names: this way we don't need to put them in quotes.Ĭapital case letters represent variables in Picat (as in Prolog), so we would have to put them in quotes to represent literal symbols. Or the third is input, and the 1 st and 2 nd are output. So either is the first parameter is input, and the second and third are output, We want to be able to make moves in both directions The index declaration tells how the facts can be used. get( Middle) = 1,Īction = ,Īt the begging of the program there is a bunch of move predicate facts that define lines of neighboring holes on the board. ( move( Begin, Middle, End) move( End, Middle, Begin) ), Here is my complete Picat program to solve the puzzle:įinal( Pegs) => foreach( Char in Pegs.keys())Īction( Pegs, NewPegs, Action, Cost) ? => member( End, Pegs.keys()), The action predicate defines all possible actions and how they transform the problem state. The final predicate is true when the goal is reached, and false otherwise. I have written a blog post with a description and examples of using the planner module: Artificial intelligence planning with Picat.īasically, to solve a planning problem with Picat one needs to define a final predicate and an action predicate. Picat has a planner module for declarative solving of planning problems. In this blog post I use the currently latest version Picat 0.9. Pattern-matching instead of unification, destructive assignment, loops… In many ways, Picat is similar to Prolog, especially B-Prolog,īut it has some features of modern functional and imperative languages: Picat ( ) is a new multiparadigm logic-based programming language. ![]() The goal is to eliminate all pegs except one, leaving the last one in the center.Īs soon as I saw the puzzle I realized that it is very suitable for solving as a planning problem in Picat. In this puzzle all holes A–P, except the center hole H, initially have pegs.Ī peg can jump over nearby peg to the next empty hole, and the peg that was jumped over is eliminated (somewhat similar to checkers). With a description of a pentagonal peg solitaire puzzle and a solution using integer linear programming and SAS/OR. Solving Pentagonal Peg Solitaire puzzle with Picat
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |