-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgridworld-planning.lisp
1984 lines (1820 loc) · 81.8 KB
/
gridworld-planning.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Name: gridworld-planning.lisp
;;
;; Author: Lenhart Schubert and Daphne Liu
;; Date of Version 1: Jan. 2008 version 1 by Lenhart Schubert
;; Date of Version 2: Apr. 2009 version 2 by Daphne Liu
;; Date of Version 3: Jan. 2010 version 3 by Daphne Liu
;; Date of Version 4: Nov. 2010 version 4 by Daphne Liu
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ABOUT KNOWLEDGE STORTEDE AND AVAILABILITY TO 'TED':
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; We distinguish 3 sorts of facts
;
; - roadmap facts (about the arrangement of points and roads
; connecting them), stored as the value of *roadmap-knowledge*;
; they are created via the function 'def-roadmap'; the agent
; TED is assumed to know these facts;
;
; - general facts about the world, in particular about the
; properties of various types of entities, stored as the value
; of *general-knowledge*; these are non-unit and/or non-ground
; Horn clauses, typically created by 'def-object', though they
; could also be created by explicitly pushing facts into
; *general-knowledge*; they are intended to allow further
; inferences to be drawn about the current situation, either
; from the perspective of the agent's beliefs (assuming the
; agent TED knows all the general facts), or for modelling the
; world as it actually is.
;
; - specific facts, i.e., ground predications (we might at some
; point consider allowing negative ground literals as well);
; originally sets of these were associated with particular
; points in the road grid, but with the introduction of a
; clear distinction between what the agent believes, and
; what it will "notice" at a particular location, this scheme
; has had to be changed; specific facts are now stored
; uniformly as *world-facts*; what the agent can observe at
; a particular location, after each action, is separately
; calculated, using the notion of objects that are "co-moving"
; with another object. For example, suppose there is an apple
; at the 'home' location initially, and the agent decides
; to pocket it, despite not being hungry at that point. If
; the agent now walks to another location, the facts *about*
; the apple -- that the agent has it, that it's edible, etc.,
; should be available at the new location -- not just as facts
; the agent knows (which was the case in the old version) but
; as actual facts that the actual implementation of the agent's
; actions at that location can modify (e.g., making the apple
; inedible, and rendering false that the agent "has" it, by
; eating it). We could perhaps handle this by moving facts
; about about an object from one location to another, when the
; object moves -- but this reqquires inference in general, and
; seems quite cumbersome. So instead, we keep specific facts
; in the single *world-facts* repository. (This would also make
; possible in future to make inferences in the world that
; depend on facts about objects in different locations -- e.g.,
; telephone calls, remote bank deposits, social relationships
; between non-colocated individuals, etc.) As mentioned, the
; new scheme requires figuring out what objects are at a given
; location, taking account of "co-moving" objects, and then
; making non-occluded predications about the objects at the
; agent's location noticeable to it (so that its belief can
; be appropriately updated). We do this with the help of user-
; supplied list of predicates *left-comoving-preds* and *right-
; comoving*preds*, examples of which are (is_in x y) (if x is
; in y, then x moves with y) and (has x y) (if x has y, then
; y moves with x).
;
; To deal with inferred facts, we also maintain a subset of
; *world-facts* called *protected-facts*, which includes no
; inferred facts.
;
; What facts are known to TED in a given state?
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; It is important to note that atomic ground facts also get
; stored in state-nodes (generated in the planning process),
; as the value of the 'wffs' field of a state-node. THESE WFFS
; CAN BE VIEWED AS THE GROUND FACTS THAT TED IS AWARE OF IN THAT
; STATE. These in general include both the roadmap facts and
; local facts (acquired by observation at the present location
; and at previously visited locations), the latter quite possibly
; elaborated through the use of general knowledge. Note that since
; state wffs are propagated from state-to-(successor)state when
; an operator is applied -- except for changes made by that operator
; -- THE TEDENT, TED, NEVER "FORGETS" ANYTHING IT HAS LEARNED BY
; VISITING A POINT OR MAKING INFERENCES (except, once again, facts
; that are changed by the actions it has taken or is considering).
;
; There is also provision for supplying some initial knowledge to
; the agent that is non-local (and not roadmap knowledge). This
; is done simply by supplying any facts we want the agent to
; know initially as part of the curr-facts argument when we
; place 'TED' at a particular initial location.
;
; The above description of how the knowledge of TED evolves is
; not completely accurate, because allowance is also made for
; the possibility that the "actual" actions taken by the agent
; have somewhat different effects from those the agent "thinks"
; they have, and also that there may be exogenous change. In
; particular, the agent's knowledge state after performing an
; action is recomputed (using 'notice-new-local-facts') by
; checking the agent's beliefs (current state) against locally
; observable facts. The latter are obtained by a variant
; of the action chosen by the agent, whose name adds the
; extension '.actual' to the name of the model action assumed
; by the agent. This "actual" version may differ in its effects
; from the model version (though if no actual version is
; prespecified, a copy of the model version is used as the
; actual action). Positive locally observable facts missing
; from the agent's beliefs are added, and beliefs that would be
; locally observable if they were true, but are not in fact
; locally present are deleted. Any new inferences that follow
; by using *general-knowledge* are added to the *world-facts*,
; (while previous inferences are dropped), and so the agent
; may pick up some of these as well, if they are local and not
; occluded.
;
; How do we handle interaction with the user?
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; The default method is simply to have a function for querying the
; agent's current state, as a way of asking about its beliefs.
;
; But it would be nice to also be able to tell it something, and
; indeed to be able to "converse" with it -- and have it be aware
; THAT it is conversing, and to choose to reply voluntarily, rather
; than by unconscious, unnoticed "reflex".
;
; We could first of all have a 'listen!' function (optionally
; used prior to a 'go!') that allows us to provide certain
; questions, facts, or requests. This should directly insert the
; fact that the speech act occurred into the agent's belief state,
; and run relevant inferential updates based on that fact. The
; chief inference for a question might be that the question-asker
; wants TED to tell him/her/it an answer to the question (this is
; a simplification from a more general speech act approach); this
; will prime the agent for potentially responding accordingly. The
; agent will need to have operators for responding (i.e., satisfying
; its interlocutor's requests, or accepting knowledge). For
; answering a question, it might have an operator 'answer-question',
; whose arguments are an interlocutor and a question. (We want
; to potentially allow different behaviors towards different
; interlocutors). This operator would have to handle both the
; derivation of an answer and the verbal output. Is this even
; possible within a non-hierarchical planning framework?
;
; We should be able to handle this through computable effects:
; the effect is something like (say TED (answer-to? ?x)),
; where ?x is bound to the input question, and which upon evalu-
; ation becomes (say TED <some specific proposition>). Besides
; storing this effect in the agent's knowledge state as usual,
; we would also ensure that if the questioner is the user, the
; answer is actually printed to standard-output as a side-effect
; when executing 'answer-to?'. At this point the agent should also
; make the inference that the interlocutor knows the content of
; the answer, and (perhaps!) believes that content. This should be
; automatic from applying general knowledge to local facts that
; are noticed -- and certainly facts about the user (like those
; about the agent, TED) should be regarded as always being local
; to wherever the agent is. So the one thing required here (in
; addition to an appropriate 'answer-to?' function, of course)
; is that facts about the user always be treated as local in
; 'notice-new-local-facts'.
;
; 'Answer-to?' should handle both yes-no and wh-questions. The
; unifications that check what actions are possible in a given
; state should be able to distinguish speech act descriptions that
; specify a yes-no question from ones that specify a wh-question,
; or for that matter, from ones that specify a direct request or
; a fact. The interactive 'listen!' function should look at the
; form of the input and decide whether to insert
; (requests-answer User ?question), or
; (requests-action User ?action), or
; (offers-fact User ?fact),
; with appropriate values of the variables, of course.
;
; ABOUT PROCEDURALLY EVALUABLE (OR AT LEAST SIMPLIFIABLE) PREDS/FUNCS:
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Evaluable predicates and functions must either have names
; ending in "?", or be one of +,-,*,/,<,<=,=,>=,>.
;
; Some programs may allow for equality/inequality literals of form
; (EQ t1 t2), or (NEQ t1 t2), but this is not used here. Instead,
; we assume that in instantiating an operator, the bindings of
; distinct variables must be distinct. However, EQ and NEQ could
; be handled using corresponding evaluable predicates eq?, neq?.
;
;; SOME GLOBAL ENTITIES
;; ====================
; Note that *world-facts* are initialized in gridworld-definitions.lisp;
;~~~~~~~~~~~~~~~~~~~~~~~~ these are ALL the specific (atomic) facts
; Note also, *general-knowledge* is defined in gridworld-definitions.lisp;
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for now, general facts = general knowledge;
(defvar *plan* nil); shows the currently best sequence of future actions
;~~~~~~~~~~~~~~~~~~
(defvar *states* nil) ; sequence of states (where each state is a set of
;~~~~~~~~~~~~~~~~~~~~ ground predications), starting at present,
; corresponding to *plan*;
(defvar *inference-limit* 2) ; depth of forward inference;
;~~~~~~~~~~~~~~~~~~~~~~~~~~
;(defvar *curr-state-node* nil)
(defvar *real-history* nil) ; the sequence of actions (with parameter values)
; and events so far in the world
(defvar *TED-history* nil) ; the sequence of actions (with parameter values)
; taken so far from the agent's perspective
(defvar *operators* nil) ; names of the available operators;
; must be set by the user
(defvar *search-beam* nil) ; list of items, each of form (i . op-names),
;~~~~~~~~~~~~~~~~~~~~~~~~~ ; where i > 0 and op-names lists the op. names
; allowed at each step (to be set by the user)
;; SOME BASIC UTILITIES
;; ====================
(defun put (atm indic val) (setf (get atm indic) val))
;~~~~~~~~~~~~~~~~~~~~~~~~~
(defun unionf (x y) (union x y :test #'equal))
;~~~~~~~~~~~~~~~~~~
(defun memberf (x y) (member x y :test #'equal))
;~~~~~~~~~~~~~~~~~~
(defun intersectionf (x y) (intersection x y :test #'equal))
;~~~~~~~~~~~~~~~~~~~~~~~~~
(defun set-differencef (x y) (set-difference x y :test #'equal))
;~~~~~~~~~~~~~~~~~~~~~~~~~~~
(defun removef (lst1 lst2)
(let ((result lst2))
(dolist (x lst1)
(setq result (remove x result :count 1 :test #'equal))
)
result
)
)
(defun var (x) ; is x a variable, i.e., an atom with first character"?"
;~~~~~~~~~~~~~
(if (and x (symbolp x))
(char= (nth 0 (coerce (string x) 'list)) #\?)
nil ))
(defun *append (u v); append 2 lists where one or both may be T,
;~~~~~~~~~~~~~~~~~~~; interpreted here as trivial unifier, hence,
; like the empty list
(if (equal u T) v (if (equal v T) u (append u v))) )
(defun first-n (x n)
;~~~~~~~~~~~~~~~~~~~~
; Return the length-n prefix of x
(if (atom x) x (butlast x (max 0 (- (length x) n)))) )
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; ROUTINES FOR FINDING THE BINDINGS THAT MATCH GOALS TO A STATE ;;
;; ============================================================= ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun all-bindings-of-goals-to-fact-htable (goals fact-htable terms); Revised Dec. 2009
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Find all unifiers of the variables occurring in goals (a set
; of +ve & -ve literals, possibly containing variables) obtainable
; by matching the goals to the fact-htable (a set of +ve ground literals);
;
; Method: Here we just reorder the goals and extract all terms
; occurring in 'fact-htable', and then call the recursive routine
; (all-bindings-of-goals-to-fact-htable1 goals fact-htable terms) -- see
; this for further explanation.
;
(let ((gg goals) (ff fact-htable)
(wff-terms (remove-duplicates terms :test #'equal))
)
; Reorder goals so that positive goals come before negative
; goals, and for same-sign goals, goals with more variables
; precede ones with fewer variables, and for same-sign, same-
; number-of-variables goals, goals with more arguments precede
; ones with fewer arguments; this is to minimize work in matching;
;
(setq gg (sort (copy-list gg) #'> :key #'rank-for-goal-sorting))
(all-bindings-of-goals-to-fact-htable1 gg ff wff-terms)
)
); end of all-bindings-of-goals-to-fact-htable
(defun rank-for-goal-sorting (goal)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; The idea is to give highest ranks to goals that will tend to
; cut down the search space most quickly (i.e., have few matches).
; Evaluable expressions are given lowest rank, because (currently)
; goals containing evaluable expressions must be simplified to
; ones not containing such expressions (i.e., T, nil, or a goal
; containing only ordinary, nonevaluable preds/functions) before
; being matched to the "facts" of a given state.
;
; Assign a rank to 'goal' so that all positive goals have a higher
; rank than all negative goals, and among goals of the same sign,
; goals with fewer variables always have a higher rank than goals
; with more variables, and among goals of the same sign with the
; same number of variables, goals with more terms always have
; higher rank than goals with fewer terms. Assume that a predicate
; can have no more than 10 arguments (o/w ranks won't be exactly
; as stated). Finally lower the rank by a large amount if the goal
; contains an evaluable expression, so that its rank will be lower
; than that of any goal containing no evaluable expressions.
;
(let ((rank (if (poslit goal) 200 0))
(var-count (length (remove-duplicates (vars goal))))
(term-count+1
(if (poslit goal) (length goal) (length (second goal)))))
(decf rank (* 10 var-count))
(incf rank term-count+1)
(when (contains-evaluable-expr goal)
(decf rank 400)
)
rank
)
); end of rank-for-goal-sorting
(defun contains-evaluable-expr (expr)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(cond ((atom expr) nil)
((evaluable-func (car expr)) t)
((atom (car expr)); for atomic (car expr), need only check cdr
(if (member t (mapcar #'contains-evaluable-expr (cdr expr)))
t nil))
(t (if (member t (mapcar #'contains-evaluable-expr expr))
t nil))
)
); end of contains-evaluable-expr
(defun all-bindings-of-goals-to-fact-htable1 (goals fact-htable terms); Revised Dec. 2009 by Daphne Liu
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Find all unifiers of the variables occurring in goals (a set
; of +ve & -ve literals, possibly containing variables) obtainable
; by matching the goals to the fact-htable (a hashtable of
; (+ve) ground literals), using 'terms' as the names of all
; possible individuals (these are just the *distinct* terms
; occurring in 'fact-htable', precomputed for convenience).
; Method:
; 1. results := nil; {initialization}
; 2. uu := all-bindings-of-goal-to-fact-htable(first(gg),fact-htable,terms);
; 3. if rest(gg) = nil then return uu;
; 4. if uu = (t) (first goal matched exactly)
; then return all-bindings-of-goals-to-fact-htable1
; (rest(gg), fact-htable, terms);
; 5. For each u in uu:
; i. vv := all-bindings-of-goals-to-fact-htable1
; (rest(gg)_u, fact-htable, terms),
; where subscript _u indicates substitution using u;
; ii. if vv = nil then continue with next u in uu;
; iii. append to 'results' all the unifiers obtained by
; grafting u into the unifiers in vv;
; 6. return results.
;
(prog ((gg goals) g results uu vv)
(setq g (pop gg))
(setq uu (all-bindings-of-goal-to-fact-htable g fact-htable terms))
(when (null gg) (return uu))
(when (equal uu '(t))
(return (all-bindings-of-goals-to-fact-htable1 gg fact-htable terms))
)
(dolist (u (reverse uu)); just to end up with original order
(setq vv (all-bindings-of-goals-to-fact-htable1
(subst-unifier-in-wffs u gg) fact-htable terms))
(when vv
(setq vv (mapcar #'(lambda (v) (*append u v)) vv))
(setq results (append vv results))
)
)
(return results)
)
); end of all-bindings-of-goals-to-fact-htable1
(defun all-bindings-of-goal-to-fact-htable (g ff terms); Revised Dec. 2009 by Daphne Liu
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(if (poslit g)
(all-bindings-of-posgoal-to-fact-htable g ff)
(all-bindings-of-neggoal-to-fact-htable g ff terms)
)
)
(defun all-bindings-of-posgoal-to-fact-htable (g ff); Revised Dec. 2009 by Daphne Liu
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Before attempting to find the bindings of goal g to the facts ff,
; check if g contains an evaluable expression & if so simplify it.
; If the simplification yields T, then the list '(T) containing
; just the trivial unifier is returned (because "truth" matches
; any set of facts); if simplification yields nil, then the empty
; list () of unifiers is returned (because "falsity" matches no
; set of facts). If the simplified goal still contains an evaluable
; expression, then () is again returned (because we don't handle
; solving for variables embedded by computable functions). After
; these special cases have been treated, the unifier of (the
; possibly simplified) goal with each fact is found, and the
; non-nil values are returned.
(prog ((g1 g))
(when (contains-evaluable-expr g1)
(setq g1 (simplify-value g1))
(if (eq g1 t)
(return '(t))
(when (or (eq g1 nil)
(contains-evaluable-expr g1))
(return nil)
)
)
)
(return (remove-if #'null
(mapcar #'(lambda (f) (unifier g f))
(possible-positive-unifiers g ff))
)
)
)
); end of all-bindings-of-posgoal-to-fact-htable
(defun possible-positive-unifiers (g ff); Revised Dec. 2009 by Daphne Liu
(let* ((shortest-leng 0) hash-value hash-leng
shortest-hash-value (shortest-index -1)
(keys (generate_allkeys_from_hashkey (convert_pred_to_hashkey g)))
(keys-leng (length keys))
(first-non-null-hash-value-reached 'NIL)
)
(dotimes (i keys-leng)
(setq hash-value (gethash (nth i keys) ff))
(when (not (null hash-value))
(setq hash-leng (car hash-value))
(when (and (> hash-leng 0)
(or (> shortest-leng hash-leng) (null first-non-null-hash-value-reached))
)
(setq shortest-leng hash-leng)
(setq shortest-index i)
(setq shortest-hash-value (cdr hash-value))
(setq first-non-null-hash-value-reached 'T)
)
)
)
shortest-hash-value
)
)
(defun all-bindings-of-neggoal-to-fact-htable (g ff terms); Revised Dec. 2009 by Daphne Liu
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(complement-unifiers
(all-bindings-of-posgoal-to-fact-htable (second g) ff) (vars g) terms
)
)
(defun alphabetically-order (uu); alphabetically order variables in
; the unifiers listed in uu
(mapcar #'(lambda (u)
(if (eq u t) t
(sort (copy-list u) #'string<
:key #'(lambda (x) (string (car x))) )))
uu
)
)
(defun complement-unifiers (uu vars terms)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Find the bindings of 'vars', with elements of 'terms' as possible
; binders, that DON'T coincide with any bindings in 'uu'.
;
; Method in the general case: subtract uu from the set of all bindings
; (where we're sure the subtraction works because the order of variables
; in unifiers is first made uniform).
;
; The elements of uu are generally of form ((var1 . val1) ...
; (vark . valk)), where the var1, ..., vark are the same (and in the
; same order) in all cases. However, it is possible that uu is nil
; while the given 'vars' are nonempty, in which case all possible
; bindings of the 'vars' should be returned -- that's why the 'vars'
; are separately supplied. Also uu might be (t) (indicating that the
; positive form of a negative ground literal was matched to a state),
; in which case the result should be nil.
;
(when (null vars); then uu must be nil or '(t)
(return-from complement-unifiers (if (null uu) '(t) nil))
)
(when (null terms); unexpected condition
(return-from complement-unifiers nil)
)
(let (ordered-vars ordered-uu vv)
; we keep variables in lexicographic order, so that set-
; differencing will work (e.g., the set-difference between
; (((?x . a) (?y . b))) & (((?y . b) (?x . a))) should be nil)
(setq ordered-vars
(sort (copy-list vars) #'string<
:key #'(lambda (x) (string x))))
(setq ordered-uu (alphabetically-order uu))
(setq vv (all-bindings ordered-vars terms))
; `all-bindings' keeps the variables in the given order in
; the list of unifiers produced as output;
(reverse (set-differencef vv ordered-uu))
)
); end of complement-unifiers
(defun all-bindings (vars terms); cons each var with each term
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(let (vv ww)
(cond ((and vars terms)
(setq vv (mapcar #'(lambda (x) (cons (car vars) x)) terms))
(setq ww (all-bindings (cdr vars) terms))
(combine-sets-of-unifiers (mapcar #'list vv) ww)
)
(t nil)
)
)
); end of all-bindings
(defun combine-sets-of-unifiers (uu vv);
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; concatenate each unifier in uu with each unifier in vv;
; the variables in uu will precede those in vv;
(when (null uu) (return-from combine-sets-of-unifiers vv))
(when (null vv) (return-from combine-sets-of-unifiers uu))
(let (result)
(dolist (u (reverse uu))
(setq result
(append (mapcar #'(lambda (v) (*append u v)) vv) result)
)
)
result
)
); end of combine-sets-of-unifiers
;; The following two programs ignore the possibility of EQ, NEQ
;; literals for the time being..
(defun poslits (lits); all positive lits among 'lits'
;~~~~~~~~~~~~~~~~~~~~~
(remove-if-not #'poslit lits)
)
(defun neglits (lits); all negatively embedded atoms among 'lits'
;~~~~~~~~~~~~~~~~~~~~~
(mapcar #'second ; drop "not"s
(remove-if-not #'neglit lits))
)
(defun poslit (lit) (not (neglit lit)))
;~~~~~~~~~~~~~~~~~~
(defun neglit (lit) (and (listp lit) (eq (car lit) 'not)))
;~~~~~~~~~~~~~~~~~~
(defun collect-terms (lits); all terms occurring in literals 'lits'
;~~~~~~~~~~~~~~~~~~~~~~~~~~~
(remove-duplicates ;; NB: we use :test #'equal for generality
(apply #'append (mapcar #'args lits)) :test #'equal)
)
(defun collect-terms-duplicate (lits); all terms occurring in literals 'lits'
;~~~~~~~~~~~~~~~~~~~~~~~~~~~
(apply #'append (mapcar #'args lits))
)
(defun vars (lit); bag of variables occurring in literal 'lit'
;~~~~~~~~~~~~~~~~~
(if (atom lit) nil (remove-if-not #'var (args lit)))
)
(defun collect-vars (lits); set of vars occurring in literals 'lits'
;~~~~~~~~~~~~~~~~~~~
(remove-duplicates (apply #'append (mapcar #'vars lits)))
)
(defun args (lit); return list of args occurring in literal 'lit'
;~~~~~~~~~~~~~~~~~~~
(cond ((atom lit) nil)
((eq (car lit) 'not) (cdr (second lit)))
(t (cdr lit))
)
)
(defun find-all-positive-bindings (poslits db);
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Find all sets of bindings of the variables occurring in poslits (a
; set of positive literals) obtainable by matching poslits to the db
; (a set of positive ground literals);
;
(prog (results phi u remlits vv)
(if poslits
(setq phi (car poslits))
(return '(T)); T is the trivial unifier
)
(dolist (phi1 (if (equal (car phi) 'EQ)
(equalities db)
db
)
)
(setq u (unifier phi phi1))
(when u
(setq remlits
(mapcar #'(lambda (x) (subst-unifier u x))
(cdr poslits))
)
(setq vv (find-all-positive-bindings remlits db))
(when vv
(setq results
(unionf (mapcar #'(lambda (v) (*append u v)) vv)
results)
)
)
)
)
(return results)
)
); end of find-all-positive-bindings
(defun equalities (db);
;~~~~~~~~~~~~~~~~~~~~~~
; Find all equalities of form (EQ c c) where c is some constant appearing
; in db (a set of positive, function-free ground literals).
(let ((constants (remove-duplicates (reduce #'append (mapcar #'cdr db)))))
(mapcar #'(lambda (x) (list 'EQ x x)) constants)
)
)
(defun unifier (lit1 lit2);
;~~~~~~~~~~~~~~~~~~~~~~~~~
; Unify two literals (where `lit2' for our purposes is ground),
; if possible, returning the unifier if it exists and nil otherwise.
; For equal ground literals, the unifier is T, else it is a list
; ((var1 . term1) ... (vark . termk)). Variables are NOT renamed,
; i.e., a variable occurring in both lit1 and lit2 will be uniformly
; bound to a unique term. Variables are expected to be Lisp symbols
; starting with `?'. Substitution for variables of lit1 is preferred
; to substitution for variables of lit2 (allowed for generality).
(if (not (equal (car lit1) (car lit2)))
nil ; must be same pred
(if (equal (cdr lit1) (cdr lit2))
T ; trivial unifier
(if (equal (car lit1) 'not)
(unifier (second lit1) (second lit2))
(if (not (equal (length lit1) (length lit2)))
nil
((lambda (x) (if (null x)
T; a null arglist unifier
; implies (trivial) success
(if (member nil x)
nil
x
)
)
); a null element indicates a failed substitution
(arglist-unifier (cdr lit1) (cdr lit2))
)
)
)
)
)
)
(defun subst-unifier (uni wff);
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Substitute for variables of wff as specified by unifier uni.
; uni may be T (trivial unifier, for which we return wff) or of form
; ((var1 . term1) ... (vark . termk))
(prog ((wff-out wff))
(when (equal uni t) (return wff))
(dolist (pair uni)
(setq wff-out (subst (cdr pair) (car pair) wff-out))
)
(return wff-out)
)
)
(defun subst-unifier-in-wffs (uni wffs);
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(mapcar #'(lambda (wff) (subst-unifier uni wff)) wffs)
)
(defun arglist-unifier (list1 list2)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Unify equal-length lists of (perhaps functional) terms where the
; terms in `list1' may be, or may contain, variables (Lisp symbols
; with initial character `?'). Here result nil indicates trivial
; success, & (nil) indicates failure.
(if (null list1)
nil
(if (equal (car list1) (car list2))
(arglist-unifier (cdr list1) (cdr list2))
(if (var (car list1))
(cons (cons (car list1) (car list2))
(arglist-unifier
(subst (car list2) (car list1) (cdr list1))
(subst (car list2) (car list1) (cdr list2))
)
)
; initial complex terms?
(if (and (listp (car list1)) (listp (car list2))
(= (length (car list1)) (length (car list2)))
)
(let ((uni (arglist-unifier (car list1) (car list2))))
(append uni
(arglist-unifier
(subst-unifier uni (cdr list1))
(cdr list2)
)
)
)
'(nil)
)
)
) ; nil in unifier list signals failure
)
); end of arglist-unifier
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; ROUTINES FOR DEFINING AND INSTANTIATING ACTION OPERATORS ;;
;; ======================================================== ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defstruct op ; an operator (type of action), or instance of it
;~~~~~~~~~~~~~
name ; name of the action type (even for an instance)
; whose value (under eval) is this operator;
instance ; name of this instance (or nil, for an operator),
; whose value (under eval) is this operator instance;
pars ; variables, starting with "?" (e.g., ?x, ?y, ...),
; or specific values (ground terms), for instances;
preconds ; a list of positive or negative literals, containing
; parameters or constants as arguments; evaluable
; predicates (<, <=, =, >=, >, or ones ending in "?")
; and functional terms, including evaluable ones
; (+, -, *, /, or ones ending in "?") are allowed
; as well;
effects ; a list of positive or negative literals -- same
; syntax as for preconds; again we allow evaluable
; predicates and functional expressions, which can
; be Lisp-eval'ed whenever they don't embed variables.
; e.g.,
; (+ 2 (weight-of? ?obj)).
;
; After ?obj has been replaced by, say, Box3, this
; would be automatically evaluated as
; (eval (+ 2 (weight-of? 'Box3)));
; Note that in this case the user-supplied 'weight-of?'
; Lisp function would have to handle a symbolic
; argument (and quite possibly, access gridworld
; knowledge in the evaluation);
time-required ; estimated time required, which should be numerical
; or a lisp expression that can be evaluated if all
; parameters therein (if any) are replaced by
; specific values; (EVALUATION NOT IMPLEMENTED YET)
value ; the inherent reward (or cost) of the operator,
; which could be numerical or a lisp expression
; which can be evaluated if all parameters therein
; (if any) are replaced by specific values;
); end of op
(defun instantiate-op (op uni); Revised 2009 by Daphne Liu
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Form an instance of action type 'op', returning a (generated)
; name of the instance, as a variant of the name of 'op'
; The procedure is formulated in such a way that it could be
; used equally well for partial instantiation as for full
; instantiation of an operator.
;
(when (null uni) (return-from instantiate-op nil))
(let* ((name (op-name op))
(instance (gensym (string name)))
(pars (op-pars op))
(preconds (op-preconds op))
(effects (op-effects op))
(time-required (op-time-required op))
(value (op-value op))
)
(when (not (eq uni t)); not the trivial unifier
(dolist (u uni)
(setq pars (subst (cdr u) (car u) pars))
)
;(format t "~% NAME ~a ~a ~%" name pars)
(dolist (u uni)
(setq preconds (subst (cdr u) (car u) preconds))
)
(dolist (u uni)
(setq effects (subst (cdr u) (car u) effects))
)
;(format t "~% BEFORE EFFECTS ~A ~%" effects)
(setq effects (mapcar #'simplify-value effects))
(when (evaluable-func (car effects))
(setq effects (simplify-value effects))
)
;(format t "~% AFTER EFFECTS ~A ~%" effects)
(dolist (u uni)
(setq time-required (subst (cdr u) (car u) time-required))
)
;(format t "~% BEFORE TIME~%")
(setq time-required (simplify-value time-required))
;(format t "~% AFTER TIME ~%")
(dolist (u uni)
(setq value (subst (cdr u) (car u) value))
)
;(format t "~% BEFORE VALUE~%")
(setq value (simplify-value value))
;(format t "~% AFTER VALUE ~A ~A~%" name value)
)
(set instance
(make-op :name name
:instance instance
:pars pars
:preconds preconds
:effects effects
:time-required time-required
:value value ))
instance ; return name of instance
)
); end of instantiate-op
(defun simplify-value (expr); Revised 2009 by Daphne Liu
;~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Evaluate/simplify a func/pred expression expr that may contain
; (a) user-defined Lisp func/preds (ones with a name ending in "?"),
; (b) arithmetic functions +,-,*,/, or relations <,<=,=,>=,>, or
; (c) ordinary logical func/preds (i.e., ones that are interpreted
; without being Lisp-evaluated).
;
; "Evaluation" here really means simplification, and is only
; carried out to the extent that the arguments of the outermost
; func/pred are variable-free. For example, an expression (+ 1 1 ?x)
; is not further simplified, and (+ 1 (* 2 3) ?x) is simplified
; just to (+ 1 6 ?x). The arguments of each func/pred in expr are
; simplified if possible, and if the func/pred is evaluable and
; its arguments are variable-free, it is procedurally applied
; to its argument before a result is returned. If it is not
; evaluable, the expr is returned unchanged except for the
; simplification of its args (if possible).
;
; Note that an expression like (loc-of Robbie) would be returned
; unchanged, whereas (loc-of? Robbie) would be evaluated, with
; the argument in effect quoted. (The world model might be accessed
; for the evaluation.) An expression like (+ 1 cost) would cause
; an error, because an attempt would be made to apply the Lisp
; '+' function to arguments 1 and 'cost. (So if 'cost' is to be
; obtained in some implicit way, e.g., by consulting gridworld
; knowledge, then a new function such as '+?' or 'sum?' should
; be defined and used.)
;
;(format t "~% expr is ~A ~A ~%" expr (atom expr))
(cond ((atom expr) expr)
((and (not (contains-var expr))
(evaluable-func (car expr))) ; +,-,*,/,<,<=,=,>=,>,random,
; or ends in "?"
;(prog2
;(format t "~% here ~A ~%" expr)
(apply (car expr) (mapcar #'simplify-value (cdr expr))))
((or (eq (car expr) 'answer_to_whq.actual?)
(eq (car expr) 'answer_to_whq?))
(apply (car expr) (mapcar #'simplify-value (cdr expr))));(mapcar #'simplify-value (cdr expr))))
(t (cons (car expr) (mapcar #'simplify-value (cdr expr))))
)
)
(defun evaluable-func (f) ; must be symbol, & end in ? or be one
; of +,-,*,/,<,<=,=,>=,>,random
(and (symbolp f) (or (member f '(+ - * / < <= = >= >))
(eq f 'random)
(char= (car (last (coerce (string f) 'list))) #\?)))
)
(defun contains-var (expr)
;~~~~~~~~~~~~~~~~~~~~~~~~~~
; Does Lisp expression 'expr' contain a variable (atom starting
; with "?") at any structural level?
;
(cond ((var expr) t)
((atom expr) nil)
((find-if #'contains-var expr) t)
(t nil) ))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; ROUTINES FOR FORWARD CHAINING AND PLAN SELECTION/EXECUTION ;;
;; ========================================================== ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defstruct state-node ; a node in a tree of states generated
; by forward search;
terms ; a list of terms in the wffs in wff-htable
name ; a (generated) atomic name, whose value
; (via eval) is this state-tree node
wff-htable ; a hashtable of ground atomic wffs defining
; the state (though the ground requirement,
; and prohibition of negations may
; eventually be relaxed);
children ; a list ((action-name_1 . state-node-name_1)
; ... (action-name_k . state-node-name_k))
; pairs, where each action-name_i is the name
; of an action instance and state-node-name_i
; is the name of the corresponding successor
; state; some of these children might have no
; successors at a given time, others might
; have successors to various depths;
operators ; list of the names of the operators that
; were used so far in generating children;
; more might yet be added, generating further
; children;
parent ; the (action-name . state-node-name) pair
; which generated this state. For the very
; first state in Gridworld, this is nil;
local-value ; a numerical value for the "desirability"
; (reward) of that state, presumably
; computed by taking the initial state to
; have 0 value, and then computing changes
; in state-value based on the effects of
; each action taken since that initial state
; (these values are in general estimates,
; because states are in general predicated
; rather than real);
forward-value ; the estimated cumulative value of the best
; plan starting at this state (not counting
; the local-value at the present state);
; this counts both the inherent values of
; the actions of the best plan and the states
; generated by that plan.
); end of state-node
(defun chain-forward (state-node search-beams)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Chain forward from the given state (hashtable of +ve ground wffs),
; conducting a beam search using the operators and beam widths
; specified in 'search-beams', and return the forest of plans,
; attached to 'state-node' with the best plan first (i.e.,
; following leftmost branches in the leftmost tree). The idea
; is to call this program, and then actually execute the first
; step of the best plan, and then iterate. If we stick to the
; same beam-width after executing the first step, and the beam-
; widths for successive steps are decreasing, then after each
; step the forward search just adds some more branches to the
; plan-tree, rather than starting from scratch.
;
; The actions formed as children of the given state-node are
; provided as output (along with their values), but the "real"
; output consists of the changes made to the planning tree
; emanating from the given state-node (whose leftmost, i.e.,
; seemingly best, action sequence also becomes available as
; the value of *plan*, and whose corresponding leftmost state
; sequence becomes available as *states*, where a state is
; represented as a set of ground predications).
;
; state-node: a structured state node, from which we are
; to chain forward (in general, adding to children that
; are already present);
; search-beams: a list ((n_1 . ops_1) ... (n_k . ops_k)), where the
; n_i are numerical upper bounds on the number of distinct
; successor actions to be searched further from, when adding
; the ith step of any plan obtained in the forward-chaining,
; and each ops_i is a list of operators (specified by name)
; to be considered (in addition to ones that may have been
; considered in a previous iteration) when adding possible
; ith steps to any plan.
;
(if (null search-beams) (return-from chain-forward nil))
(let* ((state-node-name (state-node-name state-node))
(wff-htable (state-node-wff-htable state-node))
(children (state-node-children state-node))
(operators (state-node-operators state-node))
(beam (car search-beams))