;;;;;;;;;;Exercice 1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; 1.1 (gps '(son-at-home car-works) '(son-at-school) *school-ops*) ;; l'appel pour lequel la base d'actions est faite: (gps '(son-at-home car-needs-battery have-money have-phone-book) '(son-at-school) *school-ops*) ;;; 1.2 ; suffisant: (push newrule list-ops) ; mieux (defun add-op (newrule list-ops) "ajoute une regle avec effet de bord sur list-ops" (if (member newrule list-ops :test #'(lambda (r1 r2) (eql (op-action r1) (op-action r2)))) list-ops (push newrule list-ops))) ; spécialisation: (defun add-schoolop (newrule) (add-op newrule *school-ops*)) (defun rem-op (ruleaction list-ops) (remove-if #'(lambda (r) (eql ruleaction (op-action r))) list-ops)) ; ne marche pas (pas d'effet de bord): ;(defun add-rule (newrule list-ops) ; (push newrule list-ops)) ; pour comprendre les effets de bords par des ; fonctions, vous pouvez tester: (defun f (l) (setf (cdr l) nil)) (defun add_in_2nd_position (x l) (let ((cdrl (cdr l))) (setf (cdr l) (list x)) (setf (cddr l) cdrl) l)) ; possibilité avec une macro: (defmacro add_rule (newrule list-ops) `(push ,newrule ,list-ops)) ;;;;;;;;;;Exercice 2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Une version simplifiée de la version originale du labyrinte ;;; sans "convert", sans notation en prédicats "(at n)" (cf. version finale de gps) (defun mappend (fn list) "Append the results of calling fn on each element of list. Like mapcon, but uses append instead of nconc." (apply #'append (mapcar fn list))) (defun op-simple (action &key preconds add-list del-list) "Make a new operator " (make-op :action action :preconds preconds :add-list add-list :del-list del-list)) (defun make-maze-ops (pair) "Make maze ops in both directions" (list (make-maze-op (first pair) (second pair)) (make-maze-op (second pair) (first pair)))) (defun make-maze-op (here there) "Make an operator to move between two places" (op-simple `(move from ,here to ,there) :preconds `(,here) :add-list `(,there) :del-list `(,here))) (defparameter *maze-ops* (mappend #'make-maze-ops '((1 2) (2 3) (3 4) (4 9) (9 14) (9 8) (8 7) (7 12) (12 13) (12 11) (11 6) (11 16) (16 17) (17 22) (21 22) (22 23) (23 18) (23 24) (24 19) (19 20) (20 15) (15 10) (10 5) (20 25)))) ; (gps '(1) '(25) *maze-ops*); marche car pas de boucle dans le labyrinte ; on rajoute une boucle: (defparameter *maze-ops* (mappend #'make-maze-ops '((25 20) (1 2) (2 3) (3 4) (4 9) (9 14) (9 8) (8 7) (7 12) (12 13) (12 11) (11 6) (11 16) (16 17) (17 22) (21 22) (22 23) (23 18) (23 24) (24 19) (19 20) (20 15) (15 10) (10 5) (20 25)))) ; (gps '(1) '(25) *maze-ops*) ;; boucle ;;;;;;;;;;Exercice 3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; 3.1 ;; cf. la boucle dans le labyrinthe ci-dessus ;; ou, dans l'exemple de *school-ops*, une règle du genre: (push (make-op :action 'get-money :preconds '(have-money) :add-list '(have-money)) *school-ops*) ;;; 3.2 ;; un but avec deux sous-buts => ceux-ci ne sont pas réalisés simultanément ;; comme le laisse penser l'appel, mais séquentiellement. En fait, ;; l'argent sera dépensé par l'achieve du but son-at-school, et donc le ;; but ne sera pas réalisé: (gps '(son-at-home car-needs-battery have-money have-phone-book) '(have-money son-at-school) *school-ops*) (EXECUTING LOOK-UP-NUMBER) (EXECUTING TELEPHONE-SHOP) (EXECUTING TELL-SHOP-PROBLEM) (EXECUTING GIVE-SHOP-MONEY) (EXECUTING SHOP-INSTALLS-BATTERY) (EXECUTING DRIVE-SON-TO-SCHOOL) SOLVED ;;; 3.3 ;; Et donc, dans le cas où les deux sous-buts sont dans un ordre inversé, ;; cela ne marche pas: (gps '(son-at-home car-needs-battery have-money have-phone-book) '(son-at-school have-money) *school-ops*) (EXECUTING LOOK-UP-NUMBER) (EXECUTING TELEPHONE-SHOP) (EXECUTING TELL-SHOP-PROBLEM) (EXECUTING GIVE-SHOP-MONEY) (EXECUTING SHOP-INSTALLS-BATTERY) (EXECUTING DRIVE-SON-TO-SCHOOL) NIL