-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprimitive.lisp
615 lines (505 loc) · 16.1 KB
/
primitive.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
;;;; FILE: primitive.lisp
;;;; AUTHORS: Manuel Casas Barrado, Marcos Díez García
;;;; DESCRIPTION: Building Planification Graphs
;;;; - ABSTRACTION LAYER 0 -
;;; TYPED DATA MECHANISM.
;;; Will allows us to distinguish the basic elements of the
;;; Planification Graph.
;;; Basic elements: literal, predicate, action ...
;; Constructor.
;; Creates an object with a label attached
(defun attach-type (typ contents)
(cons typ contents))
;; Selectors.
(defun typ (object)
(car object))
(defun contents (object)
(cdr object))
;; Functions over objects.
;; eq-type?
;; Checks if the 2 objs given have the same type, and the type is
;; equal to 'nametype'. Example: (eq-type? o1 o2 'literal)
(defun eq-type? (obj1 obj2 nametype)
(and (equal (typ obj1) nametype)
(equal (typ obj2) nametype)))
;; gen-pairs
;; Returns the list of all the possible object pairs given the set of
;; objects.
(defun gen-pairs (objects)
(let ((powerset (gen-powerset objects)))
(loop for subset in powerset
if (= (length subset) 2)
collect subset)))
;; gen-powerset
;; Returns the list of all possible subsets of objects.
(defun gen-powerset (objects)
(if (null objects)
(list nil)
(let ((prev (gen-powerset (cdr objects))))
(append (mapcar #'(lambda (elt) (cons (car objects) elt))
prev)
prev))))
;;;; - ABSTRACTION LAYER 1 -
;;; LITERAL
;; Constructor.
;; Creates a literal for a given name ('A, 'B, 'ManosLimpias, ...)
;; and a given logical value (t or nil)
;; Example: (make-lit 'A nil)
(defun make-lit (name val)
(attach-type 'literal
(cons name val)))
;; Selectors.
;; name-lit
;; Returns the symbolic name of the literal.
(defun name-lit (l)
(car (contents l)))
;; val-lit
;; Returns the logical value of a given literal.
(defun val-lit (l)
(cdr (contents l)))
;; Functions over literals.
;; lit?
;; Checks if the object is a literal.
(defun lit? (obj)
(equal (typ obj)
'literal))
;;; PREDICATE
;; Constructor.
(defun make-pred (name objects val)
(attach-type 'predicate
(cons `(,name ,objects)
val)))
;; Selectors.
;; name-pred
;; Returns the symbolic name of a given predicate.
(defun name-pred (p)
(caar (contents p)))
;; objs-pred
;; Returns the terms of a given predicate.
(defun objs-pred (p)
(cadar (contents p)))
;; val-pred
;; Returns the logical value of a given predicate.
(defun val-pred (p)
(cdr (contents p)))
;; Functions over predicates
;; pred?
;; Checks if the object is a predicate.
(defun pred? (obj)
(equal (typ obj)
'predicate))
;;; VARIABLE
;; Constructor.
(defun make-var (name)
(attach-type 'variable
`(,name)))
;; Selectors.
(defun name-var (v)
(car (contents v)))
(defun var? (obj)
(equal (typ obj)
'variable))
;;; CONJUNCTION
;; Constructor.
(defun conj (objects)
(attach-type 'conjuncion
objects))
;; Functions over conjunctions.
;; nth-conj
;; Returns the 'nth' element of a given conjunction.
(defun nth-conj (conj n)
(if (= n 0)
(nth n conj)
(car
(nth n conj))))
;;; LOGIC NOT (predicates and literals)
(defun not-obj (obj)
(cond
((lit? obj)
(make-lit (name-lit obj)
(not (val-lit obj))))
((pred? obj)
(make-pred (name-pred obj)
(objs-pred obj)
(not (val-pred obj))))))
;;;; - ABSTRACTION LAYER 2 -
;;; STATE
;; Constructor.
;; Returns a 'state' for a given conjunction.
(defun make-state (&key (name '-) conj)
(attach-type 'state
(cons name
(contents conj))))
;; Selectors.
(defun name-state (state)
(car (contents state)))
(defun objs-state (state)
(cdr (contents state)))
;; Functions over states.
(defun state? (obj)
(equal (typ obj) 'state))
;; reach-target?
;; Returns 'true' if the target state is found in the current state,
;; given the terms of both states.
(defun reach-target? (current-terms target-terms)
(let ((target-term (car target-terms)))
(if (equal target-terms ())
t
(and (find target-term current-terms :test #'equal)
(reach-target? current-terms (cdr target-terms))))))
;;; ACTION
;; Constructor.
(defun make-action (name preconditions effects)
(attach-type 'action
`(,name ,(conj preconditions) ,(conj effects))))
;; Selectors.
;; pres
;; Returns the preconditions of a given action.
(defun pres (action)
(contents (nth 2 action)))
;; effs
;; Returns the effects of a given action.
(defun effs (action)
(contents (nth 3 action)))
;; Functions over actions.
(defun action? (obj)
(equal (typ obj) 'action))
;; persistence?
;; Checks if the given action is a 'persistence action'.
(defun persistence? (a)
(equal (pres a) (effs a)))
;;; UNIFICATION
;;; This is a simplified version of unification. We restrict ourselves
;;; to literals and predicates, we will not consider variables.
;; Unification for literals.
;; Two given literals will 'unify' if and only if their names and their
;; values are the same.
;; Unification for predicates.
;; Two given predicates will 'unify' if and only if their names, values
;; and terms are the same.
;; The order of the terms matters: 'p(A B)' is not the same as 'p(B A)'
;; applicable-action?
;; Returns true if all the preconditions are found in the state given.
;; Testing by #'equal ensures that names, values and terms are the same.
(defun applicable-action? (terms preconds)
(let ((pre (car preconds)))
(cond
((equal preconds ())
t)
(T ; otherwise
(and (find pre terms :test #'equal)
(applicable-action? terms (cdr preconds)))))))
;;; MUTEX & LINK
;;; Mutex represents the conflict between 2 literals, predicates or
;;; actions.
;;; Link represents that some literal or predicate satifies a specific
;;; precondition of an action. Also represents the effects generated by
;;; some action.
;; Constructor.
(defun make-edge (obj1 obj2 label)
(attach-type label ; mutex or link
(cons obj1 obj2)))
;; Selectors.
;; source
;; Returns the first object of a given link.
(defun source (link)
(let ((link-typ (typ link)))
(if (or (equal link-typ 'link)
(equal link-typ 'mutex))
(car (contents link))
(error "Argument is not a 'link' nor 'mutex'."))))
;; target
;; Returns the second object of a given link.
(defun target (link)
(let ((link-typ (typ link)))
(if (or (equal link-typ 'link)
(equal link-typ 'mutex))
(cdr (contents link))
(error "Argument is not a 'link' nor 'mutex'."))))
(defun label (link)
(let ((link-typ (typ link)))
(if (or (equal link-typ 'link)
(equal link-typ 'mutex))
link-typ
(error "Argument is not a 'link' nor 'mutex'."))))
;; Functions to check conflicts.
;; Literals and predicates.
(defun opposite? (obj1 obj2)
(cond
((eq-type? obj1 obj2 'literal)
(and
(not (eq (val-lit obj1) ; different values
(val-lit obj2)))
(equal (name-lit obj1) ; same names
(name-lit obj2))))
((eq-type? obj1 obj2 'predicate)
(and
(not (eq (val-pred obj1) ; different values
(val-pred obj2)))
(equal (name-pred obj1) ; same names
(name-pred obj2))
(equal (objs-pred obj1) ; same objects
(objs-pred obj2))))
(T (error "Wrong type of arguments."))))
;; Actions.
(defun conflict? (terms1 terms2)
(let ((nxt-term (car terms1)))
(cond
((or (equal terms1 '())
(equal terms2 '()))
nil)
((find (not-obj nxt-term)
terms2
:test #'equal)
T)
;otherwise
(T (conflict? (cdr terms1)
terms2)))))
;; interference?
;; Returns 'true' if exists an interference conflict between 2 actions.
(defun interference? (action1 action2)
(cond
((conflict? (effs action1)
(pres action2))
T)
((conflict? (effs action2)
(pres action1))
T)
(T nil)))
;; Competing needs conflict
(defun inconsistency-pres? (action1 action2)
(conflict? (pres action1)
(pres action2)))
;; Inconsistency conflict
(defun inconsistency-effs? (action1 action2)
(conflict? (effs action1)
(effs action2)))
;; Auxiliar functions over mutexes.
;; link-all-to-all
;; When 2 actions have conflict we have to link all the effects of one
;; action with the effects of the other action. This function returns
;; a list with all those mutexes for those 2 actions.
(defun link-all-to-all (effs-pairs)
(let ((effs-pair (car effs-pairs)))
(if (equal effs-pairs ())
()
(let ((eff1 (car effs-pair))
(eff2 (cadr effs-pair)))
(cons (make-edge eff1 eff2 'mutex)
(link-all-to-all (cdr effs-pairs)))))))
;; remov-duplicates
;; Returns the list of mutex without duplicates
;; Example:
;; mutex1: (p, q)|
;; mutex2: (q, p)| -----> result of filtering: (p, q)
;; mutex3: (p, q)|
(defun remov-duplicates (unexplored)
(let ((mutex (car unexplored)))
(if (equal unexplored ())
()
(if (or (find mutex
(cdr unexplored)
:test #'equal)
(find (make-edge (target mutex) (source mutex) 'mutex)
(cdr unexplored)
:test #'equal))
(remov-duplicates (cdr unexplored))
(cons mutex
(remov-duplicates (cdr unexplored)))))))
;;;; - ABSTRACTION LAYER 3 -
;;; LAYERS
;; Constructors.
(defun make-action-layer (actions mutexes links)
(attach-type 'action-layer
(list actions mutexes links)))
(defun make-state-layer (state mutexes links)
(attach-type 'state-layer
(list state mutexes links)))
;; Functions over layers.
(defun action-layer? (layer)
(equal (typ layer) 'action-layer))
(defun state-layer? (layer)
(equal (typ layer) 'state-layer))
;; Selectors.
(defun actions (layer)
(if (action-layer? layer)
(car (contents layer))
(error "Wrong type of layer.")))
(defun state (layer)
(if (state-layer? layer)
(car (contents layer))
(error "Wrong type of layer.")))
(defun mutexes (layer)
(cadr (contents layer)))
(defun links (layer)
(caddr (contents layer)))
;;;; - ABSTRACTION LAYER 4 -
;;; AUXILIAR FUNCTIONS FOR GENERATION OF LAYERS
;; gen-persistent-actions
;; Returns the list of persistent actions for a given state.
;; We will use as the name of each action the name of the term in the
;; state. Example:
;; term -> p
;; persistent-action -> name: p, pres: {p}, effs: {p}
(defun gen-persistent-actions (terms)
(let ((term (car terms)))
(cond
((equal terms ())
())
((lit? term)
(cons (make-action (name-lit term) (list term) (list term))
(gen-persistent-actions (cdr terms))))
((pred? term)
(cons (make-action (name-pred term) (list term) (list term))
(gen-persistent-actions (cdr terms)))))))
;; gen-new-state-effs
;; Returns the set of the effects, which constitute the new state,
;; of the actions given.
(defun gen-new-state-effs (actions)
(let ((action (car actions)))
(if (equal actions ())
()
(remove-duplicates (append (effs action)
(gen-new-state-effs (cdr actions)))
:test #'equal))))
;; link-state-to-actions
;; Returns the listing of links that connect a term of a state
;; with those actions that the term satisfies.
;; Example of use:
;; (link-state-to-actions (objs-state st5) (list a5) (list a5))
;;
(defun link-state-to-actions (state actions)
(link-state-to-actions* (objs-state state) actions actions))
(defun link-state-to-actions* (terms unexplored actions-record)
(let ((term (car terms))
(action (car unexplored)))
(cond
((equal terms ())
())
((equal unexplored ()) ; all actions explored for term
(link-state-to-actions* (cdr terms) ; next term
actions-record ; reset unexplored
actions-record))
((not (equal (find term (pres action) :test #'equal)
nil))
(cons (make-edge term action 'link)
(link-state-to-actions* terms ; keep current term as next
(cdr unexplored) ; next action
actions-record)))
; otherwise
(T (link-state-to-actions* terms ; keep current term as next
(cdr unexplored) ; next action
actions-record)))))
;; link-actions-to-state
;; Returns the listing of links that connect an action with its
;; correspondant effects in the new state.
(defun link-actions-to-state (actions new-state)
(let ((action (car actions)))
(if (equal actions ())
()
(append (link-action-to-state action (effs action) new-state)
(link-actions-to-state (cdr actions) new-state)))))
(defun link-action-to-state (action effs new-state)
(let ((eff (car effs)))
(if (equal effs ())
()
(let ((term (find eff (objs-state new-state) :test #'equal)))
(if (not (equal term nil))
(cons (make-edge action term 'link)
(link-action-to-state action (cdr effs) new-state))
(link-action-to-state action (cdr effs) new-state))))))
;; gen-actions-mutexes
;; Returns the list of mutexes between actions given
;; the list of pairs of actions.
(defun gen-actions-mutexes (actions-pairs)
(let ((actions-pair (car actions-pairs)))
(if (equal actions-pairs ())
()
(let ((action1 (car actions-pair))
(action2 (cadr actions-pair)))
(if (or (interference? action1 action2)
(inconsistency-pres? action1 action2)
(inconsistency-effs? action1 action2))
(cons (make-edge action1 action2 'mutex)
(gen-actions-mutexes (cdr actions-pairs)))
(gen-actions-mutexes (cdr actions-pairs)))))))
;; gen-opposite-terms-mutexes
;; Returns the list of mutexes between opposite terms, given the
;; list of pairs of terms.
(defun gen-opposite-terms-mutexes (terms-pairs)
(let ((terms-pair (car terms-pairs)))
(if (equal terms-pairs ())
()
(let ((term1 (car terms-pair))
(term2 (cadr terms-pair)))
(if (opposite? term1 term2)
(cons (make-edge term1 term2 'mutex)
(gen-opposite-terms-mutexes (cdr terms-pairs)))
(gen-opposite-terms-mutexes (cdr terms-pairs)))))))
;; gen-conflict-terms-mutexes
;; Returns the list of mutexes between those pairs of terms produced
;; by conflictive actions.
(defun gen-conflict-terms-mutexes (actions-mutexes)
(let ((actions-mutex (car actions-mutexes)))
(if (equal actions-mutexes ())
()
(let ((action1 (source actions-mutex))
(action2 (target actions-mutex)))
(remov-duplicates
(append (link-all-to-all (gen-pairs (remove-duplicates
(append (effs action1)
(effs action2))
:test #'equal)))
(gen-conflict-terms-mutexes (cdr actions-mutexes))))))))
;;;; - TOP ABSTRACTION LAYER -
;; gen-actions-layer
;; Returns for a given state-layer, the layer of actions available
;; (though not necessarily applicable) to that state.
(defun gen-actions-layer (state actions)
(let* ((persistents (gen-persistent-actions (objs-state state)))
(mutexes (gen-actions-mutexes
(gen-pairs (append actions persistents))))
(links (link-state-to-actions state
(append actions persistents))))
(make-action-layer (append actions persistents)
mutexes
links)))
;; gen-state-layer
;; Returns for a given layer of actions, the new state layer produced
;; by those actions.
(defun gen-state-layer (actions-layer)
(let* ((new-effs (gen-new-state-effs
(actions actions-layer)))
(new-state (make-state :conj (conj new-effs)))
(mutexes (remove-duplicates ; action-conflictive and opposite term
(append (gen-opposite-terms-mutexes
(gen-pairs (objs-state new-state)))
(gen-conflict-terms-mutexes
(mutexes actions-layer)))
:test #'equal))
(links (link-actions-to-state (actions actions-layer)
new-state)))
(make-state-layer new-state mutexes links)))
;; make-graph
;; Returns the layers generated throughout the building of
;; the planification graph. Given:
;; initial layer as the 'current-layer',
;; target-layer' containing the target state,
;; set of actions of problem domain,
;; accumulator of 'layers' containing the initial layer.
(defun make-graphplan (current-layer target-layer actions layers)
(if (or (reach-target? (objs-state (state current-layer))
(objs-state (state target-layer)))
(equal current-layer
(caddr layers))) ; previous state-layer
layers
(let* ((actions-layer (gen-actions-layer (state current-layer) actions))
(new-state-layer (gen-state-layer actions-layer)))
(make-graphplan new-state-layer
target-layer
actions
(append new-state-layer actions-layer layers)))))
;;;; ------------------------------------------------------------
;;;; T E S T
; uncomment next line to load the 'tests' file
(load "tests.lisp")