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 java.awt.Color;
28 import zeus.util.*;
29 import zeus.concepts.*;
30 import zeus.concepts.fn.*;
31 import zeus.actors.rtn.*;
32 import zeus.actors.rtn.util.DelegationStruct;
33
34 /***
35 * PlanRecord is used to manage the execution of a (primitive, mutable or infered) task.
36 * The field task is the primitive task being executed, the field thread is the ZeusTask
37 * that is actually being run
38 */
39 public class PlanRecord implements SuppliedRequester {
40 public static final int FREE = 0;
41 public static final int TEMP = 1;
42 public static final int TENTATIVE = 2;
43 public static final int FIRM = 3;
44 public static final int RUNNING = 4;
45 public static final int FAILED = 5;
46 public static final int COMPLETED = 6;
47 public static final int JEOPARDY = 7;
48 public static final int AGREEMENT = 8;
49
50 protected static final boolean BOOKED = true;
51
52 public static final Color[] color = {
53 Color.lightGray,
54 Color.orange,
55 Color.yellow,
56 Color.cyan,
57 Color.green,
58 Color.red,
59 Color.white,
60 Color.magenta,
61 Color.blue
62 };
63
64 public static final String[] state_string = {
65 "Free",
66 "Temporary",
67 "Tentative",
68 "Firm",
69 "Running",
70 "Failed",
71 "Completed",
72 "Jeopardy",
73 "Service-Agreement"
74 };
75
76 protected Planner planner;
77 protected int state = TEMP;
78 protected PlanRecord parent;
79 protected String id;
80 protected Goal goal;
81 protected PrimitiveTask task;
82 protected int proc;
83 protected int start_time;
84 protected int lstart_time;
85 protected int end_time;
86 protected double cost;
87 protected ZeusTask thread = null;
88 protected String diagnostic = null;
89 protected String key = null;
90 protected boolean is_disposed = false;
91
92 protected ConsumedDb consumedDb = null;
93 protected ProducedDb producedDb = null;
94 protected int reconfirm_count = 0;
95
96 protected Vector other_tasks = null;
97 protected Vector path = null;
98
99
100 protected PlanRecord original = null;
101 protected int noAllowedInvocations = 1;
102 protected int noAvailableItems = 0;
103 protected boolean[] slots = null;
104 protected Vector images = null;
105
106
107 public PlanRecord () {
108 ;
109 }
110
111
112 protected void init(Planner planner, String key, PlanRecord parent,
113 Goal goal, PrimitiveTask task, int proc, int start,
114 int end) {
115
116 Assert.notNull(key);
117 Assert.notNull(goal);
118 Assert.notNull(task);
119 Assert.notFalse(start >= 0);
120 Assert.notFalse(end >= 0);
121 Assert.notFalse(proc >= 0);
122
123 this.planner = planner;
124 this.key = key;
125 this.parent = parent;
126 this.id = planner.getAgentContext().newId("PlanRecord");
127 this.goal = goal;
128 this.task = task;
129 this.start_time = start;
130 this.lstart_time = start;
131 this.end_time = end;
132 this.proc = proc;
133 this.cost = task.getCost();
134
135 if ( (noAvailableItems = goal.getFact().getNumber()) == 0 ) {
136 Core.USER_ERROR("Integer expected in goal.fact.no field." +
137 "\nEnsure \"no\" constraints are defined in all task specifications");
138
139
140 noAvailableItems = 1;
141 }
142 task.preprocess();
143 consumedDb = new ConsumedDb(this,task);
144 producedDb = new ProducedDb(this,task);
145
146 Core.DEBUG(3,"PlanRecord created: " + this);
147 }
148
149 public PlanRecord(Planner planner, String key, PlanRecord parent,
150 Goal goal, PrimitiveTask task, int proc, int start,
151 int end) {
152
153 init(planner, key, parent, goal, task, proc, start, end);
154 producedDb.add(task.getActiveEffectPos(), parent, noAvailableItems,
155 goal.getId(),!(goal.getFact().isReadOnly()));
156
157 if ( parent != null )
158 parent.updateCost(cost);
159
160 planner.add(this);
161 planner.notifyMonitors(this,Planner.CREATE);
162 }
163
164 protected PlanRecord(Planner planner, PlanRecord original, String key,
165 PlanRecord parent, Goal goal, PrimitiveTask task,
166 int proc, int start, int end) {
167
168 Assert.notNull(original);
169 Assert.notFalse(goal.whichType() == Goal.DISCRETE);
170 init(planner, key, parent, goal, task, proc, start, end);
171 this.original = original;
172
173 planner.add(this);
174 planner.notifyMonitors(this,Planner.CREATE);
175 }
176
177 public String getId() { return id; }
178 public int getProc() { return proc; }
179 public int getState() { return state; }
180 public int getStartTime() { return start_time; }
181 public int getLatestStartTime() { return lstart_time; }
182 public int getEndTime() { return end_time; }
183 public PrimitiveTask getTask() { return task; }
184 public Goal getGoal() { return goal; }
185 public PlanRecord getParent() { return parent; }
186 public String getKey() { return key; }
187 public double getCost() { return cost; }
188 public ConsumedDb getConsumedDb() { return consumedDb; }
189 public ProducedDb getProducedDb() { return producedDb; }
190 public AgentContext getAgentContext() { return planner.getAgentContext(); }
191 public SuppliedDb getSuppliedDb() { return goal.getSuppliedDb(); }
192
193 public int anySideEffect(Fact desc, PlanRecord rec,
194 Object precond, int required) {
195
196 boolean status = isDiscrete() && (state == FIRM || state == RUNNING);
197 status |= (getRoot() == rec.getRoot());
198
199 if ( !status ) return required;
200
201 Fact[] produced = task.getPostconditions();
202 Bindings b = new Bindings(planner.getAgentContext().whoami());
203 for(int i = 0; required > 0 && i < produced.length; i++, b.clear()) {
204 if ( produced[i].unifiesWith(desc,b) )
205 required = producedDb.anySideEffect(i,rec,precond,required);
206 }
207 return required;
208 }
209
210 public void setAlternativeTasks(Vector Tasks) {
211 this.other_tasks = Tasks;
212 }
213
214
215 public void setPath(Vector path) {
216 this.path = path;
217 }
218
219
220 public Vector getChildPath() {
221 Vector child_path = Misc.copyVector(path);
222 child_path.addElement(goal.getFact());
223 return child_path;
224 }
225
226
227 public PlanRecord[] getChildren() {
228 return consumedDb.getChildren();
229 }
230
231
232 public boolean hasAtMostOneParent(PlanRecord parent, String key) {
233 return producedDb.hasAtMostOneParent(parent,key);
234 }
235 public DataRec getDatarec(int precond_position) {
236 return consumedDb.getDatarec(precond_position);
237 }
238 public int getConsumedPosition(String goal_id) {
239 return consumedDb.getPosition(goal_id);
240 }
241
242
243 public boolean isPreconditionConsumed(int precond_position) {
244 Fact precond = task.getPrecondition(precond_position);
245 return !precond.isReadOnly();
246 }
247
248
249 public int noRequiredItems(int precond_position) {
250 return consumedDb.requiredItems(precond_position);
251 }
252
253
254 public int getAmountUsed(int precond_position) {
255 return consumedDb.amountUsed(precond_position);
256 }
257
258
259 public boolean setSupplier(int precond_position, int amount,
260 SuppliedItem item) {
261
262 String Id = planner.getAgentContext().newId("used");
263 boolean consumed = isPreconditionConsumed(precond_position);
264 boolean b = item.reserve(Id,start_time,consumed,
265 amount,planner.getAgentContext().whoami(), goal.getId(),key);
266 if ( b ) consumedDb.add(precond_position,Id,amount);
267 return b;
268 }
269
270 public void chainPrecondition(PlanRecord child, int effect_position,
271 int amount, int precond_position) {
272 consumedDb.add(precond_position,child,effect_position,amount);
273 }
274
275
276 public void preconditionExists(PlanRecord child, int effect_position,
277 int amount, int precond_position) {
278 consumedDb.factExists(precond_position,child,effect_position,amount);
279 }
280
281
282 public void preconditionExists(String goal_id) {
283 consumedDb.factExists(goal_id);
284 }
285
286
287 public void replacePrecondition(String goal_id, PlanRecord child,
288 int effect_position, int amount) {
289 consumedDb.replace(goal_id,child,effect_position,amount);
290 }
291
292
293 public void breakEffectChain(int effect_position, PlanRecord rec,
294 int precond_position, int amount) {
295 producedDb.remove(effect_position,rec,precond_position,amount);
296 if ( parent == rec && !producedDb.references(parent) ) {
297 parent = producedDb.firstParent();
298 if ( parent != null ) {
299 int first_position = producedDb.firstPosition(parent);
300 task.setActiveEffect(first_position);
301 goal.setFact(task.getActiveEffect());
302 setKey(parent.getKey());
303 }
304 else {
305
306 String other_key = producedDb.firstKey();
307 if ( other_key != null )
308 setKey(other_key);
309 }
310 }
311 }
312
313 public Goal recreateSubgoal(Goal g) {
314 int position = consumedDb.getPosition(g.getId());
315 Fact x = consumedDb.remove(g.getId());
316 Goal g1 = createSubgoal(x,position);
317 double t = planner.getAgentContext().now() +
318 planner.getAgentContext().getReplanPeriod();
319 g1.setConfirmTime(new Time(t));
320
321 g1.setSuppliedDb(this.goal.getSuppliedDb());
322
323 setState(JEOPARDY);
324 return g1;
325 }
326
327 public void reconfirm() {
328 Assert.notFalse(state == JEOPARDY);
329 Core.DEBUG(2,"Decrementing reconfirm from: " + reconfirm_count);
330 if ( --reconfirm_count == 0 )
331 setState(FIRM);
332 }
333
334 public void setKey(String nkey) {
335 Core.DEBUG(3,"PlanRecord: " + this + "\n\tsetKey: " + nkey);
336 if ( parent == null || nkey.equals(parent.getKey()) ) {
337 consumedDb.update(nkey,this.key);
338 this.key = nkey;
339
340 PlanRecord[] children = consumedDb.getChildren();
341 for(int i = 0; i < children.length; i++ )
342 children[i].setKey(nkey);
343 }
344 }
345
346 public boolean isDiscrete() {
347 return goal.whichType() == Goal.DISCRETE;
348 }
349 public boolean isContinuous() {
350 return goal.whichType() == Goal.CONTINUOUS;
351 }
352 public boolean hasMoreEnactments() {
353 Assert.notFalse(goal.whichType() == Goal.CONTINUOUS);
354 return noAvailableItems > 0;
355 }
356 public boolean hasEnoughResources() {
357 return consumedDb.hasEnoughResources();
358 }
359
360 public void updateCost(double value) {
361
362 this.cost += value;
363
364 if ( parent != null ) parent.updateCost(value);
365 }
366
367 public boolean applyConstraints(Bindings bindings) {
368 if ( !task.applyConstraints(bindings) ) return false;
369 return producedDb.constrain(bindings);
370 }
371
372 public Bindings getBindings() {
373 Bindings b = new Bindings(planner.getAgentContext().whoami());
374 Fact f1 = goal.getFact();
375 Fact f2 = task.getActiveEffect();
376 Assert.notFalse( f2.unifiesWith(f1,b) );
377 return b;
378 }
379
380 public boolean isOnCell(int proc,int t) {
381 return this.proc == proc && t >= start_time && t < end_time;
382 }
383
384 protected void vacatingPosition(int proc, int start, int end) {
385 Assert.notFalse(goal.whichType() == Goal.CONTINUOUS);
386 Assert.notFalse(proc == this.proc);
387
388 for(int i = start - start_time; i < end - start_time; i++ )
389 slots[i] = !BOOKED;
390
391 for(int i = start; i < end; i++ )
392 planner.assignCell(proc,i,this);
393 }
394
395
396 protected void originalDisposed() {
397 Assert.notNull(original);
398 original = null;
399 }
400
401
402 public void reassign(int pc, int st) {
403 if ( original != null )
404 original.vacatingPosition(proc,start_time,end_time);
405 else
406 planner.freeCells(proc,start_time,end_time);
407
408 proc = pc;
409 start_time = st;
410 end_time = st + task.getTime();
411 consumedDb.newStartTime(start_time);
412 }
413
414
415 public void incrementTime(int t) {
416
417 planner.freeCell(proc,end_time-1);
418 end_time = t+1;
419 }
420
421
422 public String diagnostic() {
423 return diagnostic;
424 }
425
426
427 /***
428 * mapPreToPost is used to map precondition variables that are
429 * supposed to be copied to post conditions
430 * synchronised?
431 *@author Simon Thompson
432 *@since 1.2
433 */
434 public Fact [][] mapPreToPost(Fact [][] input, Fact[] exp_out) {
435
436 Core.DEBUG (1, "in mapPreToPost");
437 AgentContext cont = this.getAgentContext();
438 TaskDb tdb = cont.getTaskDb();
439 String taskName = task.getName();
440 Task retTask = tdb.getTask (taskName);
441
442 Fact [] retPre = retTask.getPreconditions();
443 Fact [] retPost = retTask.getPostconditions();
444
445 debug("\nTask from DB = " + retTask.toString());
446
447 debug("\nThis task = " + task.toString());
448
449 Fact [][] output = new Fact [exp_out.length][1];
450 debug(String.valueOf(input.length));
451 for (int count = 0; count<input.length; count++) {
452
453 debug(String.valueOf(exp_out.length));
454 for (int count2 = 0; count2 < exp_out.length; count2++) {
455
456
457 output[count2][0] = exp_out[count2];
458
459 String [] map = retPost[count2].buildMap(retPre[count]);
460
461 output[count2][0].doMap(input[count][0],map);
462 debug("in = " + input[count][0] + " out = " +output[count2][0]);
463
464 }
465 }
466 return output;
467
468 }
469
470 /***
471 bind the any variables in the task cost and time to their pre & postcondition
472 values at run time
473
474 */
475 public void mapCostAndTime() {
476 AgentContext cont = this.getAgentContext();
477 TaskDb tdb = cont.getTaskDb();
478 String taskName = task.getName();
479 Task retTask = tdb.getTask (taskName);
480 Fact [] retPost = retTask.getPostconditions();
481 Fact [] post = task.getPostconditions();
482 Fact [] retPre = retTask.getPreconditions();
483 Fact [] pre = task.getPreconditions();
484 ValueFunction time = task.getTimeFn();
485 ValueFunction cost = task.getCostFn();
486 for (int i = 0; i<retPost.length; i++) {
487 map (time, retPost[i], post[i]);
488 map (cost, retPost[i], post[i]);
489 }
490 for (int i = 0; i<retPre.length; i++) {
491 map (time, retPre[i], pre[i]);
492 map (cost,retPre[i], pre[i]);
493 }
494
495
496 }
497
498
499 public void map (ValueFunction val, Fact lhs, Fact rhs) {
500 debug ("val = " + val.toString() + "\nlhs = " + lhs.toString() + "\nrhs = " + rhs.toString());
501 }
502
503
504 public boolean exec() {
505 diagnostic = null;
506 PrimitiveTask task_image = new PrimitiveTask(task);
507
508 /***
509 Fact fact = goal_image.getFact();
510 Fact f2 = task_image.getActiveEffect();
511 es.ok = es.ok && f2.unifiesWith(fact,b)
512 */
513
514 if ( goal.whichType() != Goal.DISCRETE || thread != null )
515 return false;
516
517 if ( !consumedDb.hasEnoughResources() ) {
518 setState(FAILED);
519 diagnostic = "1: Cannot exec - inadequate resources";
520 Core.DEBUG(2,diagnostic);
521 return true;
522 }
523 try {
524 String name = task.getName();
525
526
527 if ( name.startsWith("GenTask") )
528 name = "GenTask";
529
530
531
532 Class c = Class.forName(name);
533 thread = (ZeusTask) c.newInstance();
534 Fact[][] input = consumedDb.getInputData();
535 consumedDb.consumeResources();
536 System.out.println(task.pprint());
537 thread.setInputArgs(input);
538 /***
539 everything else is being set from the primitiveTask, but
540 this is not right... I think that the output arguments need to
541 be mapped from the inputArgs at this point
542 */
543
544 thread.setExpectedOutputArgs(task.getOriginalPostconditions());
545
546 Fact[] exp_input = task.getPreconditions();
547 thread.setExpectedInputArgs(exp_input);
548
549 thread.setMedia(goal.getTargetMedia());
550 thread.setContext(getAgentContext());
551 Fact [] exp_out = task.getOriginalPostconditions();
552 Fact [][] act_out = null;
553
554 if (input.length>0) {
555 act_out = mapPreToPost (input,exp_out);
556 }
557 else {
558 act_out = new Fact [exp_out.length][1];
559 for (int i = 0; i<exp_out.length;i++) {
560 act_out[i][0] = exp_out[i]; }
561 }
562 mapCostAndTime();
563 Bindings b = new Bindings(planner.getAgentContext().whoami());
564 task.resolve(b);
565
566 thread.setOutputArgs (act_out);
567 for (int count = 0; count<act_out.length; count ++ ) {
568 exp_out[count]= act_out[count][0];
569 }
570 thread.setExpectedOutputArgs(exp_out);
571
572 Fact [][] user_out = new Fact [task.getOriginalPostconditions().length][1];
573 Fact[][] output = new Fact[task.getOriginalPostconditions().length][1];
574
575 for (int count = 0; count<user_out.length; count++ ) {
576 user_out[count][0] = exp_out[count];
577 }
578
579 for(int i = 0; i < user_out.length; i++ ) {
580 debug ("user_out[" + String.valueOf(i) + "] = " + user_out[i].toString());
581 output[i] = user_out[i];
582
583 }
584
585 /*** int j = user_out.length;
586 for(int i = 0; i < exp_input.length; i++ )
587 if ( exp_input[i].isReplaced() )
588 output[j++] = input[i]; */
589
590 task.relaxNumberFields();
591 thread.start();
592
593
594
595 setState(RUNNING);
596 diagnostic = "Running started ... ";
597 Core.DEBUG(2,diagnostic);
598 }
599
600 catch(ClassNotFoundException e) {
601 setState(FAILED);
602 diagnostic = "2: Cannot exec - ClassNotFoundException";
603 Core.DEBUG(2,diagnostic);
604 }
605 catch(IllegalAccessException e) {
606 setState(FAILED);
607 diagnostic = "3: Cannot exec - IllegalAccessException";
608 Core.DEBUG(2,diagnostic);
609 }
610 catch(InstantiationException e) {
611 setState(FAILED);
612 diagnostic = "4: Cannot exec - InstantiationException";
613 Core.DEBUG(2,diagnostic);
614 }
615 return true;
616 }
617
618
619
620
621
622 public boolean overRun() {
623 ResourceDb resDb = getAgentContext().getResourceDb();
624 if ( thread.isFinished() ) {
625 Fact[][] user_out = thread.getOutputArgs();
626
627 if ( user_out != null && user_out.length > 0 ) {
628 Fact[][] output = thread.outputArgs;
629
630 Fact[][] input = thread.getInputArgs();
631 Fact[] exp_input = thread.getExpectedInputArgs();
632
633
634
635
636 int j = user_out.length;
637 for(int i = 0; i < exp_input.length; i++ )
638 if ( exp_input[i].isReplaced() )
639 resDb.add(input[i]);
640
641
642
643 if (output!= null)
644 producedDb.allocatePostconditions(output);
645
646 setState(COMPLETED);
647 return false;
648 }
649 else {
650 setState(FAILED);
651 diagnostic = "5: Failed - task execution did not produce output";
652 return false;
653 }
654 }
655 double t = planner.getAgentContext().now();
656
657 if ( t >= end_time ) {
658 if ( t < goal.getEndTime() &&
659 planner.incrementProcessorTime(this,(int)t) ) {
660
661 return false;
662 }
663 setState(FAILED);
664 diagnostic = "5: Failed - overrun allocated time: " +
665 t + " > " + end_time;
666 thread.abort();
667 return true;
668 }
669 return false;
670 }
671
672
673 protected void setState(int newState, PlanRecord parent) {
674
675
676
677
678 if ( parent == this.parent )
679 setState(newState);
680 }
681
682
683 public void setState(int newState) {
684 Assert.notFalse(newState >= TEMP && newState <= AGREEMENT);
685
686 Core.DEBUG(3,"Setting state for rec " + id + " from " +
687 state_string[state] + " to " + state_string[newState]);
688 state = newState;
689 planner.notifyMonitors(this,Planner.STATE_CHANGE);
690
691 PlanRecord[] children;
692 switch( state ) {
693 case TEMP:
694 case TENTATIVE:
695 children = getChildren();
696 for(int i = 0; i < children.length; i++ )
697 children[i].setState(newState,this);
698 break;
699
700 case FIRM:
701 Core.DEBUG(3,this);
702 Core.DEBUG(3,producedDb);
703 Core.DEBUG(3,consumedDb);
704
705 goal.setSuppliedDb(null);
706 if ( goal.whichType() == Goal.CONTINUOUS ) {
707 setState(AGREEMENT);
708 return;
709 }
710 children = getChildren();
711 for(int i = 0; i < children.length; i++ )
712 children[i].setState(newState,this);
713 break;
714
715 case AGREEMENT:
716 goal.setSuppliedDb(null);
717 Assert.notFalse(goal.whichType() == Goal.CONTINUOUS);
718 if ( slots == null ) {
719 noAllowedInvocations = goal.getInvocations();
720 slots = new boolean[end_time-start_time];
721 for(int i = 0; i < slots.length; i++ )
722 slots[i] = !BOOKED;
723 images = new Vector();
724 }
725 children = getChildren();
726 for(int i = 0; i < children.length; i++ )
727 children[i].setState(newState,this);
728 break;
729
730 case RUNNING:
731 break;
732
733 case COMPLETED:
734 break;
735
736 case FAILED:
737 dispose(parent,key);
738 producedDb.notifyFailed(other_tasks,path);
739 break;
740
741 case JEOPARDY:
742 reconfirm_count++;
743 break;
744
745 default:
746 break;
747 }
748 }
749
750
751 public void softFail(PlannerQueryStruct struct, int mode) {
752 Core.DEBUG(2,"softFail..." + struct);
753
754 if ( mode == Planner.REPLAN ) {
755 state = FAILED;
756 planner.notifyMonitors(this,Planner.STATE_CHANGE);
757 }
758
759 Goal g;
760 Vector subgoals = descendantSubgoals();
761 subgoals.addElement(this.goal.getId());
762 for(int i = 0; i < struct.external.size(); i++ ) {
763 g = (Goal)struct.external.elementAt(i);
764 if ( subgoals.contains(g.getId()) )
765 struct.external.removeElementAt(i--);
766 }
767 dispose(parent,key);
768 if ( mode == Planner.REPLAN ) {
769 planner.clear_bind(struct.goals);
770 for(int i = 0; i < struct.goals.size(); i++ ) {
771 g = (Goal)struct.goals.elementAt(i);
772 if ( subgoals.contains(g.getId()) )
773 struct.goals.removeElementAt(i--);
774 }
775 }
776 producedDb.softNotifyFailed(other_tasks,path,struct,mode);
777 }
778
779
780 public Vector descendantSubgoals() {
781 Vector subgoals = consumedDb.currentSubgoals();
782 PlanRecord[] children = consumedDb.getChildren();
783 Vector sub;
784 for(int i = 0; i < children.length; i++ ) {
785 sub = children[i].descendantSubgoals();
786 subgoals = Misc.union(subgoals,sub);
787 }
788 return subgoals;
789 }
790
791
792 public int latestConfirmTime() {
793 int lct = start_time;
794
795 PlanRecord[] children = consumedDb.getChildren();
796 for(int i = 0; i < children.length; i++ )
797 lct = Math.min(lct,children[i].latestConfirmTime());
798 return lct;
799 }
800
801
802 public void dispose() {
803 dispose(parent,key,goal.getSuppliedDb());
804 }
805
806
807 public void dispose(PlanRecord parent, String key) {
808 dispose(parent,key,goal.getSuppliedDb());
809 }
810
811 protected void dispose(PlanRecord aParent, String aKey,
812 SuppliedDb db) {
813 if ( is_disposed ) return;
814
815 Core.DEBUG(3,"Dispose rec " + id + "-" + goal.getFactType() +
816 ": " + state_string[state]);
817
818 PlanRecord rec;
819 PlanRecord[] children;
820 switch(state) {
821 case TEMP:
822 case TENTATIVE:
823 case FIRM:
824 case RUNNING:
825 case JEOPARDY:
826
827
828
829
830
831 if ( producedDb.hasAtMostOneParent(aParent,aKey) ) {
832 Core.DEBUG(3,"rec " + id + " hasAtMostOneParent");
833
834 planner.freeCells(proc,start_time,end_time);
835 if ( thread != null ) thread.abort();
836 thread = null;
837 children = consumedDb.getChildren();
838 for(int i = 0; i < children.length; i++ )
839 children[i].dispose(this,key);
840 consumedDb.releaseResources(db);
841 Core.DEBUG(3,"Calling planner.del: " + this);
842 planner.del(this);
843 is_disposed = true;
844 planner.notifyMonitors(this,Planner.DISPOSE);
845 }
846 break;
847
848 case AGREEMENT:
849 for(int i = 0; images != null && i < images.size(); i++ ) {
850 rec = (PlanRecord)images.elementAt(i);
851 rec.originalDisposed();
852 }
853
854 case FAILED:
855 case COMPLETED:
856
857 if ( thread != null ) thread.abort();
858 thread = null;
859
860 if ( goal.whichType() == Goal.CONTINUOUS ) {
861 for(int i = 0; i < slots.length; i++ )
862 if ( slots[i] != BOOKED )
863 planner.freeCell(proc,i+start_time);
864 }
865 else {
866 planner.freeCells(proc,start_time,end_time);
867 }
868
869 children = consumedDb.getChildren();
870 for(int i = 0; i < children.length; i++ )
871 children[i].dispose(this,key);
872 consumedDb.releaseResources(db);
873 planner.del(this);
874 is_disposed = true;
875 planner.notifyMonitors(this,Planner.DISPOSE);
876 break;
877
878 default:
879 Assert.notNull(null);
880 }
881 }
882
883
884 public boolean hasAncestor(PlanRecord ancestor) {
885 PlanRecord father = this;
886 while( father != null ) {
887 if ( father == ancestor )
888 return true;
889 father = father.getParent();
890 }
891 return false;
892 }
893
894
895 public PlanRecord getRoot() {
896 PlanRecord root = this;
897 while( root.getParent() != null )
898 root = root.getParent();
899 return root;
900 }
901
902 public void reallocateResource(int precond_position, int amount) {
903 reallocateResource(precond_position,amount,null,null);
904 }
905
906
907 public void reallocateResource(int precond_position, PlanRecord child,
908 int effect_position, int amount,
909 Vector Tasks, Vector path) {
910 consumedDb.remove(precond_position,child,effect_position,amount);
911 reallocateResource(precond_position,amount,Tasks,path);
912 }
913
914
915 public void reallocateResource(int precond_position, int amount,
916 Vector Tasks, Vector Path) {
917 ResourceDb db = planner.getAgentContext().ResourceDb();
918 Goal g;
919
920 Core.DEBUG(3,"Attempting reallocation...");
921
922 SuppliedDb given = this.goal.getSuppliedDb();
923 if ( given != null )
924 amount = given.allocateResource(this,precond_position,amount);
925
926 if ( amount == 0 ) return;
927
928 if ( (g = db.allocateResource(this,precond_position,amount)) == null )
929 return;
930
931 diagnostic = "Required resource unavailable - replanning";
932 setState(JEOPARDY);
933
934 double t = planner.getAgentContext().now() +
935 planner.getAgentContext().getReplanPeriod();
936 g.setConfirmTime(new Time(t));
937
938 Core.DEBUG(3,"Reallocation failed... internal replanning");
939
940 if ( path == null )
941 path = Misc.copyVector(this.path);
942
943 PlannerQueryStruct struct = new PlannerQueryStruct(g);
944 struct.internal.addElement(this);
945 planner.schedule(key,this,path,g,Tasks,struct,Planner.EXPAND);
946
947 if ( !struct.external.isEmpty() ) {
948 Core.DEBUG(3,"Reallocation failed... external replanning");
949 planner.index(struct);
950 planner.getAgentContext().Engine().replan(struct,key);
951 }
952 else if ( !struct.internal.isEmpty() )
953 reconfirm();
954 }
955
956 public void raiseException(int effect_position, String exception_key,
957 int amount) {
958
959
960
961
962 Goal g = new Goal(goal);
963
964 g.setId(planner.getAgentContext().newId("subgoal"));
965 g.setImage(goal.getId());
966
967 Fact needed = task.getPostcondition(effect_position);
968 needed.setNumber(amount);
969 g.setFact(needed);
970 g.setDesiredBy(planner.getAgentContext().whoami());
971 double t = planner.getAgentContext().now() +
972 planner.getAgentContext().getReplanPeriod();
973 g.setConfirmTime(new Time(t));
974
975 Core.DEBUG(3,"Top goal... internal replanning");
976
977 PlannerQueryStruct struct = new PlannerQueryStruct(g);
978 planner.schedule(key,null,path,g,other_tasks,struct,Planner.EXPAND);
979 if ( !struct.internal.isEmpty() ) {
980 if ( !struct.external.isEmpty() ) {
981 Core.DEBUG(3,"Top goal... external replanning");
982 planner.index(struct);
983 planner.getAgentContext().Engine().replan(struct,key);
984 }
985 else
986 planner.book(FIRM,g,struct.internal);
987 }
988 else {
989 Vector goals = new Vector();
990 goals.addElement(goal);
991 DelegationStruct ds = new DelegationStruct(planner.getAgentContext().whoami(),
992 "failure",exception_key,goals);
993 planner.getAgentContext().Engine().add(ds);
994 }
995 }
996
997
998 public void softReallocateResource(int precond_position, PlanRecord child,
999 int effect_position, int amount,
1000 Vector Tasks, Vector path,
1001 PlannerQueryStruct struct, int mode) {
1002 consumedDb.remove(precond_position,child,effect_position,amount);
1003 softReallocateResource(precond_position,amount,Tasks,path,struct,mode);
1004 }
1005
1006
1007 public void softReallocateResource(int precond_position, int amount,
1008 Vector Tasks, Vector Path,
1009 PlannerQueryStruct struct, int mode) {
1010
1011 ResourceDb db = planner.getAgentContext().ResourceDb();
1012 Goal g;
1013
1014 if ( path == null )
1015 path = Misc.copyVector(this.path);
1016
1017 Core.DEBUG(3,"Attempting soft reallocation...");
1018
1019 SuppliedDb given = this.goal.getSuppliedDb();
1020 if ( given != null )
1021 amount = given.allocateResource(this,precond_position,amount);
1022
1023 if ( amount == 0 ) return;
1024
1025 if ( (g = db.allocateResource(this,precond_position,amount)) == null )
1026 return;
1027
1028 diagnostic = "Required resource unavailable - replanning";
1029 if ( mode == Planner.REPLAN ) {
1030 struct.goals.addElement(g);
1031 planner.index(struct);
1032 setState(JEOPARDY);
1033 double t = planner.getAgentContext().now() +
1034 planner.getAgentContext().getReplanPeriod();
1035 g.setConfirmTime(new Time(t));
1036 }
1037 else {
1038 g.setConfirmTime(this.goal.getConfirmTime());
1039 }
1040
1041 Core.DEBUG(3,"Soft reallocation failed... internal replanning");
1042
1043 if ( !struct.internal.contains(this) )
1044 struct.internal.addElement(this);
1045
1046 planner.schedule(key,this,path,g,Tasks,struct,Planner.EXPAND);
1047 }
1048
1049
1050 public void softRaiseException(int effect_position, String exception_key,
1051 int amount, PlannerQueryStruct struct,
1052 int mode) {
1053
1054
1055
1056
1057 Fact needed = task.getPostcondition(effect_position);
1058 needed.setNumber(amount);
1059
1060 Goal g;
1061 if ( mode == Planner.REPLAN ) {
1062 g = new Goal(goal);
1063
1064 g.setId(planner.getAgentContext().newId("subgoal"));
1065 g.setImage(goal.getId());
1066 g.setDesiredBy(planner.getAgentContext().whoami());
1067
1068 g.setFact(needed);
1069 double t = planner.getAgentContext().now() +
1070 planner.getAgentContext().getReplanPeriod();
1071 g.setConfirmTime(new Time(t));
1072 g.setSuppliedDb(null);
1073 }
1074 else {
1075 g = goal;
1076 }
1077
1078 Core.DEBUG(3,"Top goal... soft internal replanning");
1079
1080 this.removeRecordTree(struct.internal);
1081 planner.schedule(key,null,path,g,other_tasks,struct,Planner.EXPAND);
1082
1083 if ( struct.internal.isEmpty() && mode == Planner.REPLAN ) {
1084 Vector goals = new Vector();
1085 goals.addElement(goal);
1086 DelegationStruct ds = new DelegationStruct(
1087 planner.getAgentContext().whoami(),"failure",
1088 exception_key,goals);
1089 planner.getAgentContext().Engine().add(ds);
1090 }
1091 }
1092
1093
1094 public void removeRecordTree(Vector data) {
1095 data.removeElement(this);
1096 PlanRecord[] children = getChildren();
1097 for(int i = 0; i < children.length; i++ )
1098 children[i].removeRecordTree(data);
1099 }
1100
1101
1102 public ReportRec report() {
1103 String parent_id = parent != null ? parent.getGoal().getId() : null;
1104
1105 Vector siblings = new Vector();
1106 if ( goal.getImage() != null )
1107 siblings.addElement(goal.getImage());
1108
1109 Vector parents = producedDb.getAllParents();
1110 parents.removeElement(goal.getId());
1111
1112 ReportRec report = new ReportRec(goal.getId(), goal.getFactType(),
1113 task.getName(), planner.getAgentContext().whoami(),
1114 state, goal.getDesiredBy(),
1115 goal.getRootId(), parent_id,
1116 start_time, end_time, cost,
1117 consumedDb.allSubgoals(), siblings, parents,
1118 task.getPreconditions(), task.getPostconditions()
1119 );
1120 return report;
1121 }
1122
1123
1124 public Goal createSubgoal(Fact fact, int precon_position) {
1125 String goalId = planner.getAgentContext().newId("subgoal");
1126 String myself = planner.getAgentContext().whoami();
1127
1128 Goal g = new Goal(goal.whichType(),goalId,fact,myself);
1129
1130 if ( goal.whichType() == Goal.CONTINUOUS ) {
1131 g.setStartTime(start_time);
1132 g.setEndTime(end_time - task.getTime());
1133 g.setInvocations(goal.getInvocations());
1134 }
1135 else {
1136 g.setEndTime(start_time);
1137 }
1138 g.setConfirmTime(goal.getConfirmTime());
1139 g.setPriority(goal.getPriority());
1140 g.setCost(0);
1141 g.setRootId(goal.getRootId());
1142
1143 g.setSuppliedDb(this.goal.getSuppliedDb());
1144
1145 consumedDb.add(precon_position, g.getId(), fact.getNumber());
1146
1147 return g;
1148 }
1149
1150
1151 public boolean hasSubgoal(String goalId) {
1152 return consumedDb.currentSubgoals().contains(goalId);
1153 }
1154
1155
1156 public boolean hasSubgoal(Goal goal) {
1157 return consumedDb.currentSubgoals().contains(goal.getId());
1158 }
1159
1160
1161 public boolean equals(PlanRecord rec) {
1162 return id.equals(rec.getId()) &&
1163 goal.equals(rec.getGoal()) &&
1164 task.equals(rec.getTask());
1165 }
1166
1167
1168 public PlanRecord enact(PlannerEnactStruct es, Goal goal_image,
1169 PlanRecord parent_image, String key_image,
1170 Hashtable substitution_table) {
1171 System.out.println("ENACTING....");
1172 Fact fact = goal_image.getFact();
1173 int required = fact.getNumber();
1174 int etime = goal_image.getEndTime();
1175 int duration = task.getTime();
1176
1177 etime = (etime <= 0) ? end_time + etime : etime;
1178 goal_image.setEndTime(etime);
1179
1180 Core.DEBUG(4,"required = " + required);
1181 Core.DEBUG(4,"noAllowedInvocations = " + noAllowedInvocations);
1182 Core.DEBUG(4,"noAvailableItems = " + noAvailableItems);
1183 Core.DEBUG(4,"etime = " + etime);
1184 Core.DEBUG(4,"end_time = " + end_time);
1185 Core.DEBUG(4,"start_time = " + start_time);
1186 Core.DEBUG(4,"duration = " + duration);
1187
1188 es.ok = es.ok &&
1189 goal.whichType() == Goal.CONTINUOUS &&
1190 goal_image.whichType() == Goal.DISCRETE &&
1191 etime <= end_time &&
1192 etime >= start_time + duration &&
1193 noAllowedInvocations > 0 &&
1194 required <= noAvailableItems;
1195
1196 if ( !es.ok ) {
1197 Core.DEBUG(4,"Failed here");
1198 return null;
1199 }
1200
1201 boolean found = false;
1202 int top = 0, bottom = 0;
1203 for(int i = etime-start_time-1; !found && i >= duration-1; i-- ) {
1204 found = true;
1205 top = i; bottom = top-duration+1;
1206 for(int j = top; j >= bottom; j-- )
1207 found = found && slots[j] != BOOKED;
1208 }
1209 if ( !found ) {
1210 es.ok = false;
1211 return null;
1212 }
1213 System.out.println("ENACTING");
1214 PrimitiveTask task_image = new PrimitiveTask(task);
1215
1216
1217
1218
1219
1220 task_image.relaxNumberFields();
1221
1222 Core.DEBUG(4,"TaskImage Before = \n" + task_image.pprint());
1223
1224 Bindings b = new Bindings(planner.getAgentContext().whoami());
1225 Fact f2 = task_image.getActiveEffect();
1226 es.ok = es.ok && f2.unifiesWith(fact,b) &&
1227 b.add(es.bindings) &&
1228 task_image.applyConstraints(b);
1229
1230 Core.DEBUG(4,"TaskImage After = \n" + task_image.pprint());
1231
1232 if ( !es.ok )
1233 return null;
1234
1235
1236 PlanRecord image = new PlanRecord(planner, this, key_image, parent_image,
1237 goal_image, task_image, proc, start_time+bottom, start_time+top+1);
1238
1239 images.addElement(image);
1240 image.setAlternativeTasks(Misc.copyVector(other_tasks));
1241 image.setPath(Misc.copyVector(path));
1242 for(int i = start_time+top; i > start_time+top-duration; i-- ) {
1243 Core.DEBUG(4,"Assigning cell[" + proc + "][" + i + "] to "+image);
1244 planner.assignCell(proc,i,image);
1245 }
1246
1247 substitution_table.put(this,image);
1248 es.images.addElement(image);
1249 producedDb.share(image.getProducedDb(),
1250 parent_image, key_image, parent, key);
1251 consumedDb.share(image.getConsumedDb());
1252
1253
1254
1255 int s_etime = etime - end_time;
1256
1257 Goal child_goal_image;
1258 PlanRecord child;
1259 PlanRecord child_image;
1260 Object any;
1261 String goal_id;
1262 Fact f1;
1263
1264 Hashtable children = image.getConsumedDb().getAllChildren();
1265 Enumeration enum = children.keys();
1266 while( enum.hasMoreElements() ) {
1267
1268 f1 = (Fact) enum.nextElement();
1269 any = children.get(f1);
1270
1271 String goalId = planner.getAgentContext().newId("subgoal");
1272 String myself = planner.getAgentContext().whoami();
1273
1274 child_goal_image = new Goal(Goal.DISCRETE,goalId,f1,myself);
1275 child_goal_image.setEndTime(s_etime);
1276 child_goal_image.setPriority(goal.getPriority());
1277 child_goal_image.setCost(0);
1278 child_goal_image.setRootId(goal_image.getRootId());
1279
1280 if ( any instanceof String ) {
1281 goal_id = (String)any;
1282 image.getConsumedDb().update(child_goal_image.getId(),goal_id);
1283 es.external.addElement(child_goal_image);
1284 es.table.put(child_goal_image.getId(),goal_id);
1285 }
1286 else {
1287 child = (PlanRecord)any;
1288 child_image = (PlanRecord)substitution_table.get(child);
1289 if ( child_image == null )
1290 child_image = child.enact(es,child_goal_image,image,key_image,
1291 substitution_table);
1292 Assert.notNull(child_image);
1293 image.getConsumedDb().update(child_image,child);
1294 }
1295 }
1296
1297 for(int j = top; j >= bottom; j-- )
1298 slots[j] = BOOKED;
1299
1300 noAllowedInvocations--;
1301 noAvailableItems = noAvailableItems - required;
1302 return image;
1303 }
1304
1305 public String toString() {
1306 return id + "/" + goal.getFactType() + "/" + goal.getFactId() + "/" + key;
1307 }
1308
1309 public void debug (String str) {
1310
1311 }
1312
1313 }