1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package zeus.actors;
25
26 import java.util.*;
27 import zeus.util.*;
28 import zeus.concepts.*;
29
30 public class Decomposition extends Hashtable {
31 protected Vector constraints;
32
33 protected Vector links;
34 protected int node_pointer = -1;
35 protected String root = null;
36 protected Vector nodeList = new Vector();
37 protected Planner planner = null;
38
39
40
41 public Decomposition () {
42 ;
43 }
44
45 public Decomposition(Planner planner, String key, PlanRecord parent,
46 Vector path, Goal goal, SummaryTask task) {
47
48 this.planner = planner;
49 links = task.links();
50 constraints = task.constraints();
51
52 boolean first_time = true;
53 String rightNode, leftNode;
54 Enumeration enum;
55 TaskLink link;
56 Hashtable pairs = new Hashtable();
57 KeyValue st;
58 Vector temp, curr = new Vector();
59 curr.addElement(TaskNode.END);
60 int count = 0;
61 while( !curr.isEmpty() ) {
62 temp = new Vector();
63 enum = links.elements();
64 while( enum.hasMoreElements() ) {
65 link = (TaskLink)enum.nextElement();
66 rightNode = link.getRightNode();
67 if ( curr.contains(rightNode) ) {
68 leftNode = link.getLeftNode();
69 if ( !leftNode.equals(TaskNode.BEGIN) ) {
70 if ( !temp.contains(leftNode) )
71 temp.addElement(leftNode);
72
73 if ( !this.containsKey(leftNode) ) {
74 this.add(task.getNode(leftNode));
75 st = new KeyValue(leftNode,count++);
76 Assert.notFalse( pairs.put(st.key,st) == null );
77 }
78 else {
79 st = (KeyValue)pairs.get(leftNode);
80 st.value = (double)count++;
81 }
82
83 this.addParentNode(leftNode,rightNode);
84 }
85 }
86 }
87 if ( first_time ) {
88 determineRoot(key,parent,path,goal,temp);
89 first_time = false;
90 }
91 curr = temp;
92 }
93
94
95 enum = links.elements();
96 while( enum.hasMoreElements() ) {
97 link = (TaskLink)enum.nextElement();
98 if ( link.referencesNode(TaskNode.BEGIN) ||
99 link.referencesNode(TaskNode.END) )
100 links.removeElement(link);
101 }
102
103
104 KeyValue tmp = new KeyValue();
105 KeyValue[] data = new KeyValue[pairs.size()];
106 enum = pairs.elements();
107 for(int i = 0; enum.hasMoreElements(); i++ )
108 data[i] = (KeyValue)enum.nextElement();
109
110
111 boolean swapped = true;
112 while( swapped ) {
113 swapped = false;
114 for( int i = 0; i < data.length-1; i++ ) {
115 if ( data[i].value > data[i+1].value ) {
116 tmp.set(data[i]);
117 data[i].set(data[i+1]);
118 data[i+1].set(tmp);
119 swapped = true;
120 }
121 }
122 }
123 for(int i = 0; i < data.length; i++ )
124 nodeList.addElement(data[i].key);
125 node_pointer = 0;
126 }
127
128 protected void determineRoot(String key, PlanRecord parent, Vector path,
129 Goal goal, Vector candidates) {
130
131 Assert.notFalse(candidates.size() == 1);
132 Fact f1 = goal.getFact();
133 String nodeId;
134 Fact[] produced;
135 DecompositionStruct struct;
136 Bindings b = new Bindings(planner.getAgentContext().whoami());
137 for(int i = 0; i < candidates.size(); i++ ) {
138 nodeId = (String)candidates.elementAt(i);
139 struct = (DecompositionStruct)this.get(nodeId);
140 produced = struct.node.getPostconditions();
141 for(int j = 0; j < produced.length; j++, b.clear()) {
142 if ( !produced[j].isSideEffect() && produced[j].unifiesWith(f1,b) ) {
143 struct.node.resolve(b);
144 root = nodeId;
145 struct.key = key;
146 struct.goal = new Goal(goal);
147 struct.parent_record = parent;
148 struct.path = path;
149 return;
150 }
151 }
152 }
153 }
154
155 protected void add(TaskNode node) {
156 DecompositionStruct struct;
157 struct = new DecompositionStruct(planner.getAgentContext().whoami(),node);
158 Assert.notFalse( put(node.getName(),struct) == null);
159 }
160
161 protected void addParentNode(String childId, String parentId) {
162 if ( parentId.equals(TaskNode.END) ) return;
163 DecompositionStruct struct = (DecompositionStruct)get(childId);
164 if ( !struct.parents.contains(parentId) ) {
165 struct.parents.addElement(parentId);
166 addChildNode(parentId,childId);
167 }
168 }
169 protected void addChildNode(String parentId, String childId) {
170 if ( childId.equals(TaskNode.BEGIN) ) return;
171 DecompositionStruct struct = (DecompositionStruct)get(parentId);
172 if ( !struct.children.contains(childId) )
173 struct.children.addElement(childId);
174 }
175
176 public synchronized String nextNode() {
177 String nodeId;
178 if ( node_pointer < nodeList.size() ) {
179 nodeId = (String)nodeList.elementAt(node_pointer++);
180 Core.DEBUG(2,"nextNode(): id = " + nodeId);
181 return allParentsScheduled(nodeId) ? nodeId : nextNode();
182 }
183 return null;
184 }
185 public synchronized void reset() {
186 node_pointer = 0;
187 }
188
189 protected TaskLink findLink(String left, String right) {
190 TaskLink link;
191 Enumeration enum = links.elements();
192 while( enum.hasMoreElements() ) {
193 link = (TaskLink)enum.nextElement();
194 if ( link.getLeftNode().equals(left) &&
195 link.getRightNode().equals(right) ) return link;
196 }
197 return null;
198 }
199
200 protected boolean allParentsScheduled(String nodeId) {
201 String parentId = null;
202 DecompositionStruct struct, st, pt;
203 struct = (DecompositionStruct)get(nodeId);
204 for(int i = 0; i < struct.parents.size(); i++ ) {
205 parentId = (String)struct.parents.elementAt(i);
206 st = (DecompositionStruct)get(parentId);
207 Core.DEBUG(2,"allParentsScheduled(): nodeId = " + nodeId +
208 " parentId = " + parentId + " parent.scheduled = " +
209 st.scheduled);
210 if ( !st.scheduled ) return false;
211 }
212
213 if ( struct.parents.isEmpty() || struct.goal != null )
214 return true;
215
216
217 struct.current_parent = (String)struct.parents.elementAt(0);
218 pt = (DecompositionStruct)get(struct.current_parent);
219 struct.parent_record = pt.record;
220
221
222 struct.key = pt.key;
223
224
225 TaskLink link = findLink(nodeId,struct.current_parent);
226 struct.parent_link = link.getId();
227
228
229 Fact produced = null;
230 produced = pt.node.getPrecondition(link.getRightGroup(),link.getRightArg());
231
232 if ( pt.record == null ) {
233
234 struct.goal = new Goal(pt.image.whichType(),
235 planner.getAgentContext().newId("subgoal"),
236 produced,
237 planner.getAgentContext().whoami());
238
239 if ( pt.image.isContinuous() ) {
240 int s = pt.image.getStartTime();
241 int e = pt.image.getEndTime();
242 int n = pt.image.getInvocations();
243 int u = (e-s)/n;
244 struct.goal.setStartTime(s);
245 struct.goal.setEndTime(e - u);
246 struct.goal.setInvocations(n);
247 }
248 else {
249 struct.goal.setEndTime(getStartTime(link,pt));
250 }
251 struct.goal.setConfirmTime(pt.image.getConfirmTime());
252 struct.goal.setPriority(pt.image.getPriority());
253 struct.goal.setCost(0);
254 struct.goal.setRootId(pt.image.getRootId());
255 }
256 else {
257 Task task = pt.record.getTask();
258 Fact[] consumed = task.getPreconditions();
259 Bindings b = new Bindings(planner.getAgentContext().whoami());
260 boolean found = false;
261 for(int i = 0; !found && i < consumed.length; i++, b.clear()) {
262 if ( produced.unifiesWith(consumed[i],b) ) {
263 struct.goal = pt.record.createSubgoal(consumed[i],i);
264 found = true;
265 }
266 }
267 Assert.notFalse(found);
268 }
269 int start = struct.goal.getStartTime();
270 int end = struct.goal.getEndTime();
271
272 TaskLink link1;
273 for(int i = 0; i < struct.parents.size(); i++ ) {
274 parentId = (String)struct.parents.elementAt(i);
275 st = (DecompositionStruct)get(parentId);
276 link1 = findLink(nodeId,parentId);
277 if ( st.record == null ) {
278 if ( st.image.isContinuous() ) {
279 int s = st.image.getStartTime();
280 int e = st.image.getEndTime();
281 int n = st.image.getInvocations();
282 int u = (e-s)/n;
283 start = Math.min(start,s);
284 end = Math.min(end,e-u);
285 }
286 else {
287 end = Math.min(end,getStartTime(link1,st));
288 }
289 }
290 else {
291 if ( st.goal.isContinuous() ) {
292 start = Math.min(start,st.record.getStartTime());
293 end = Math.min(end,st.record.getEndTime() -
294 st.record.getTask().getTime());
295 }
296 else {
297 end = Math.min(end,st.record.getStartTime());
298 }
299 }
300 }
301
302 struct.goal.setEndTime(end);
303 if ( struct.goal.isContinuous() )
304 struct.goal.setStartTime(start);
305
306
307 struct.path = Misc.copyVector(pt.path);
308 struct.path.addElement(pt.goal.getFact());
309
310
311 links.removeElement(link);
312 return true;
313 }
314
315 protected int getStartTime(TaskLink link, DecompositionStruct struct) {
316 String itemId = (String)struct.lookupTable.get(link.getId());
317 SuppliedItem item = struct.given.getSuppliedItem(itemId);
318 return item.getEarliestReservationTime();
319 }
320 protected String[] getReservationId(TaskLink link,
321 DecompositionStruct struct) {
322 String itemId = (String)struct.lookupTable.get(link.getId());
323 SuppliedItem item = struct.given.getSuppliedItem(itemId);
324 return item.getReservationId();
325 }
326
327 public Fact[] getPreconditions(String node) {
328 DecompositionStruct struct = (DecompositionStruct)this.get(node);
329 return struct.node.getPreconditions();
330 }
331 public Fact[] getPostconditions(String node) {
332 DecompositionStruct struct = (DecompositionStruct)this.get(node);
333 return struct.node.getPostconditions();
334 }
335
336 public Vector getPath(String node) {
337 DecompositionStruct struct = (DecompositionStruct)this.get(node);
338 return struct.path;
339 }
340 public Goal getGoal(String node) {
341 DecompositionStruct struct = (DecompositionStruct)this.get(node);
342 return struct.goal;
343 }
344 public String getKey(String node) {
345 DecompositionStruct struct = (DecompositionStruct)this.get(node);
346 return struct.key;
347 }
348 public PlanRecord getParentRecord(String node) {
349 DecompositionStruct struct = (DecompositionStruct)this.get(node);
350 return struct.parent_record;
351 }
352
353 public void setRecords(String node, Vector records) {
354 DecompositionStruct st = (DecompositionStruct)this.get(node);
355 st.records = records;
356 st.record = (PlanRecord)records.elementAt(0);
357 st.scheduled = true;
358
359 if ( node.equals(root) ) return;
360
361 DecompositionStruct pt = (DecompositionStruct)this.get(st.current_parent);
362 if ( pt.record == null ) {
363 String itemId = (String)pt.lookupTable.get(st.parent_link);
364 SuppliedItem item = pt.given.getSuppliedItem(itemId);
365 String[] refs = item.getReservationId();
366
367 String consumer, consumer_id;
368 String comms_key;
369 int amount, start;
370 boolean consumed;
371
372 String producer = st.agent;
373 String producer_id = st.record.getGoal().getId();
374 for(int i = 0; i < refs.length; i++ ) {
375 consumer = item.getReservingAgent(refs[i]);
376 consumer_id = item.getReservationGoalId(refs[i]);
377 comms_key = item.getReservationCommsKey(refs[i]);
378
379 amount = item.getReservedAmount(refs[i]);
380 start = item.getReservationTime(refs[i]);
381 consumed = item.isReservationConsumed(refs[i]);
382 Assert.notFalse(amount > 0);
383
384 pt.image.addProducer(itemId, refs[i], comms_key,
385 producer, producer_id, consumer, consumer_id);
386
387 st.record.getProducedDb().replaceOrAdd(
388 st.goal.getId(),
389 consumer_id + "/" + refs[i], start, amount, consumed );
390 }
391 }
392 }
393 public boolean allNodesScheduled() {
394 DecompositionStruct struct;
395 Enumeration enum = this.elements();
396 while( enum.hasMoreElements() ) {
397 struct = (DecompositionStruct)enum.nextElement();
398 if ( !struct.scheduled ) return false;
399 }
400 return true;
401 }
402 public void setQueued(String node, boolean set) {
403 DecompositionStruct struct;
404 struct = (DecompositionStruct)get(node);
405 struct.queued = set;
406 }
407 public boolean isQueued(String node) {
408 DecompositionStruct struct;
409 struct = (DecompositionStruct)get(node);
410 return struct.queued;
411 }
412 public boolean isScheduled(String node) {
413 DecompositionStruct struct;
414 struct = (DecompositionStruct)get(node);
415 return struct.scheduled;
416 }
417 public PlanRecord getRecord(String node) {
418 DecompositionStruct struct = (DecompositionStruct)this.get(node);
419 return struct.record;
420 }
421 public PlanRecord getRootRecord() {
422 DecompositionStruct struct = (DecompositionStruct)this.get(root);
423 return struct.record;
424 }
425
426 public String getNodeWithGoalId(String goalId) {
427 Core.DEBUG(3,"getNodeWithId\n" + this);
428 DecompositionStruct struct;
429 Enumeration enum = this.elements();
430 while( enum.hasMoreElements() ) {
431 struct = (DecompositionStruct)enum.nextElement();
432 if ( struct.goal != null &&
433 struct.goal.getId().equals(goalId) )
434 return struct.node.getName();
435 }
436 return null;
437 }
438 public void setImage(String node, Goal image, String agent,
439 String delegation_key) {
440 Core.DEBUG(3,"SetImage: node = " + node);
441 Core.DEBUG(3,"SetImage: image = " + image);
442 DecompositionStruct st = (DecompositionStruct)this.get(node);
443 Core.DEBUG(3,"SetImage: st = " + st);
444 SuppliedDb db = image.getSuppliedDb();
445 Core.DEBUG(3,"SetImage: db = " + db);
446 Assert.notFalse(st.given.add(db));
447 Core.DEBUG(3,"SetImage: After assert");
448 st.image = image;
449 st.agent = agent;
450 st.scheduled = true;
451 st.queued = false;
452
453
454
455
456 String consumer, consumer_id;
457 int amount, start;
458 boolean consumed;
459 String itemId;
460 SuppliedItem item;
461 String[] refs;
462 String producer, producer_id;
463 String comms_key;
464
465 DecompositionStruct pt = (DecompositionStruct)this.get(st.current_parent);
466 producer = st.agent;
467 producer_id = st.image.getId();
468
469 if ( pt.record == null ) {
470 itemId = (String)pt.lookupTable.get(st.parent_link);
471 item = pt.given.getSuppliedItem(itemId);
472 refs = item.getReservationId();
473
474 for(int i = 0; i < refs.length; i++ ) {
475 consumer = item.getReservingAgent(refs[i]);
476 consumer_id = item.getReservationGoalId(refs[i]);
477 comms_key = item.getReservationCommsKey(refs[i]);
478
479 amount = item.getReservedAmount(refs[i]);
480 start = item.getReservationTime(refs[i]);
481 consumed = item.isReservationConsumed(refs[i]);
482 Assert.notFalse(amount > 0);
483
484 pt.image.addProducer(itemId, refs[i], comms_key,
485 producer, producer_id, consumer, consumer_id);
486
487 st.image.addConsumer(producer, producer_id, consumer, consumer_id,
488 refs[i], comms_key, start, amount, consumed);
489 }
490 }
491 else {
492 String use_ref = planner.getAgentContext().newId("used");
493
494 consumer = planner.getAgentContext().whoami();
495 consumer_id = pt.goal.getId();
496
497 start = pt.record.getStartTime();
498 int precond_position = pt.record.getConsumedPosition(producer_id);
499 consumed = pt.record.isPreconditionConsumed(precond_position);
500 amount = pt.record.getAmountUsed(precond_position);
501 Assert.notFalse(amount > 0);
502
503 st.image.addConsumer( producer, producer_id,
504 consumer, consumer_id, use_ref, delegation_key,
505 start, amount, consumed );
506
507 pt.record.getConsumedDb().update( producer_id + "/" + use_ref,
508 producer_id );
509 }
510 st.key = delegation_key;
511 }
512
513 public void enforceLinks() {
514 TaskLink link;
515 LinkInfo info;
516 SuppliedItem item;
517 String[] refs;
518
519 String itemId, producer, producer_id, consumer, consumer_id, comms_key;
520 int amount, start;
521 boolean consumed;
522
523 Enumeration enum = links.elements();
524 while( enum.hasMoreElements() ) {
525 link = (TaskLink)enum.nextElement();
526 Core.DEBUG(2,"About to hardChain " + link.getId());
527 info = getLinkInfo(link);
528 if ( info.child.record != null ) {
529 if ( info.parent.record != null ) {
530 info.child.record.getProducedDb().hardChain(
531 info.effect_position,info.amount,info.parent.record,
532 info.precond_position
533 );
534 }
535 else {
536 itemId = (String)info.parent.lookupTable.get(link.getId());
537 item = info.parent.given.getSuppliedItem(itemId);
538 refs = item.getReservationId();
539
540 producer = planner.getAgentContext().whoami();
541 producer_id = info.child.goal.getId();
542 for(int i = 0; i < refs.length; i++ ) {
543 consumer = item.getReservingAgent(refs[i]);
544 consumer_id = item.getReservationGoalId(refs[i]);
545 comms_key = item.getReservationCommsKey(refs[i]);
546
547 info.parent.image.addProducer(
548 itemId, refs[i], comms_key,
549 producer, producer_id, consumer, consumer_id
550 );
551
552 amount = item.getReservedAmount(refs[i]);
553 start = item.getReservationTime(refs[i]);
554 consumed = item.isReservationConsumed(refs[i]);
555 Assert.notFalse(amount > 0);
556
557 info.child.record.getProducedDb().hardChain(
558 info.effect_position, consumer_id + "/" + refs[i],
559 amount, start, consumed
560 );
561 }
562 }
563 }
564 else {
565 if ( info.parent.record != null ) {
566 String use_ref = planner.getAgentContext().newId("used");
567 info.child.image.addConsumer(
568 info.child.agent, info.child.goal.getId(),
569 planner.getAgentContext().whoami(), info.parent.goal.getId(),
570 use_ref, info.child.key,
571 info.start, info.amount, info.consumed
572 );
573 info.parent.record.getConsumedDb().add(
574 info.precond_position,info.child.goal.getId() + "/" + use_ref,
575 info.amount);
576
577 }
578 else {
579 itemId = (String)info.parent.lookupTable.get(link.getId());
580 item = info.parent.given.getSuppliedItem(itemId);
581 refs = item.getReservationId();
582
583 producer = info.child.agent;
584 producer_id = info.child.goal.getId();;
585 for(int i = 0; i < refs.length; i++ ) {
586 consumer = item.getReservingAgent(refs[i]);
587 consumer_id = item.getReservationGoalId(refs[i]);
588 comms_key = item.getReservationCommsKey(refs[i]);
589
590 info.parent.image.addProducer(
591 itemId,refs[i],comms_key,
592 producer,producer_id,consumer,consumer_id
593 );
594
595 amount = item.getReservedAmount(refs[i]);
596 start = item.getReservationTime(refs[i]);
597 consumed = item.isReservationConsumed(refs[i]);
598 Assert.notFalse(amount > 0);
599
600 info.child.image.addConsumer(
601 info.child.agent, info.child.goal.getId(),
602 consumer, consumer_id,
603 refs[i], comms_key, start, amount, consumed
604 );
605 }
606 }
607 }
608 }
609 links.removeAllElements();
610 }
611
612 protected LinkInfo getLinkInfo(TaskLink link) {
613 LinkInfo info = new LinkInfo();
614 Fact f1;
615 Fact[] data;
616 Bindings b = new Bindings(planner.getAgentContext().whoami());
617
618 info.child = (DecompositionStruct)get(link.getLeftNode());
619 info.parent = (DecompositionStruct)get(link.getRightNode());
620
621 if ( info.child.record != null ) {
622 f1 = info.child.node.getPostcondition(link.getLeftGroup(),link.getLeftArg());
623 data = info.child.record.getTask().getPostconditions();
624 for(int i = 0; i < data.length; i++, b.clear()) {
625 if ( f1.unifiesWith(data[i],b) ) {
626 info.effect_position = i;
627 break;
628 }
629 }
630 }
631
632 if ( info.parent.record != null ) {
633 f1 = info.parent.node.getPrecondition(link.getRightGroup(),link.getRightArg());
634 data = info.parent.record.getTask().getPreconditions();
635 for(int i = 0; i < data.length; i++, b.clear()) {
636 if ( f1.unifiesWith(data[i],b) ) {
637 info.precond_position = i;
638 info.amount = data[i].getNumber();
639 if ( info.amount == 0 ) {
640 System.err.println("Error: integer expected in " +
641 "task.precond.fact.no field." +
642 "\nEnsure \"no\" constraints are defined in all task " +
643 "specifications >> " + link.getId());
644
645
646 info.amount = 1;
647 }
648 info.consumed = !data[i].isReadOnly();
649 info.start = info.parent.record.getStartTime();
650 break;
651 }
652 }
653 }
654 return info;
655 }
656
657 public SuppliedDb getSuppliedDb(String node) {
658 DecompositionStruct st = (DecompositionStruct)get(node);
659 if ( st.given != null ) return st.given;
660
661 st.given = new SuppliedDb(planner.getAgentContext().OntologyDb());
662 st.lookupTable = new Hashtable();
663 Enumeration enum = links.elements();
664 TaskLink link;
665 Fact f1;
666 String me = planner.getAgentContext().whoami();
667 String id;
668 SuppliedItem item;
669 while( enum.hasMoreElements() ) {
670 link = (TaskLink)enum.nextElement();
671 if ( link.getRightNode().equals(node) ) {
672 f1 = st.node.getPrecondition(link.getRightGroup(),link.getRightArg());
673 id = planner.getAgentContext().newId("supplied");
674 item = new SuppliedItem(id,link.getId(),me,f1);
675 st.given.add(item);
676 st.lookupTable.put(link.getId(),id);
677 }
678 }
679 return st.given;
680 }
681 }
682
683 class LinkInfo {
684 public DecompositionStruct child = null;
685 public DecompositionStruct parent = null;
686 public int effect_position = -1;
687 public int precond_position = -1;
688 public int amount = 0;
689 public int start = -1;
690 public boolean consumed = false;
691 }
692
693 class DecompositionStruct {
694 public TaskNode node = null;
695 public PlanRecord record = null;
696 public Vector records = null;
697 public String key = null;
698 public Goal goal = null;
699 public Goal image = null;
700 public String agent = null;
701 public String parent_link = null;
702 public Vector path = null;
703 public PlanRecord parent_record = null;
704 public String current_parent = null;
705 public Vector parents = new Vector();
706 public Vector children = new Vector();
707 public boolean scheduled = false;
708 public boolean queued = false;
709 public SuppliedDb given = null;
710 public Hashtable lookupTable = null;
711
712 public DecompositionStruct(String self, TaskNode node) {
713 Assert.notNull(node);
714 this.node = node;
715 agent = self;
716 }
717 public String toString() {
718 return "(:node " + node.getName() + "\n" +
719 " :records " + records + "\n" +
720 " :record " + record + "\n" +
721 " :key " + key + "\n" +
722 " :goal " + goal + "\n" +
723 " :image " + image + "\n" +
724 " :agent " + agent + "\n" +
725 " :path " + path + "\n" +
726 " :parent_record " + parent_record + "\n" +
727 " :current_parent " + current_parent + "\n" +
728 " :parent_link " + parent_link + "\n" +
729 " :parents " + parents + "\n" +
730 " :children " + children + "\n" +
731 " :scheduled " + scheduled + "\n" +
732 " :queued " + queued + "\n" +
733 " :given " + given + "\n" +
734 " :lookupTable " + lookupTable + "\n" +
735 ")";
736 }
737 }
738