De-CLOS the parse tree
author |
Steve Losh <steve@stevelosh.com> |
date |
Fri, 15 Jul 2016 20:16:26 +0000 |
parents |
5edeeac89e03 |
children |
(none) |
(in-package #:bones.wam)
;;;; Rules
(setf *database* (make-database))
(push-logic-frame)
(fact (role robot))
(facts (init (off p))
(init (off q))
(init (off r))
(init (off s))
(init (step 1)))
(rule (next (on p))
(does robot a)
(true (off p)))
(rule (next (on q))
(does robot a)
(true (on q)))
(rule (next (on r))
(does robot a)
(true (on r)))
(rule (next (off p))
(does robot a)
(true (on p)))
(rule (next (off q))
(does robot a)
(true (off q)))
(rule (next (off r))
(does robot a)
(true (off r)))
(rule (next (on p))
(does robot b)
(true (on q)))
(rule (next (on q))
(does robot b)
(true (on p)))
(rule (next (on r))
(does robot b)
(true (on r)))
(rule (next (off p))
(does robot b)
(true (off q)))
(rule (next (off q))
(does robot b)
(true (off p)))
(rule (next (off r))
(does robot b)
(true (off r)))
(rule (next (on p))
(does robot c)
(true (on p)))
(rule (next (on q))
(does robot c)
(true (on r)))
(rule (next (on r))
(does robot c)
(true (on q)))
(rule (next (off p))
(does robot c)
(true (off p)))
(rule (next (off q))
(does robot c)
(true (off r)))
(rule (next (off r))
(does robot c)
(true (off q)))
(rule (next (off s))
(does robot a)
(true (off s)))
(rule (next (off s))
(does robot b)
(true (off s)))
(rule (next (off s))
(does robot c)
(true (off s)))
(rule (next (on s))
(does robot a)
(true (on s)))
(rule (next (on s))
(does robot b)
(true (on s)))
(rule (next (on s))
(does robot c)
(true (on s)))
(rule (next (off s))
(does robot d)
(true (on s)))
(rule (next (on s))
(does robot d)
(true (off s)))
(rule (next (on p))
(does robot d)
(true (on p)))
(rule (next (off p))
(does robot d)
(true (off p)))
(rule (next (on q))
(does robot d)
(true (on q)))
(rule (next (off q))
(does robot d)
(true (off q)))
(rule (next (on r))
(does robot d)
(true (on r)))
(rule (next (off r))
(does robot d)
(true (off r)))
(rule (next (step ?y))
(true (step ?x))
(succ ?x ?y))
(facts (succ 1 2)
(succ 2 3)
(succ 3 4)
(succ 4 5)
(succ 5 6)
(succ 6 7)
(succ 7 8))
(facts (legal robot a)
(legal robot b)
(legal robot c)
(legal robot d))
(rule (goal robot 100)
(true (on p))
(true (on q))
(true (on r))
(true (on s)))
(rule (goal robot 0)
(true (off p)))
(rule (goal robot 0)
(true (off q)))
(rule (goal robot 0)
(true (off r)))
(rule (goal robot 0)
(true (off s)))
(rule (terminal)
(true (step 8)))
(rule (terminal)
(true (on p))
(true (on q))
(true (on r))
(true (on s)))
(finalize-logic-frame)
(defun extract (key results)
(mapcar (lambda (result) (getf result key)) results))
(defun initial-state ()
(extract '?what (query-all (init ?what))))
(defun terminalp ()
(prove (terminal)))
(defun equiv-roles (move1 move2)
(eq (car move1) (car move2)))
(defun legal-moves ()
(let* ((individual-moves
(query-map (lambda (move)
(cons (getf move '?role)
(getf move '?action)))
(legal ?role ?action)))
(joint-moves
(apply #'map-product #'list
(equivalence-classes #'equiv-roles individual-moves))))
joint-moves))
(defun roles ()
(extract '?role (query-all (role ?role))))
(defun goal-value (role)
(getf (invoke-query `(goal ,role ?goal))
'?goal))
(defun goal-values ()
(invoke-query-all `(goal ?role ?goal)))
(defun next-state ()
(extract '?what (query-all (next ?what))))
(defun apply-state (state)
(push-logic-frame)
(loop :for fact :in state
:do (invoke-fact `(true ,fact)))
(finalize-logic-frame))
(defun apply-moves (moves)
(push-logic-frame)
(loop :for (role . action) :in moves
:do (invoke-fact `(does ,role ,action)))
(finalize-logic-frame))
(defun clear-state ()
(pop-logic-frame))
(defun clear-moves ()
(pop-logic-frame))
(defun perform-move (joint-move)
(prog2
(apply-moves joint-move)
(next-state)
(clear-moves)))
(defvar *count* 0)
(defvar *role* nil)
;; nodes: (state . path)
(defun depth-first-search (&key exhaust)
(let ((*count* 0)
(*role* (first (roles)))
(nodes (make-queue)))
(enqueue (cons (initial-state) nil) nodes)
(pprint
(while (not (queue-empty-p nodes))
(incf *count*)
(destructuring-bind (state . path)
(dequeue nodes)
(apply-state state)
; (format t "Searching: ~S (~D remaining)~%" state (length remaining))
(if (terminalp)
(prog1
(if (and (not exhaust) (= 100 (goal-value *role*)))
(list state (reverse path))
nil)
(clear-state))
(let ((children
(loop :for joint-move :in (legal-moves)
:collect (cons (perform-move joint-move)
(cons joint-move path)))))
(clear-state)
(queue-append nodes children))))))
(format t "~%Searched ~D nodes.~%" *count*)))