|
1 | 1 | ;;; The Problem Solver Module for Techne.
|
2 |
| -;;; Contains the interface described in techne/papers/caise11-tms/caise-tms.tex |
| 2 | +;;; Contains the interface described in papers/caise11-tms/caise-tms.tex |
3 | 3 | ;;; E.g. ASK, TELL, UNTELL
|
4 | 4 |
|
5 | 5 | ;;; Load the ATMS
|
6 |
| -(load "techne-atms.dx64fsl") ; Clozure |
| 6 | +(load "/Users/nernst/Dropbox/research/src/tms/techne-atms.dx32fsl") ; Clozure |
7 | 7 | ;(load "techne-atms.fasl") ; SBCL
|
8 | 8 |
|
9 | 9 | ;;; Data storage
|
10 | 10 | ;;; TODO: figure out why defclass is preferred for REKB over defstruct
|
11 |
| -(defvar *goals* nil) |
12 |
| -(defvar *da* nil) |
13 |
| -(defvar *tasks* nil) |
14 |
| -(defvar *opts* nil) ; optional goals |
15 |
| -(defvar *assm-count* 0) ; how many assumptions have we been told? The computational limit is ~100? TODO verify this. |
| 11 | +(defvar *goals* ()) |
| 12 | +(defvar *assumptions* ()) |
| 13 | +(defvar *opts* ()) ; optional goals |
| 14 | +(defvar *assm-count* 0) ; how many assumptions have we been told? The computational limit is ~300 |
| 15 | +(defvar *mands* ()) ; use equal to compare strings (?) |
| 16 | +(defvar *assm-form* ()) ; hold labelled formulae |
| 17 | +(defvar *labels* (make-hash-table :test 'equalp)) ;case insensitive |
| 18 | +(defvar *impl-repo* nil) ; hold the sets of implementations |
16 | 19 |
|
17 | 20 | ;;;Distance functions
|
18 |
| -(defun min-effort (initial-solution new-solutions) |
19 |
| - " The solution which differs in the fewest tasks and is shortest." |
| 21 | +(defun min-effort (new-solutions) |
| 22 | + " The solution which differs in the fewest tasks" |
| 23 | + ;; TODO add minimize set size of new solution |
| 24 | + (let ((existing (getf (first *impl-repo*) :TASKS )) (smallest (first new-solutions))) |
| 25 | + ;;assume use last set of impl |
| 26 | + (loop for soln in new-solutions |
| 27 | + if (< (length (set-difference soln existing)) (length (set-difference smallest existing))) |
| 28 | + do (setf smallest soln) |
| 29 | + finally (return smallest)))) |
20 | 30 | )
|
21 | 31 |
|
22 |
| -(defun max-fam (initial-solution new-solutions) |
| 32 | +(defun max-fam (new-solutions) |
23 | 33 | "The solution which differs in the fewest tasks from the previous one"
|
24 |
| - ) |
25 |
| - |
26 |
| -(defun simple (initial-solution new-solutions) |
27 |
| - "The shortest new solution" |
28 |
| - ) |
29 |
| - |
30 |
| -;;; TELLs |
| 34 | + ;; maximize intersection |
| 35 | + (let ((existing (getf (first *impl-repo*) :TASKS )) (biggest (first new-solutions))) |
| 36 | + ;;assume use last set of impl |
| 37 | + (loop for soln in new-solutions |
| 38 | + ;do (print existing) |
| 39 | + if (> (length (intersection existing soln)) (length (intersection existing biggest))) |
| 40 | + do (setf biggest soln) |
| 41 | + finally (return biggest)))) |
| 42 | + |
| 43 | +(defun simple (new-solutions) |
| 44 | + "The shortest new solution, if a match, determined non-deterministically" |
| 45 | + (let ((sorted (sort new-solutions #'shorterp))) |
| 46 | + (first sorted))) |
| 47 | + |
| 48 | +(defun shorterp (list1 list2) |
| 49 | + (< (length list1) (length list2))) |
| 50 | + |
| 51 | +;; track implemented tasks |
| 52 | +(defun mark-implemented (tasks &optional (name "") ) |
| 53 | + "Take a list of tasks which the user marked as selected" |
| 54 | + ;; TODO: verify they are actually a valid solution? |
| 55 | + ;; TODO: store old goals .. where do they go. |
| 56 | + (push (list :name name :tasks tasks :date (get-universal-time)) *impl-repo*)) |
| 57 | + |
| 58 | +;;; TELL/UNTELL |
31 | 59 | (defun declare-atomic (atom label sort rekb)
|
32 | 60 | "Add the pair (ATOM LABEL) to the symbol table"
|
33 |
| - ; was it a task? |
34 |
| - (if (eql sort :TASK) |
35 |
| - (setf ?assume t) ;TODO also add this to list of goals etc. |
36 |
| - (setf ?assume nil)) |
37 |
| - (tms-create-node rekb label :ASSUMPTIONP ?assume)) |
38 |
| - |
39 |
| -(defun assrt-formula (consequent ants sort label rekb) ;TODO ant/cons should be a single arg formula |
40 |
| - "If equivalent formula not yet asserted, add to set of LABELLED SORTED FORMULA." |
41 |
| - (justify-node label consequent ants) |
42 |
| - ) |
43 |
| - |
44 |
| -(defun assrt-opt (goal rekb) ; changed from assert to assrt to avoid conflict with lisp-unit |
45 |
| - "Flag ATOM as attractive." |
46 |
| - ) |
47 |
| - |
48 |
| - ;UNTELLs |
49 |
| -(defun undeclare-atomic (atom rekb) |
| 61 | + ;; if a task or DA, we justify with an assumption to indicate defeasibility |
| 62 | + (if (or (eql sort :DA) (eql sort :TASK)) |
| 63 | + (progn |
| 64 | + (let ((ass-node (tms-create-node rekb label :ASSUMPTIONP nil))) |
| 65 | + (let ((fakenode (tms-create-node rekb (concatenate 'string "fake-" label) :ASSUMPTIONP t))) |
| 66 | + (incf *assm-count*) |
| 67 | + (justify-node (concatenate 'string "fake-just-" label) ass-node (list fakenode)) |
| 68 | + ;(setf *assumptions* (nconc *assumptions* (list label))) ; the name |
| 69 | + (setf (gethash (concatenate 'string "fake-" label) *labels*) fakenode) |
| 70 | + ;(nconc *assumption-refs* (list fakenode))) ; the actual node |
| 71 | + ass-node))) |
| 72 | + (progn ;; otherwise, just a simple node |
| 73 | + (setf *goals* (nconc *goals* (list label))) |
| 74 | + (tms-create-node rekb label :ASSUMPTIONP nil)))) |
| 75 | + |
| 76 | +(defun undeclare-atomic (label rekb) |
50 | 77 | "Remove ATOM and any FORMULAs with ATOM as member from REKB."
|
51 |
| - ) |
| 78 | + ;; see DeKleer's ATMS paper for the default logic reasoning behind this |
| 79 | + ;; lookup the label in the list of DA or TASKs |
| 80 | + (unless (label-in-table-p (concatenate 'string "fake-" label)) |
| 81 | + (error "\"~A\" is not a valid atom" label)) |
| 82 | + (let ((x (gethash (concatenate 'string "fake-" label) *labels*))) |
| 83 | + (justify-node (concatenate 'string "retracted-" label) (contradiction rekb) (list x)) |
| 84 | + (remhash (concatenate 'string "fake-" label) *labels* ))) |
| 85 | + |
| 86 | +(defun assert-formula (consequent ants sort label rekb) |
| 87 | + "If equivalent formula not yet asserted, add to set of LABELLED SORTED FORMULA." |
| 88 | + ;;TODO ant/cons should be a single arg formula |
| 89 | + ;; create a fake node that will be used to retract the formula. |
| 90 | + (when (eq sort :DA) |
| 91 | + (let ((ass-node (tms-create-node rekb (concatenate 'string "fakeform-" label) :ASSUMPTIONP t))) |
| 92 | + ;; call the ATMS justification method from fake-node + ants to consequent |
| 93 | + ;; add this node to the table for future retraction |
| 94 | + (setf (gethash (concatenate 'string "fakeform-" label) *labels*) ass-node) |
| 95 | + (let ((new-ants (append (list ass-node) ants))) |
| 96 | + (justify-node label consequent new-ants))))) |
52 | 97 |
|
53 | 98 | (defun retract-formula (label rekb)
|
54 | 99 | "Remove formula identified by LABEL from REKB."
|
55 |
| - ) |
| 100 | + (unless (label-in-table-p (concatenate 'string "fakeform-" label)) |
| 101 | + (error "\"~A\" is not a valid formula" label)) |
| 102 | + (let ((x (gethash (concatenate 'string "fakeform-" label) *labels*))) |
| 103 | + (justify-node (concatenate 'string "retractedform-" label) (contradiction rekb) (list x)) |
| 104 | + (remhash (concatenate 'string "fakeform-" label) *labels* ))) |
| 105 | + |
| 106 | +(defun assert-opt (goal rekb) |
| 107 | + "Flag ATOM as attractive." |
| 108 | + ;; todo: restrict so can only be performed on goals |
| 109 | + (setf *opts* (nconc *opts* (list goal)))) |
56 | 110 |
|
57 | 111 | (defun retract-opt (goal rekb)
|
58 | 112 | "Remove the optional status of this goal"
|
59 |
| - ) |
| 113 | + (setf *opts* (remove goal *opts*))) |
| 114 | + |
| 115 | +(defun assert-mandatory (goal rekb mandatory?) |
| 116 | + "Flag ATOM as mandatory or not mandatory in solution." |
| 117 | + ;; get the goal name |
| 118 | + ;; (setq goal-name (node-string goal)) |
| 119 | + ;; (if mandatory? |
| 120 | + ;; (setq value goal) |
| 121 | + ;; (setq value nil)) |
| 122 | + ;; (setf (gethash goal-name *mand*) value) |
| 123 | + ;; ) |
| 124 | + (setf *mands* (nconc *mands* (list goal)))) |
| 125 | +;; add to the list, hash is quicker but don't think it will matter |
| 126 | + |
| 127 | +(defun retract-mand (goal rekb) |
| 128 | + "Remove the optional status of this goal" |
| 129 | + (setf *mands* (remove goal *mands*))) |
60 | 130 |
|
61 | 131 | ;ASKs
|
62 | 132 | (defun ask-sort (label rekb)
|
63 | 133 | "Return the sort of the given label"
|
64 | 134 | )
|
65 | 135 |
|
66 |
| -(defun are-goals-entailed? (goals rekb) |
| 136 | +(defun is-solution-p (rekb) |
| 137 | + "Check whether all mandatory goals are satisfied by a common explanation" |
| 138 | + ) |
| 139 | + |
| 140 | +(defun are-goals-achieved-from-p (goals rekb) |
| 141 | + "For the given list of goals, are all the mandatory goals explained by that set?" |
| 142 | + ) |
| 143 | + |
| 144 | +(defun are-goals-entailed-p (goals rekb) |
67 | 145 | "Are the set of goals entailed by the rekb?
|
68 | 146 | entailment of a set of goals mean they are consistent w/ all of at
|
69 | 147 | least 1 of the other goal's contexts"
|
70 |
| - |
71 | 148 | (setf goal (pop goals)) ;get environments for each goal
|
72 | 149 | (setf entailed? nil) ; TODO use LET instead of setf?
|
73 | 150 | (dolist (env (tms-node-label goal)) ;env of first goal (tms-node-label goal)
|
74 | 151 | (setf congruent? t)
|
75 | 152 | (dolist (other goals) ; compare to remaining goals
|
76 | 153 | (setf all-false? t)
|
77 | 154 | (dolist (other-env (tms-node-label other))
|
78 |
| - (if (not (not (compare-env env other-env))) ; if EQ,:S21,:S12 continue |
| 155 | + (when (not (not (compare-env env other-env))) ; if EQ,:S21,:S12 continue |
79 | 156 | (setf all-false? nil)))
|
80 | 157 | ;; looped all envs in that goal, should we continue?
|
81 | 158 | (if all-false?
|
82 | 159 | (setf congruent? nil))) ;TODO add short-circuit to prevent eval of all goals.
|
83 | 160 | (if congruent?
|
84 |
| - (setf entailed? t))) ;at least one env in the other goals matches this env. TODO again short-circuit would be nice. |
| 161 | + (setf entailed? t))) ;at least one env in the other goals matches this env. |
| 162 | + ;;TODO again short-circuit would be nice. |
85 | 163 | entailed?)
|
86 | 164 |
|
87 | 165 | (defun min-change-task-entailing (goals tasks dist_fn rekb)
|
|
134 | 212 | (defun contradiction (rekb)
|
135 | 213 | "return the TMS contradiction special node"
|
136 | 214 | (tms-create-node rekb 'CONTRADICTION :CONTRADICTORYP t))
|
| 215 | + |
| 216 | +(defun print-rekb (rekb) |
| 217 | + "print the values in the rekb" |
| 218 | + (print *assumptions*) |
| 219 | + (print-atms-statistics rekb)) |
| 220 | + |
| 221 | +(defun print-assumption-hash (rekb) |
| 222 | + "print the keys of the assumption nodes added for retraction" |
| 223 | + (loop for key being the hash-keys of *labels* |
| 224 | + do (print key))) |
| 225 | + |
| 226 | +(defun label-in-table-p (label) |
| 227 | + "try to find the given label, suitably prepended with 'fake-' or 'fakeform-', in the dictionary" |
| 228 | + (nth-value 1 (gethash label *labels*))) |
0 commit comments