Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Loop and Conditional extensions to the SHOP domain language #142

Draft
wants to merge 29 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
1fbbf7d
All recent changes but unstaged.
ukuter Apr 8, 2022
6b6166f
Add a test suite for domain conditionals
mdehavensift Apr 29, 2022
1e5a6a7
Add parameters to allow disabling debug prints in loop extensions
mdehavensift May 1, 2022
1287cc4
Use loop extension debug printing function in conditional extensions
mdehavensift May 1, 2022
0ea841a
Move some debug prints in explicit search behind *verbose* checks
mdehavensift May 1, 2022
abd5f52
Fix errors from rebase.
rpgoldman Aug 22, 2023
61f246d
Fix undefined variable.
rpgoldman Aug 22, 2023
48d23b4
Fix more rebase issues.
rpgoldman Aug 22, 2023
3be9da9
Fix variable issues.
rpgoldman Aug 22, 2023
82ddd4b
Remove incorrect ignore declaration.
rpgoldman Aug 22, 2023
8be565a
Fix two bugs in seek-plans-stack.
rpgoldman Aug 23, 2023
1f479f9
Remove a condition
mdehavensift Aug 23, 2023
1a93302
Change (until (not <condition>)) to (while <condition>)
mdehavensift Aug 23, 2023
ea1aa06
Replace slot type comments with declarations
mdehavensift Aug 23, 2023
c215068
Add ftype declaration to make-conditional-state-expand
mdehavensift Aug 23, 2023
99bd64e
Fix misformed ftype definition
mdehavensift Aug 23, 2023
d396dd1
Use conditional-p rather than duplicating the check directly
mdehavensift Aug 23, 2023
31e9772
Replace dbg-lp with trace-print
mdehavensift Aug 24, 2023
d9951f4
Create looping-mixin
mdehavensift Aug 24, 2023
a43364f
gensym + intern replaced by gentemp
mdehavensift Aug 24, 2023
bee99e1
Fix indentation error
mdehavensift Aug 24, 2023
b7e3e96
Import relevant SHOP symbols into loop conditionals test package
mdehavensift Aug 24, 2023
7ddcd7b
Add ":redefine-ok t" to test domains in loop conditional tests
mdehavensift Aug 24, 2023
ae9da93
Fix incorrect trace print
mdehavensift Aug 24, 2023
8d362f4
Fix errors introduced when rebasing.
rpgoldman Sep 19, 2023
0808cde
RANDOM-STATE update.
rpgoldman Sep 19, 2023
1725030
Replace tabs with spaces
matthewdehaven Oct 18, 2023
987376d
Add optional package argument to new-symbol
matthewdehaven Oct 18, 2023
1a61b7a
Simplify seek-plans-task for looping domain
matthewdehaven Oct 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 89 additions & 85 deletions shop3/explicit-stack-search/explicit-search.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -105,20 +105,20 @@ objects."
(*plans-found* nil)
(*enhanced-plan-tree* plan-tree)
(*no-dependencies* no-dependencies)
(*include-rationale* rationale)
(*record-dependencies-p* (and *enhanced-plan-tree* (not *no-dependencies*)))
(*verbose* verbose)
(*which* which)
(*include-rationale* rationale)
(*make-analogy-table* (progn
(or (and make-analogy-table (eq which :first))
(not make-analogy-table)
(error "Make analogy table only supported for :which == :first"))
make-analogy-table))
(*analogical-replay* (progn
(or (and analogical-replay (eq which :first))
(not analogical-replay)
(error "Analogical replay only supported for :which == :first"))
analogical-replay))
(or (and analogical-replay (eq which :first))
(not analogical-replay)
(error "Analogical replay only supported for :which == :first"))
analogical-replay))
(problem (find-problem problem t))
(domain (cond (domain
(etypecase domain
Expand Down Expand Up @@ -162,7 +162,7 @@ objects."
(when make-analogy-table
(clear-replay-table domain *analogical-replay-table*))

(when plan-tree
(when tree
(setf (slot-value search-state 'plan-tree) tree)
(unless no-dependencies
(prepare-state-tag-decoder)))
Expand Down Expand Up @@ -229,8 +229,8 @@ List of analogical-replay tables -- optional
(setf (mode state) 'look-for-immediate-task)))
(look-for-immediate-task
(cond ((immediate-tasks state)
(let ((state (prepare-choose-immediate-task-state state)))
(setf (mode state) 'pop-immediate-task)))
(prepare-choose-immediate-task-state state)
(setf (mode state) 'pop-immediate-task))
(t
(setf (mode state) 'prepare-to-choose-toplevel-task))))
(pop-immediate-task
Expand All @@ -256,11 +256,15 @@ List of analogical-replay tables -- optional
(depth state)
(apply-substitution task (unifier state)))
(incf *expansions*)
(when (>= *verbose* 2)
(format t "~%Task name: ~s" (get-task-name task)))
(cond
((primitivep (get-task-name task))
(setf (mode state) 'expand-primitive-task))
((eql (get-task-name task) :loop)
(setf (mode state) 'unfold-looping-task))
((conditional-p (get-task-name task))
(setf (mode state) 'expand-conditional-task))
(t ; original nonprimitive:
(setf (mode state) 'prepare-to-choose-method)))))

Expand All @@ -272,84 +276,92 @@ List of analogical-replay tables -- optional
(incf (depth state)))
;; Else,
(with-slots (current-task depth world-state) state
(when (> *verbose* 0) (format t "~%Could not unfold the loop successfully..."))
(trace-print :tasks (get-task-name current-task) world-state
"~2%Depth ~s, backtracking from task~% task ~s"
"~2%Could not unfold the loop successfully...~2T~%Depth ~s, backtracking from task~% task ~s"
depth
current-task)
(stack-backtrack state))))

(expand-primitive-task
(if (expand-primitive-state state domain)
(expand-conditional-task
(if (expand-conditional-task domain state)
(progn
(setf (mode state) 'test-for-done)
(incf (depth state)))
;; Else,
(with-slots (current-task depth world-state) state
(trace-print :tasks (get-task-name current-task) world-state
"~2%Depth ~s, backtracking from task~% task ~s"
"~2%Could not expand the conditional successfully...~%Depth ~s, backtracking from task~% task ~s"
depth
current-task)
(stack-backtrack state))))
(prepare-to-choose-method
(let* ((task-name (get-task-name (current-task state)))
(methods (methods domain task-name)))
(setf (alternatives state) (sort-methods domain methods which))
(setf (mode state) 'choose-method)))
(choose-method
(if (choose-method-state state domain)
(setf (mode state) 'choose-method-bindings)
(progn
(let ((task1 (current-task state))
(depth (depth state))
(state (world-state state)))
(trace-print :tasks (get-task-name task1) state
"~2%Depth ~s, backtracking from task~% task ~s"
depth
task1))
(stack-backtrack state))))
;; the alternatives here are triples of (expansions unifiers dependencies)
(choose-method-bindings
(if (choose-method-bindings-state state)
(progn
(setf (mode state) 'test-for-done)
(incf (depth state)))
(stack-backtrack state)))
(extract-plan
(let (plan-return)
;; did we find a new plan? If so, then store it
(multiple-value-bind (success plan)
(test-plan-found state :repairable repairable)
(when success
(setf plan-return
(make-plan-return domain which
:plan plan
:state state
:repairable repairable
:replay-table *analogical-replay-table*))
(setf *plans-found* (cons plan-return *plans-found*))
(when (> *verbose* 0)
(format t "~%~%Solution plan found successfully...:~%~a"
plan))))
;; handle *PLANS-FOUND* based on the value of WHICH
(ecase which
(:first
(cond ((and plan-return (>= (length *plans-found*) plan-num-limit))
(return-from seek-plans-stack
(plan-returns (reverse *plans-found*)
unpack-returns)))
;; we've found one plan, but there are possibly more plans to find...
(plan-return (stack-backtrack state))
(t
(return-from seek-plans-stack nil))))
;; if we want all the plans, just keep searching until we fail,
;; and then return any plans we have found.
(:all (stack-backtrack state)))))))
(expand-primitive-task
(if (expand-primitive-state state domain)
(with-slots (mode depth) state
(setf mode 'test-for-done)
(incf depth))
(with-slots (current-task depth world-state) state
(trace-print :tasks (get-task-name current-task) world-state
"~2%Depth ~s, backtracking from task~% task ~s"
depth
current-task)
(stack-backtrack state))))
(prepare-to-choose-method
(let* ((task-name (get-task-name (current-task state)))
(methods (methods domain task-name)))
(setf (alternatives state) (sort-methods domain methods which))
(setf (mode state) 'choose-method)))
(choose-method
(if (choose-method-state state domain)
(setf (mode state) 'choose-method-bindings)
(with-slots (current-task depth world-state) state
(trace-print :tasks (get-task-name current-task) world-state
"~2%Depth ~s, backtracking from task~% task ~s"
depth
current-task)
(stack-backtrack state))))
;; the alternatives here are triples of (expansions unifiers dependencies)
(choose-method-bindings
(if (choose-method-bindings-state state)
(progn
(setf (mode state) 'test-for-done)
(incf (depth state)))
(stack-backtrack state)))
(extract-plan
(let (plan-return)
;; did we find a new plan? If so, then store it
(multiple-value-bind (success plan)
(test-plan-found state :repairable repairable)
(when success
(setf plan-return
(make-plan-return domain which
:plan plan
:state state
:repairable repairable
:replay-table *analogical-replay-table*))
(setf *plans-found* (cons plan-return *plans-found*))
(when (> *verbose* 0)
(format t "~%~%Solution plan found successfully...:~%~a"
plan))))
;; handle *PLANS-FOUND* based on the value of WHICH
(ecase which
(:first
(cond ((and plan-return (>= (length *plans-found*) plan-num-limit))
(return-from seek-plans-stack
(plan-returns (reverse *plans-found*)
unpack-returns)))
;; we've found one plan, but there are possibly more plans to find...
(plan-return (stack-backtrack state))
(t
(return-from seek-plans-stack nil))))
;; if we want all the plans, just keep searching until we fail,
;; and then return any plans we have found.
(:all (stack-backtrack state)))))))
(search-failed ()
(case which
(:first
;; no plans this time -- are there other plans to return?
(when *plans-found*
(plan-returns (reverse *plans-found*) unpack-returns)))
(plan-returns (reverse *plans-found*) unpack-returns)))
(:all
(when *plans-found*
(plan-returns (reverse *plans-found*) unpack-returns)))
Expand Down Expand Up @@ -488,30 +500,19 @@ of PLAN-RETURN objects."
(child (make-plan-tree-for-task-net reduction parent (plan-tree-lookup state))))
;; MAKE-PLAN-TREE-FOR-TASK-NET as a side-effect, links
;; PARENT and CHILD.
#| (format t "~%Subtree1: ~s" (make-add-child-to-tree :parent (apply-substitution
(plan-tree::complex-tree-node-task parent) unifier)
:child (apply-substitution
(plan-tree::complex-tree-node-children
child)
unifier)))
(format t "~%Subtree2: ~s" (make-add-child-to-tree :parent parent :child child))
|#
(push
(if *include-rationale*
(make-add-child-to-tree :parent (apply-substitution
(plan-tree::complex-tree-node-task parent) unifier)
:child (apply-substitution
(plan-tree::complex-tree-node-children
child)
unifier))
;; else
(make-add-child-to-tree :parent parent :child child))
(make-add-child-to-tree :parent parent :child child)
backtrack-stack)
(when *record-dependencies-p*
(let ((depends (make-dependencies parent depends (plan-tree-lookup state))))
(when (>= *verbose* 2)
(format t "~%Depends: ~s" depends))
(when depends
(setf (plan-tree:tree-node-dependencies parent) depends)
(make-add-dependencies :dependencies depends))))))



(multiple-value-setq (top-tasks tasks)
(apply-method-bindings current-task top-tasks tasks
reduction unifier))
Expand Down Expand Up @@ -579,6 +580,9 @@ trigger backtracking."
:unifier unifier
:partial-plan-cost cost)
backtrack-stack)

(when (>= *verbose* 2)
(format t "~%In primitive state?"))
(multiple-value-bind (success top-tasks1 tasks1 protections1 planned-action unifier1 tag prim-cost
depends) ;one set of dependencies...
(seek-plans-primitive-1 domain current-task world-state tasks top-tasks depth protections unifier)
Expand Down
124 changes: 124 additions & 0 deletions shop3/explicit-stack-search/plan-tree-simple-print.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
(in-package :plan-tree)

(defparameter *output-form* nil)

(defmethod print-node ((plan-tree-node top-node))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a defgeneric with docstring to explain what this is for and how to invoke it. Do we call print-node directly, or is there an outer function to invoke?

When we get the docstrings, we should reference them in the manual (I can explain how this is done).

(let ((*output-form* nil))
(iter
(for node in (complex-tree-node-children plan-tree-node))
(format t "~%Node: ~s" node)
(print-node node))
(format t "~%Plan tree: ~s" *output-form*)))

(defmethod print-node ((plan-tree-node complex-tree-node))
(let ((dependencies (tree-node-dependencies plan-tree-node))
output-dependency-form
output-children-form)
(iter
(for d in dependencies)
(push
`(:establisher
((:task
,(if (eq (establisher d) :init)
:init
(tree-node-task (establisher d))))
(:type ,(type-keyw (type-of (establisher d)))))
:label ,(prop d))
output-dependency-form))

(iter
(with children = (complex-tree-node-children plan-tree-node))
(while children)
(as node = (pop children))
(format t "~% Child node: ~s" node)
;; What about :UNORDERED???
(if (eql (type-of node) 'plan-tree::ordered-tree-node)
(setf children (append
(complex-tree-node-children node)
children))
;; else
(push
`(:task ,(tree-node-task node)
:type ,(type-keyw (type-of node)))
output-children-form)
))

(when (tree-node-task plan-tree-node)
(push
`(:task ,(tree-node-task plan-tree-node)
:type ,(type-keyw (type-of plan-tree-node))
:children ,output-children-form
:depends-on ,output-dependency-form)
*output-form*))

(iter
(for node in (complex-tree-node-children plan-tree-node))
(print-node node))))


(defmethod print-node ((plan-tree-node primitive-tree-node))
(let ((dependencies (tree-node-dependencies plan-tree-node))
output-dependency-form)
(iter
(for d in dependencies)
(push
`(:establisher
((:task
,(if (eq (establisher d) :init)
:init
(tree-node-task (establisher d))))
(:type ,(type-keyw (type-of (establisher d)))))
:label ,(prop d))
output-dependency-form))

;; there is no children since this node is primitive.

(when (tree-node-task plan-tree-node)
(push
`(:task ,(tree-node-task plan-tree-node)
:type :primitive
:depends-on ,output-dependency-form)
*output-form*))))

(defmethod print-node ((plan-tree-node ordered-tree-node))
(iter
(for node in (complex-tree-node-children plan-tree-node))
(format t "~%Node in ordered: ~s" node)
(print-node node)))

(defmethod print-node ((plan-tree-node unordered-tree-node))
(format t "~%Unordered CHILDREN: ~A"
(complex-tree-node-children plan-tree-node)))

(defun type-keyw (node-type)
(ecase node-type
(primitive-tree-node
:primitive)
(complex-tree-node
:complex)
(t (format t "~%Add this type to the list: ~s" node-type))))
#|
(plan-tree:primitive-tree-node
(unless (ignored-primitive-node-p tree)
(incf *tree-leaf-index*)
(dolist (partial-constraint partial-constraints)
(declare (type list partial-constraint))
(let ((vars (find-primitive-node-variables tree)))

(assert (eq '<= (tree-partial-constraint-op (car partial-constraint))))
(assert (eq '<= (tree-partial-constraint-op (cdr partial-constraint))))

(new-constraint-with-properties *constraint-db*
(lte-constraint (tree-partial-constraint-lhs (car partial-constraint))
(tachyon/internal/csp-problem-def/structures:node-variables-start-min vars))
:bound :min
:purpose 'tree-constraint)
(new-constraint-with-properties *constraint-db*
(lte-constraint (tree-partial-constraint-lhs (cdr partial-constraint))
(tachyon/internal/csp-problem-def/structures:node-variables-start-max vars))
:bound :max
:purpose 'tree-constraint)))))

(t (error 'unhandled-tree-node-error :node tree))))

|#
Loading