Skip to content

Instantly share code, notes, and snippets.

@fffej
Created June 19, 2009 19:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fffej/132843 to your computer and use it in GitHub Desktop.
Save fffej/132843 to your computer and use it in GitHub Desktop.
(defn contains-value?
[coll val]
(not (nil? (some (partial = val) coll))))
(defn executing?
[x]
"Is x of the form: (executing ...)?"
(and (seq? x) (= 'executing (first x))))
(defn convert-op
[op]
"Make op conform the the (EXECUTING op) convention"
(if-not (some executing? (:add-list op))
(struct operation
(:action op)
(:preconditions op)
(set (conj (:add-list op) (list 'executing (:action op))))
(:del-list op))
op))
(defn make-op
[action preconditions add-list del-list]
(convert-op (struct operation action preconditions add-list del-list)))
(defn appropriate?
[goal operation]
"An op is appropriate to a goal if it is in its add list"
(contains-value? (:add-list operation) goal))
(declare achieve-all)
(defn apply-op
[state goal op goal-stack]
"Return a new, transformed state if op is applicable."
(dbg-indent :gps (count goal-stack) "Consider: %s" (:action op))
(let [new-state (achieve-all state (:preconditions op) (cons goal goal-stack))]
(when-not (nil? state)
(dbg-indent :gps (count goal-stack) "Action: %s" (:action op))
(concat (remove (fn [x] (= x (:del-list op))) new-state)
(:add-list op)))))
(defn achieve
[state goal goal-stack]
"A goal is achieved if it already holds,
or if there is an appropriate op for it that is applicable"
(dbg-indent :gps (count goal-stack) "Goal: %s" goal)
(cond
(contains-value? state goal) state
(contains-value? goal-stack goal) nil
:else (some (fn [op] (apply-op state goal op goal-stack))
(filter (fn [x] (appropriate? goal x)) @*ops*))))
(defn sequential-subset?
[s1 s2]
(and (<= (count s1) (count s2))
(every? (fn [x] (contains-value? s2 x)) s1)))
(defn achieve-all
[state goals goal-stack]
"Achieve each goal, and make sure they still hold at the end."
(let [current-state (atom state)]
(if (and (every? (fn [g] (swap! current-state
(fn [s] (achieve s g goal-stack)))) goals)
(sequential-subset? goals @current-state))
@current-state)))
(defn GPS
[state goals ops]
"General Problem Solver: from state, achieve using ops"
(dosync
(ref-set *ops* ops))
(remove (comp not sequential?) (achieve-all (cons (list 'start) state) goals [])))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment