root/deus/RegressionPlanner.cpp

Revision 8, 15.1 kB (checked in by pantley2, 4 years ago)

added old DEUS project to SVN

Line 
1 #include "RegressionPlanner.h"
2
3
4 int RegressionPlanner::MakeNewPlan(KeyFrameNode* key_frame, PlanNode*& retPlan, int timer)
5 {
6         ClearStacks();
7     retPlan = NULL;
8        
9         // we will assume that the Key-preconds are already satisfied
10         // try to satisfy the condition for this key_frame node
11         currently_seeking = key_frame;
12    
13     try{
14                 int x = ResumePlanning(retPlan, timer, false);
15         ClearStacks();
16         return x;
17         }catch(TimeOutException tout) {
18         regression_root = PlanStack.tail();
19         throw tout;
20     }
21     regression_root = retPlan;
22 }
23
24
25 // throws TimeOutException
26 // returns 1 iff retPlan is set to a valid plan
27 int RegressionPlanner::ResumePlanning(PlanNode*& retPlan, int timer, bool use_stack)
28 {
29         int ret = 1;
30         if(currently_seeking->conditions.satisfied) return 1; // already satisfied
31         
32         try{
33                 if(!MakePlan(retPlan, use_stack))
34                 {
35                         DeletePlan(retPlan);
36                         ret = 0;
37                 }
38                 else // p now points to root of plan to achieve op's preconds
39                 {
40                 currently_seeking->conditions.satisfied = 1;   
41                 }
42         regression_root = PlanStack.tail();
43         }catch(TimeOutException){ return 0; }
44        
45     ClearStacks();
46     regression_root = retPlan;
47         return ret;
48 }
49
50 int RegressionPlanner::Replan(PlanNode*& retPlan, int timer)
51 {
52     try{
53         if(OpStack.empty())
54         {   
55             int x = MakeNewPlan(currently_seeking, retPlan, timer);
56             regression_root = retPlan;
57                         return x;
58         }
59         else
60         {
61              int y = ResumePlanning(retPlan, timer);
62              regression_root = retPlan;
63              return y;
64         }
65     }catch(TimeOutException tout) {
66         throw tout;
67         regression_root = PlanStack.tail();
68     }
69 }
70
71 // private functions
72
73 // throws TimeOutException
74 int RegressionPlanner::MakePlan(PlanNode*& retPlan, bool use_stack)
75 {
76         ResetTimer(); ///~~ use timer variable???
77
78     int ret = 0;
79     list<pair<WORLDSTATE,Condition> >::iterator bindings;
80
81     try {
82         // check all worldstates in the forward search (leaves only?)
83     // for possible variable bindings.  If there are some, then
84     // we want to know which ones are satisfied with what values
85     // in what worldstate.
86     if(!use_stack)
87     {
88         possible_bindings =
89             GetWorldStates(currently_seeking->conditions);
90
91             // check for whether there are any worldstates in which
92             // all the preconds are satisified
93         bindings = FindComplete(possible_bindings, currently_seeking->conditions);
94     }
95     if(!use_stack && bindings != possible_bindings.end())
96     {
97         // if any of the possible bindings completely satisfy condition,
98         // SUCCEEED
99             AddForwardPart(retPlan, bindings->first);///~!*&
100         return 1;
101     }
102     else
103     {
104                 // go through the possible_bindings and try to plan back to
105                 // one of the worldstates to satisfy the other parts of
106                 // the condition for which variables do not yet have
107                 // values
108         if(!use_stack)
109             satisfied_counts = CountAllSatisfied();
110                
111                 while(!possible_bindings.empty())
112                 {
113             list<pair<list<pair<WORLDSTATE,Condition> >::iterator, pair<int,int> > >::iterator
114                 best = FindBestCount();
115             if(PlanOnRest(retPlan, *best->first, best->second.second, use_stack))
116             {
117                 AddForwardPart(retPlan, best->first->first);
118                                 return 1; // planning success
119             }
120             use_stack = false; // the rest of the calls to PlanOnRest will cover new territory only
121                         possible_bindings.erase(best->first);
122             satisfied_counts.erase(best);
123                 }
124                 ret = 0;
125     }
126    
127     return ret;
128         // if timeout, save EVERYTHING and throw TimeOutException
129     }catch(TimeOutException timeout) {
130         SaveAll(); throw timeout;
131     }
132 }
133
134 list<pair<list<pair<WORLDSTATE,Condition> >::iterator, pair<int,int> > >::iterator
135 RegressionPlanner::FindBestCount(void)
136 {
137     list<pair<list<pair<WORLDSTATE,Condition> >::iterator, pair<int,int> > >::iterator
138         b(satisfied_counts.begin()), best(satisfied_counts.begin());
139     while(++b != satisfied_counts.end())
140         if(b->second.first > best->second.first)
141             best =  b;
142     return best;
143 }
144
145 list<pair<list<pair<WORLDSTATE,Condition> >::iterator,pair<int,int> > > RegressionPlanner::CountAllSatisfied(void)
146 {
147     list<pair<list<pair<WORLDSTATE,Condition> >::iterator,pair<int,int> > > ret;
148     pair<int,int> satisfied;
149     list<pair<WORLDSTATE, Condition> >::iterator b = possible_bindings.begin();
150         for(;b!=possible_bindings.end(); ++b)
151         {
152         ret.push_back(pair<list<pair<WORLDSTATE,Condition> >::iterator,pair<int,int> >(b, CountSatisfied(b->second)));
153         }
154     return ret;
155 }
156
157 // the first in the pair is the number of objects filled in in the
158 // best set of bindings of the condition
159 // the second in the pair is the index of the best set of bindings in the condition
160 pair<int,int> RegressionPlanner::CountSatisfied(Condition& cond)
161 {
162         int best = 0;
163     int num_best = _CountSatisfied(cond, best);
164     int tmp;
165     for(int s=1; s<cond.vars.size(); ++s)
166     {
167         tmp = _CountSatisfied(cond, s);
168         if(tmp > num_best)
169         {
170             num_best = tmp;
171             best = s;
172         }
173     }
174     return pair<int,int>(num_best, best);
175 }
176
177
178 int RegressionPlanner::_CountSatisfied(Condition& cond, int which_binding)
179 {
180     int num = 0;
181     for(int var = 0; var < cond.vars[which_binding].size(); ++var)
182         if(cond.vars[which_binding][var] != NULL) ++num;
183     return num;
184 }
185
186 list<pair<WORLDSTATE,Condition> >::iterator RegressionPlanner::
187     FindComplete(list<pair<WORLDSTATE,Condition> >& possible_bindings,
188     Condition& Conds)
189 {
190         list<pair<WORLDSTATE, Condition> >::iterator b(possible_bindings.begin());
191         while(b != possible_bindings.end())
192         {
193                 if(NoNulls(b->second.vars)) return b;///~here
194                 ++b;
195         }
196         return b;
197 }
198
199 // we assume that if there is a possible row without nulls, then
200 // there will not be another row without nulls
201 int RegressionPlanner::NoNulls(vector<vector<GameObject*> >& vars)
202 {
203         if(vars.size() == 0) return 0;
204         for(int v=0; v<vars[0].size(); ++v)
205         {
206                 if(vars[0][v] == NULL) return 0;
207         }
208         return 1;
209 }
210
211 void RegressionPlanner::SaveAll(void)
212 {
213     ///~~ save everything relevant to the recursive search
214     ///~~ We need to be able to pick up exactly where we left off
215 }
216
217 // returns 1 iff retPlan is valued with the root of a plan that
218 // starts at the current worldstate, passes through the worldstate
219 // indicated by the first of the pair, and ends up satisfying the
220 // conditions in Conds.
221 // throws TimeOutException
222 // DESTRUCTIVE ON retPlan
223 int RegressionPlanner::PlanOnRest(PlanNode*&retPlan,
224                pair<WORLDSTATE,Condition>& bindings, int which_binding, bool use_stack)
225 {
226         // try the which_bindings first.  if no good, continue to
227         // plan with the other bindings and see whether we can
228         // simply add some more operators to make the whole thing
229         // work out.  if it doesn't work out, return 0
230         
231         PlanNode* p = NULL;
232         retPlan = NULL;
233        
234         // Get the operators that will satisfy the remaining conditions
235         if(!use_stack) Ops = GetMeOperators(bindings.second, which_binding);
236    
237         if(Ops.empty()) return 0; // no ops can satisfy condition
238     // try to plan for the preconds of the ops for which_binding
239     if(!use_stack) { ops = Ops.begin(); done = 0; }
240         for(;ops != Ops.end(); ++ops, ++done)
241         {
242         if(!use_stack) op = ops->begin();
243            
244         for(op = ops->begin();op!=ops->end(); ++op)
245         {
246             try{
247                         if(!MakeSubPlan(p, op->PreConds, bindings.first, use_stack)) break;
248             }catch(TimeOutException tout) { throw tout; }
249                     ConcatPlans(p, new PlanNode(*op));
250                     if(!MergePlans(retPlan, p)) break;
251             use_stack = false;
252         }
253         if(op != ops->end()) // failed to plan for one of the variables
254         {
255             ///~write me on second pass
256             DeletePlan(p);
257             break;
258         }
259         use_stack = false;
260         }
261         if(ops != Ops.end()) // failed in step 1
262         {
263                 ///~write me on second pass
264                 ///~ use done here
265                 // try to recover by using the parts we've already planned
266                 // for with the other possible variable bindings
267                 ///~ feasible???
268         DeletePlan(retPlan);
269         retPlan = NULL;
270                 return 0;
271         }
272         else
273                 return 1;
274        
275 }
276
277
278
279 // creates a plan that starts at the given world state and achieves Conds
280 // returns 1 iff success, else 0
281 // throws TimeOutException
282 int RegressionPlanner::MakeSubPlan(PlanNode*& plan, Condition& Conds, WORLDSTATE& state, bool use_stack)
283 {
284     bool success = false, Continue = false;
285     if(!use_stack) cond = &Conds;
286     while(true)
287     {
288         // fill in the conds that are satisfied in W
289         if(!use_stack)
290         {
291             *cond = CheckWorldState(state.first, *cond);
292
293             if(NoNulls(cond->vars)) // conditions completely satisfied in world state
294             {
295                 if(PlanStack.empty()) return 1; // successful planning
296                 PlanNode* p = NULL, *node;
297                 do
298                 {
299                     Continue = false;
300                    
301                     // add the operator this is a precond of to a plan node
302                     node = new PlanNode(*OpStack.top().second.second);
303
304                     // and merge it with its other operators' plan nodes (after concating to the NULL)
305                     ConcatPlans(p, node);
306                     MergePlans(PlanStack.top(), p);
307
308                     // then move to the next operator in that list
309                     if(++OpStack.top().second.second == OpStack.top().second.first->end())
310                     {
311                         if(++OpStack.top().second.first == OpStack.top().first.end())
312                         {
313                             // reached the end of the operators
314                             OpStack.pop();
315                             p = PlanStack.pop();
316                             if(OpStack.empty()) // out of operators, so we're done
317                             {
318                                 plan = p;
319                                 return 1; // planning success!!!
320                             }
321                             Continue = true;
322                         }
323                         OpStack.top().second.second = OpStack.top().second.first->begin();
324                     }
325
326                 }while(Continue);
327             }
328             // find the most promising variable binding
329             satisfied = CountSatisfied(*cond);
330                
331             // recursion part
332                         OpStack.push(
333                         pair<vector<list<Operator> >, pair<vector<list<Operator> >::iterator, list<Operator>::iterator> >(
334                                 GetMeOperators(Conds, satisfied.second),
335                                 pair<vector<list<Operator> >::iterator, list<Operator>::iterator>()));
336             PlanStack.push(NULL);
337             OpStack.top().second.first = OpStack.top().first.begin();
338         }
339                
340                 if(OpStack.top().first.empty()) // no operators found
341                 {
342                         ///~ second pass: try to plan for alternate variable bindings
343                         ///~~ handle unable to plan case
344                         OpStack.clear();
345             PlanStack.clear();
346             return 0;
347                 }
348                 else
349                 {
350                         OpStack.top().second.second = OpStack.top().second.first->begin();
351                         pair<vector<list<Operator> >, pair<vector<list<Operator> >::iterator, list<Operator>::iterator> >* cur;
352                        
353                         cur = &OpStack.top();
354                         cond = &cur->second.second->PreConds;
355                        
356             if(TimesUp()) throw TimeOutException();
357                 }
358                        
359        
360        use_stack = false;
361     }
362 }
363
364
365
366
367 void RegressionPlanner::ConcatPlans(PlanNode*& plan, PlanNode* newplan)
368 {
369         // traverse the plan and redirect all of its leaf nodes to branch to
370         // newplan
371         if(plan == NULL) plan = newplan;
372     else if(newplan == NULL) return;
373     else if(newplan != NULL)
374     {
375                 ResetFlags(plan);
376                 _ConcatPlans(plan, newplan);
377         }
378 }
379
380 void RegressionPlanner::_ConcatPlans(PlanNode* plan, PlanNode* newplan)
381 {
382         if(plan == newplan) return; // should never be encountered
383         if(PrevsSatisfied(plan))
384         {
385                 plan->num = 1;
386                 if(plan->isLeaf())
387                 {
388                         MakeLink(plan, newplan);
389                 }
390                 else
391                 {
392                        
393                         for(int b=0; b<plan->branches.size(); ++b)
394                                 _ConcatPlans(plan->branches[b], newplan);
395                 }
396         }
397 }
398
399 void RegressionPlanner::ResetFlags(PlanNode* plan)
400 {
401         plan->num = 0;
402         ///~ horribly redundant, but is there a better way?
403         for(int b=0; b<plan->branches.size(); ++b)
404                 ResetFlags(plan->branches[b]);
405 }
406
407 int RegressionPlanner::PrevsSatisfied(PlanNode* plan)
408 {
409         for(int p=0; p<plan->prevs.size(); ++p)
410                 if(plan->prevs[p]->num == 0) return 0;
411         return 1;
412 }
413
414
415 ///~ is this function even meaningful in a plan where variable values are
416 ///~ ignored?   Maybe there is a situation where the precond of one op
417 ///~ is explicitly the negation of the postcond of another op, but this
418 ///~ will certainly be rare, and there are bigger fish to fry, so this can wait
419 // returns 1 iff all threats resolved successfully
420 int RegressionPlanner::ResolveThreats(PlanNode*& plan1, PlanNode*& plan2)
421 {
422         ///~stub
423         return 1;
424         ///~stub
425 }
426
427 // returns 1 iff the plans are successfully merged and
428 // the result pointed to by plan1
429 int RegressionPlanner::MergePlans(PlanNode*& plan1, PlanNode*& plan2)
430 {
431     if(plan1 == NULL){
432                 plan1 = plan2;
433                 return 1;
434         }
435     if(plan2 == NULL) {
436         return 1;
437     }
438         if(!ResolveThreats(plan1, plan2)) return 0; // fail
439
440         MergeRoots(plan1, plan2); // recursive helper
441
442         return 1;
443 }
444
445 // plan1's pointer will point to the new root after call
446 void RegressionPlanner::MergeRoots(PlanNode*& plan1, PlanNode*& plan2)
447 {
448         if(plan2 == NULL) return;
449     if(plan1 == NULL) {
450         plan1 = plan2; return;
451     }
452     if(plan1->prevs.size() && plan2->prevs.size())
453         {
454                 PlanNode* dummy_root = new PlanNode(Operator());
455                 MakeLink(dummy_root, plan1);
456                 MakeLink(dummy_root, plan2);
457                 plan1 = dummy_root;
458         }
459         else if(plan1->prevs.size())
460         {
461                 if(!Member(plan1, plan2->branches))
462                 {
463                         // make plan2 the new root
464                         MakeLink(plan2, plan1);
465                 }
466                 plan1 = plan2;
467         }
468         else if(!Member(plan2, plan1->branches))
469         {
470                 // make plan1 the new root
471                 MakeLink(plan1, plan2);
472         }
473 }
474
475
476 // adds the sequence of operators that was executed in the forward search
477 // in order to get to the world state argument
478 void RegressionPlanner::AddForwardPart(PlanNode*& plan, WORLDSTATE& state)
479 {
480     ///~ needs alteration to work with acual forward search stuctures
481     ///~ be sure to check for plan==NULL
482         ///~
483     PlanNode* w = state.second;
484     PlanNode* newnode;
485     while(!w->prevs.empty())  // while not at the current worldstate
486     {   // work back to it
487         newnode = new PlanNode(w->Op); // assume holds op that was used to get to it
488         MakeLink(newnode, plan);
489         plan = newnode;
490                 w = w->prevs[0];
491     }
492 }
493
494 void DeletePlan(PlanNode* plan)
495 {
496         PlanNode* br; bool other;
497         if(plan != NULL)
498         {
499                 for(int b=0; b<plan->branches.size(); ++b)
500                 {
501                         br = plan->branches[b];
502                         other = false;
503                         for(int p=0; p<br->prevs.size(); ++p)
504                         {
505                                 if(br->prevs[p] == plan) br->prevs[p] = NULL;
506                                 else if(br->prevs[p] != NULL) other = true;
507                         }
508                         if(!other) DeletePlan(br);
509                 }
510                 delete plan;
511         }
512 }
513
Note: See TracBrowser for help on using the browser.