Split functor cells into separate functor and arity cells
This lets us keep everything we need for unification right in the contiguous
main store array. It also makes GC a bit easier to deal with, because all the
references to things outside the WAM are kept in basically one place.
author |
Steve Losh <steve@stevelosh.com> |
date |
Sat, 16 Jul 2016 01:34:04 +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*)))