Soar Kernel  9.3.2 08-06-12
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
backtrace.cpp
Go to the documentation of this file.
1 #include <portability.h>
2 
3 /*************************************************************************
4  * PLEASE SEE THE FILE "license.txt" (INCLUDED WITH THIS SOFTWARE PACKAGE)
5  * FOR LICENSE AND COPYRIGHT INFORMATION.
6  *************************************************************************/
7 
8 /*************************************************************************
9  *
10  * file: backtrace.cpp
11  *
12  * =======================================================================
13  * Backtracing structures and routines. See also explain.c
14  * =======================================================================
15  */
16 
17 /* ====================================================================
18  Backtracing routines
19  ==================================================================== */
20 
21 #include <stdlib.h>
22 
23 #include "backtrace.h"
24 #include "mem.h"
25 #include "kernel.h"
26 #include "print.h"
27 #include "wmem.h"
28 #include "gdatastructs.h"
29 #include "agent.h"
30 #include "instantiations.h"
31 #include "production.h"
32 #include "symtab.h"
33 #include "explain.h"
34 #include "recmem.h"
35 #include "xml.h"
36 #include "soar_TraceNames.h"
37 
38 using namespace soar_TraceNames;
39 
40 /* ====================================================================
41 
42  Backtracing
43 
44  Four sets of conditions are maintained during backtracing: locals,
45  grounds, positive potentials, and negateds. Negateds are really
46  potentials, but we keep them separately throughout backtracing, and
47  ground them at the very end. Note that this means during backtracing,
48  the grounds, positive potentials, and locals are all instantiated
49  top-level positive conditions, so they all have a bt.wme_ on them.
50 
51  In order to avoid backtracing through the same instantiation twice,
52  we mark each instantiation as we BT it, by setting
53  inst->backtrace_number = backtrace_number (this is a global variable
54  which gets incremented each time we build a chunk).
55 
56  Locals, grounds, and positive potentials are kept on lists (see the
57  global variables below). These are consed lists of the conditions
58  (that is, the original instantiated conditions). Furthermore,
59  we mark the bt.wme_'s on each condition so we can quickly determine
60  whether a given condition is already in a given set. The "grounds_tc",
61  "potentials_tc", "locals_tc", and "chunker_bt_pref" fields on wme's
62  are used for this. Wmes are marked as "in the grounds" by setting
63  wme->grounds_tc = grounds_tc. For potentials and locals, we also
64  must set wme->chunker_bt_pref: if the same wme was tested by two
65  instantiations created at different times--times at which the wme
66  was supported by two different preferences--then we really need to
67  BT through *both* preferences. Marking the wmes with just "locals_tc"
68  or "potentials_tc" alone would prevent the second preference from
69  being BT'd.
70 
71  The add_to_grounds(), add_to_potentials(), and add_to_locals()
72  macros below are used to add conditions to these sets. The negated
73  conditions are maintained in the chunk_cond_set "negated_set."
74 
75  As we backtrace, each instantiation that has some Nots is added to
76  the list instantiations_with_nots. We have to go back afterwards
77  and figure out which Nots are between identifiers that ended up in
78  the grounds.
79 ==================================================================== */
80 
81 #ifdef USE_MACROS
82 
83 #define add_to_grounds(thisAgent, cond) { \
84  if ((cond)->bt.wme_->grounds_tc != thisAgent->grounds_tc) { \
85  (cond)->bt.wme_->grounds_tc = thisAgent->grounds_tc; \
86  push (thisAgent, (cond), thisAgent->grounds); } }
87 
88 #define add_to_potentials(thisAgent, cond) { \
89  if ((cond)->bt.wme_->potentials_tc != thisAgent->potentials_tc) { \
90  (cond)->bt.wme_->potentials_tc = thisAgent->potentials_tc; \
91  (cond)->bt.wme_->chunker_bt_pref = (cond)->bt.trace; \
92  push (thisAgent, (cond), thisAgent->positive_potentials); \
93  } else if ((cond)->bt.wme_->chunker_bt_pref != (cond)->bt.trace) { \
94  push (thisAgent, (cond), thisAgent->positive_potentials); } }
95 
96 #define add_to_locals(thisAgent, cond) { \
97  if ((cond)->bt.wme_->locals_tc != thisAgent->locals_tc) { \
98  (cond)->bt.wme_->locals_tc = thisAgent->locals_tc; \
99  (cond)->bt.wme_->chunker_bt_pref = (cond)->bt.trace; \
100  push (thisAgent, (cond), thisAgent->locals); \
101  } else if ((cond)->bt.wme_->chunker_bt_pref != (cond)->bt.trace) { \
102  push (thisAgent, (cond), thisAgent->locals); } }
103 
104 #else
105 
106 inline void add_to_grounds(agent* thisAgent, condition * cond)
107 {
108  if ((cond)->bt.wme_->grounds_tc != thisAgent->grounds_tc) {
109  (cond)->bt.wme_->grounds_tc = thisAgent->grounds_tc;
110  push (thisAgent, (cond), thisAgent->grounds); }
111 }
112 
113 inline void add_to_potentials(agent* thisAgent, condition * cond)
114 {
115  if ((cond)->bt.wme_->potentials_tc != thisAgent->potentials_tc) {
116  (cond)->bt.wme_->potentials_tc = thisAgent->potentials_tc;
117  (cond)->bt.wme_->chunker_bt_pref = (cond)->bt.trace;
118  push (thisAgent, (cond), thisAgent->positive_potentials);
119  } else if ((cond)->bt.wme_->chunker_bt_pref != (cond)->bt.trace) {
120  push (thisAgent, (cond), thisAgent->positive_potentials); }
121 }
122 
123 inline void add_to_locals(agent* thisAgent, condition * cond)
124 {
125  if ((cond)->bt.wme_->locals_tc != thisAgent->locals_tc) {
126  (cond)->bt.wme_->locals_tc = thisAgent->locals_tc;
127  (cond)->bt.wme_->chunker_bt_pref = (cond)->bt.trace;
128  push (thisAgent, (cond), thisAgent->locals);
129  } else if ((cond)->bt.wme_->chunker_bt_pref != (cond)->bt.trace) {
130  push (thisAgent, (cond), thisAgent->locals); }
131 }
132 #endif /* USE_MACROS */
133 
134 /* -------------------------------------------------------------------
135  Backtrace Through Instantiation
136 
137  This routine BT's through a given instantiation. The general method
138  is as follows:
139 
140  1. If we've already BT'd this instantiation, then skip it.
141  2. Mark the TC (in the instantiated conditions) of all higher goal
142  ids tested in top-level positive conditions
143  3. Scan through the instantiated conditions; add each one to the
144  appropriate set (locals, positive_potentials, grounds, negated_set).
145  4. If the instantiation has any Nots, add this instantiation to
146  the list of instantiations_with_nots.
147 ------------------------------------------------------------------- */
148 
149 /* mvp 5-17-94 */
150 void print_consed_list_of_conditions (agent* thisAgent, list *c, int indent) {
151  for (; c!=NIL; c=c->rest) {
152  if (get_printer_output_column(thisAgent) >= COLUMNS_PER_LINE-20) print (thisAgent, "\n ");
153 
154  /* mvp 5-17-94 */
155  print_spaces (thisAgent, indent);
156  print_condition (thisAgent, static_cast<condition_struct *>(c->first));
157  }
158 }
159 
160 /* mvp 5-17-94 */
161 void print_consed_list_of_condition_wmes (agent* thisAgent, list *c, int indent) {
162  for (; c!=NIL; c=c->rest) {
163  if (get_printer_output_column(thisAgent) >= COLUMNS_PER_LINE-20) print (thisAgent, "\n ");
164 
165  /* mvp 5-17-94 */
166  print_spaces (thisAgent, indent);
167  print (thisAgent, " ");
168  print_wme (thisAgent, (static_cast<condition *>(c->first))->bt.wme_);
169  }
170 }
171 
172 /* This is the wme which is causing this production to be backtraced through.
173  It is NULL when backtracing for a result preference. */
174 
175 /* mvp 5-17-94 */
178  goal_stack_level grounds_level,
179  condition *trace_cond,
180  bool *reliable,
181  int indent) {
182 
183  tc_number tc; /* use this to mark ids in the ground set */
184  tc_number tc2; /* use this to mark other ids we see */
185  condition *c;
186  list *grounds_to_print, *pots_to_print, *locals_to_print, *negateds_to_print;
187  Bool need_another_pass;
188  backtrace_str temp_explain_backtrace;
189 
190  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
191 
192  /* mvp 5-17-94 */
193  print_spaces (thisAgent, indent);
194  print (thisAgent, "... BT through instantiation of ");
195  if (inst->prod) print_with_symbols (thisAgent, "%y\n",inst->prod->name);
196  else print_string (thisAgent, "[dummy production]\n");
197 
198  xml_begin_tag(thisAgent, kTagBacktrace);
199  if (inst->prod) xml_att_val(thisAgent, kProduction_Name, inst->prod->name);
200  else xml_att_val(thisAgent, kProduction_Name, "[dummy production]");
201 
202  }
203 
204  /* --- if the instantiation has already been BT'd, don't repeat it --- */
205  if (inst->backtrace_number == thisAgent->backtrace_number) {
206  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
207 
208  /* mvp 5-17-94 */
209  print_spaces (thisAgent, indent);
210  print_string (thisAgent, "(We already backtraced through this instantiation.)\n");
211  xml_att_val(thisAgent, kBacktracedAlready, "true");
212  xml_end_tag(thisAgent, kTagBacktrace);
213  }
214  return;
215  }
216  inst->backtrace_number = thisAgent->backtrace_number;
217 
218  /* Record information on the production being backtraced through */
219  /* if (thisAgent->explain_flag) { */
220  if (thisAgent->sysparams[EXPLAIN_SYSPARAM]) {
221  temp_explain_backtrace.trace_cond = trace_cond; /* Not copied yet */
222  if (trace_cond == NULL) /* Backtracing for a result */
223  temp_explain_backtrace.result = TRUE;
224  else
225  temp_explain_backtrace.result = FALSE;
226 
227  temp_explain_backtrace.grounds = NIL;
228  temp_explain_backtrace.potentials = NIL;
229  temp_explain_backtrace.locals = NIL;
230  temp_explain_backtrace.negated = NIL;
231 
232  if (inst->prod) {
233  strncpy(temp_explain_backtrace.prod_name,inst->prod->name->sc.name, BUFFER_PROD_NAME_SIZE);
234  } else {
235  strncpy(temp_explain_backtrace.prod_name,"Dummy production", BUFFER_PROD_NAME_SIZE);
236  }
237  (temp_explain_backtrace.prod_name)[BUFFER_PROD_NAME_SIZE - 1] = 0; /* ensure null termination */
238 
239  temp_explain_backtrace.next_backtrace = NULL;
240  }
241 
242  if (!inst->reliable)
243  *reliable = false;
244 
245  /* --- mark transitive closure of each higher goal id that was tested in
246  the id field of a top-level positive condition --- */
247  tc = get_new_tc_number (thisAgent);
248  tc2 = get_new_tc_number (thisAgent);
249  need_another_pass = FALSE;
250 
251  for (c=inst->top_of_instantiated_conditions; c!=NIL; c=c->next) {
252  Symbol *id, *value;
253 
254  if (c->type!=POSITIVE_CONDITION) continue;
256 
257  if (id->id.tc_num == tc) {
258  /* --- id is already in the TC, so add in the value --- */
260  if (value->common.symbol_type==IDENTIFIER_SYMBOL_TYPE) {
261  /* --- if we already saw it before, we're going to have to go back
262  and make another pass to get the complete TC --- */
263  if (value->id.tc_num == tc2) need_another_pass = TRUE;
264  value->id.tc_num = tc;
265  }
266  } else if ((id->id.isa_goal) && (c->bt.level <= grounds_level)) {
267  /* --- id is a higher goal id that was tested: so add id to the TC --- */
268  id->id.tc_num = tc;
270  if (value->common.symbol_type==IDENTIFIER_SYMBOL_TYPE) {
271  /* --- if we already saw it before, we're going to have to go back
272  and make another pass to get the complete TC --- */
273  if (value->id.tc_num == tc2) need_another_pass = TRUE;
274  value->id.tc_num = tc;
275  }
276  } else {
277  /* --- as far as we know so far, id shouldn't be in the tc: so mark it
278  with number "tc2" to indicate that it's been seen already --- */
279  id->id.tc_num = tc2;
280  }
281  }
282 
283  /* --- if necessary, make more passes to get the complete TC through the
284  top-level positive conditions (recall that they're all super-simple
285  wme tests--all three fields are equality tests --- */
286  while (need_another_pass) {
287  Symbol *value;
288 
289  need_another_pass = FALSE;
290  for (c=inst->top_of_instantiated_conditions; c!=NIL; c=c->next) {
291  if (c->type!=POSITIVE_CONDITION)
292  continue;
294  continue;
296  if (value->common.symbol_type==IDENTIFIER_SYMBOL_TYPE)
297  if (value->id.tc_num != tc) {
298  value->id.tc_num = tc;
299  need_another_pass = TRUE;
300  }
301  } /* end of for loop */
302  } /* end of while loop */
303 
304  /* --- scan through conditions, collect grounds, potentials, & locals --- */
305  grounds_to_print = NIL;
306  pots_to_print = NIL;
307  locals_to_print = NIL;
308  negateds_to_print = NIL;
309 
310  /* Record the conds in the print_lists even if not going to be printed */
311 
312  for (c=inst->top_of_instantiated_conditions; c!=NIL; c=c->next) {
313  if (c->type==POSITIVE_CONDITION) {
314 
315  /* REW: begin 11.22.97 */
316  /* print (thisAgent, "\n Checking...");print_wme(c->bt.wme_);
317  if (c->bt.trace) print ("c->bt.trace exists..."); else print("\n no c->bt.trace...");
318  if (c->bt.wme_) {
319  print ("c->bt.wme_....");
320  if (c->bt.wme_->preference)
321  print("c->bt.wme_->preference");
322  else
323  print("\n no c->bt.wme_->preference");
324  } else
325  print ("\nNo WME No Preference!!!!!!");
326  print("\n");
327  if ((c->bt.trace) && (c->bt.wme_->preference)){
328  if (c->bt.trace != c->bt.wme_->preference) {
329  print("\n bt.trace and WME preferences not equal:\n");
330  print(thisAgent, "\nWME:"); print_wme(c->bt.wme_);
331  print("\n bt.trace:");
332  if (c->bt.trace) print_preference(c->bt.trace); else print(" NIL\n");
333  print("\n bt.wme_->preference:");
334  if (c->bt.wme_->preference) print_preference(c->bt.wme_->preference);
335  else print(" NIL\n");
336  c->bt.trace = c->bt.wme_->preference;
337  c->bt.level = c->bt.wme_->id->id.level;
338  }
339  }*/
340  /* REW: end 11.22.97 */
341  /* --- positive cond's are grounds, potentials, or locals --- */
343  add_to_grounds (thisAgent, c);
344  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM] ||
345  thisAgent->sysparams[EXPLAIN_SYSPARAM])
346  push (thisAgent, c, grounds_to_print);
347  }
348  else if (c->bt.level <= grounds_level) {
349  add_to_potentials (thisAgent, c);
350  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM] ||
351  thisAgent->sysparams[EXPLAIN_SYSPARAM])
352  push (thisAgent, c, pots_to_print);
353  }
354  else {
355  add_to_locals (thisAgent, c);
356  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM] ||
357  thisAgent->sysparams[EXPLAIN_SYSPARAM])
358  push (thisAgent, c, locals_to_print);
359  }
360  }
361  else {
362  /* --- negative or nc cond's are either grounds or potentials --- */
363  add_to_chunk_cond_set (thisAgent, &thisAgent->negated_set,
364  make_chunk_cond_for_condition(thisAgent, c));
365  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM] ||
366  thisAgent->sysparams[EXPLAIN_SYSPARAM])
367  push (thisAgent, c, negateds_to_print);
368  }
369  } /* end of for loop */
370 
371  /* --- add new nots to the not set --- */
372  if (inst->nots) push (thisAgent, inst, thisAgent->instantiations_with_nots);
373 
374  /* Now record the sets of conditions. Note that these are not necessarily */
375  /* the final resting place for these wmes. In particular potentials may */
376  /* move over to become grounds, but since all we really need for explain is*/
377  /* the list of wmes, this will do as a place to record them. */
378 
379  if (thisAgent->sysparams[EXPLAIN_SYSPARAM])
380  explain_add_temp_to_backtrace_list(thisAgent, &temp_explain_backtrace,grounds_to_print,
381  pots_to_print,locals_to_print,negateds_to_print);
382 
383  /* --- if tracing BT, print the resulting conditions, etc. --- */
384  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
385  not_struct *not1;
386 
387  /* mvp 5-17-94 */
388  print_spaces (thisAgent, indent);
389  print_string (thisAgent, " -->Grounds:\n");
390  xml_begin_tag(thisAgent, kTagGrounds);
391  print_consed_list_of_condition_wmes (thisAgent, grounds_to_print, indent);
392  xml_end_tag(thisAgent, kTagGrounds);
393  print (thisAgent, "\n");
394  print_spaces (thisAgent, indent);
395  print_string (thisAgent, "\n -->Potentials:\n");
396  xml_begin_tag(thisAgent, kTagPotentials);
397  print_consed_list_of_condition_wmes (thisAgent, pots_to_print, indent);
398  xml_end_tag(thisAgent, kTagPotentials);
399  print (thisAgent, "\n");
400  print_spaces (thisAgent, indent);
401  print_string (thisAgent, " -->Locals:\n");
402  xml_begin_tag(thisAgent, kTagLocals);
403  print_consed_list_of_condition_wmes (thisAgent, locals_to_print, indent);
404  xml_end_tag(thisAgent, kTagLocals);
405  print (thisAgent, "\n");
406  print_spaces (thisAgent, indent);
407  print_string (thisAgent, " -->Negated:\n");
408  xml_begin_tag(thisAgent, kTagNegated);
409  print_consed_list_of_conditions (thisAgent, negateds_to_print, indent);
410  xml_end_tag(thisAgent, kTagNegated);
411  print (thisAgent, "\n");
412  print_spaces (thisAgent, indent);
413  print_string (thisAgent, " -->Nots:\n");
414  /* mvp done */
415 
416  xml_begin_tag(thisAgent, kTagNots);
417  for (not1=inst->nots; not1!=NIL; not1=not1->next) {
418  print_with_symbols (thisAgent, " %y <> %y\n", not1->s1, not1->s2);
419  xml_begin_tag(thisAgent, kTagNot);
420  xml_att_val(thisAgent, kBacktraceSymbol1, not1->s1);
421  xml_att_val(thisAgent, kBacktraceSymbol2, not1->s2);
422  xml_end_tag(thisAgent, kTagNot);
423  }
424  xml_end_tag(thisAgent, kTagNots);
425  xml_end_tag(thisAgent, kTagBacktrace);
426  }
427 
428  /* Moved these free's down to here, to ensure they are cleared even if we're
429  not printing these lists */
430 
431  free_list (thisAgent, grounds_to_print);
432  free_list (thisAgent, pots_to_print);
433  free_list (thisAgent, locals_to_print);
434  free_list (thisAgent, negateds_to_print);
435 }
436 
437 /* ---------------------------------------------------------------
438  Trace Locals
439 
440  This routine backtraces through locals, and keeps doing so until
441  there are no more locals to BT.
442 --------------------------------------------------------------- */
443 
444 void trace_locals (agent* thisAgent, goal_stack_level grounds_level, bool *reliable) {
445 
446  /* mvp 5-17-94 */
447  cons *c, *prohibits;
448  condition *cond;
449  preference *bt_pref, *p;
450 
451  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
452  print_string (thisAgent, "\n\n*** Tracing Locals ***\n");
453  xml_begin_tag(thisAgent, kTagLocals);
454  }
455 
456  while (thisAgent->locals) {
457  c = thisAgent->locals;
458  thisAgent->locals = thisAgent->locals->rest;
459  cond = static_cast<condition_struct *>(c->first);
460  free_cons (thisAgent, c);
461 
462  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
463  print_string (thisAgent, "\nFor local ");
464  xml_begin_tag(thisAgent, kTagLocal);
465  print_wme (thisAgent, cond->bt.wme_);
466  print_string (thisAgent, " ");
467  }
468 
469  bt_pref = find_clone_for_level (cond->bt.trace,
470  static_cast<goal_stack_level>(grounds_level+1));
471  /* --- if it has a trace at this level, backtrace through it --- */
472  if (bt_pref) {
473 
474  /* mvp 5-17-94 */
475  backtrace_through_instantiation (thisAgent, bt_pref->inst, grounds_level,cond, reliable, 0);
476 
477  /* check if any prohibit preferences */
478  if (cond->bt.prohibits) {
479  for (prohibits=cond->bt.prohibits; prohibits!=NIL; prohibits=prohibits->rest) {
480  p = static_cast<preference_struct *>(prohibits->first);
481  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
482  print_string (thisAgent, " For prohibit preference: ");
483  xml_begin_tag(thisAgent, kTagProhibitPreference);
484  print_preference (thisAgent, p);
485  }
486  backtrace_through_instantiation (thisAgent, p->inst, grounds_level, cond, reliable, 6);
487 
488  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
489  xml_end_tag(thisAgent, kTagProhibitPreference);
490  }
491  }
492  }
493  /* mvp done */
494  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
495  xml_end_tag(thisAgent, kTagLocal);
496  }
497  continue;
498  }
499 
500  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
501  print_string (thisAgent, "...no trace, can't BT");
502  // add an empty <backtrace> tag to make parsing XML easier
503  xml_begin_tag(thisAgent, kTagBacktrace);
504  xml_end_tag(thisAgent, kTagBacktrace);
505  }
506  /* --- for augmentations of the local goal id, either handle the
507  "^quiescence t" test or discard it --- */
510  thisAgent->quiescence_symbol) &&
512  thisAgent->t_symbol) &&
513  (! cond->test_for_acceptable_preference)) {
514  *reliable = false;
515  }
516  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
517  xml_end_tag(thisAgent, kTagLocal);
518  }
519  continue;
520  }
521 
522  /* --- otherwise add it to the potential set --- */
523  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
524  print_string (thisAgent, " --> make it a potential.");
525  xml_begin_tag(thisAgent, kTagAddToPotentials);
526  xml_end_tag(thisAgent, kTagAddToPotentials);
527  }
528  add_to_potentials (thisAgent, cond);
529 
530  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
531  xml_end_tag(thisAgent, kTagLocal);
532  }
533 
534  } /* end of while locals loop */
535 
536  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
537  xml_end_tag(thisAgent, kTagLocals);
538  }
539 }
540 
541 /* ---------------------------------------------------------------
542  Trace Grounded Potentials
543 
544  This routine looks for positive potentials that are in the TC
545  of the ground set, and moves them over to the ground set. This
546  process is repeated until no more positive potentials are in
547  the TC of the grounds.
548 --------------------------------------------------------------- */
549 
550 void trace_grounded_potentials (agent* thisAgent) {
551  tc_number tc;
552  cons *c, *next_c, *prev_c;
553  condition *pot;
554  Bool need_another_pass;
555 
556  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
557  print_string (thisAgent, "\n\n*** Tracing Grounded Potentials ***\n");
558  xml_begin_tag(thisAgent, kTagGroundedPotentials);
559  }
560 
561  /* --- setup the tc of the ground set --- */
562  tc = get_new_tc_number(thisAgent);
563  for (c=thisAgent->grounds; c!=NIL; c=c->rest)
564  add_cond_to_tc (thisAgent, static_cast<condition_struct *>(c->first), tc, NIL, NIL);
565 
566  need_another_pass = TRUE;
567  while (need_another_pass) {
568  need_another_pass = FALSE;
569  /* --- look for any potentials that are in the tc now --- */
570  prev_c = NIL;
571  for (c=thisAgent->positive_potentials; c!=NIL; c=next_c) {
572  next_c = c->rest;
573  pot = static_cast<condition_struct *>(c->first);
574  if (cond_is_in_tc (thisAgent, pot, tc)) {
575  /* --- pot is a grounded potential, move it over to ground set --- */
576  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
577  print_string (thisAgent, "\n-->Moving to grounds: ");
578  print_wme (thisAgent, pot->bt.wme_);
579  }
580  if (prev_c) prev_c->rest = next_c; else thisAgent->positive_potentials = next_c;
581  if (pot->bt.wme_->grounds_tc != thisAgent->grounds_tc) { /* add pot to grounds */
582  pot->bt.wme_->grounds_tc = thisAgent->grounds_tc;
583  c->rest = thisAgent->grounds; thisAgent->grounds = c;
584  add_cond_to_tc (thisAgent, pot, tc, NIL, NIL);
585  need_another_pass = TRUE;
586  } else { /* pot was already in the grounds, do don't add it */
587  free_cons (thisAgent, c);
588  }
589  } else {
590  prev_c = c;
591  }
592  } /* end of for c */
593  } /* end of while need_another_pass */
594 
595  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
596  xml_end_tag(thisAgent, kTagGroundedPotentials);
597  }
598 }
599 
600 /* ---------------------------------------------------------------
601  Trace Ungrounded Potentials
602 
603  This routine backtraces through ungrounded potentials. At entry,
604  all potentials must be ungrounded. This BT's through each
605  potential that has some trace (at the right level) that we can
606  BT through. Other potentials are left alone. TRUE is returned
607  if anything was BT'd; FALSE if nothing changed.
608 --------------------------------------------------------------- */
609 
610 Bool trace_ungrounded_potentials (agent* thisAgent, goal_stack_level grounds_level, bool *reliable) {
611 
612  /* mvp 5-17-94 */
613  cons *c, *next_c, *prev_c, *prohibits;
614  cons *pots_to_bt;
615  condition *potential;
616  preference *bt_pref, *p;
617 
618  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
619  print_string (thisAgent, "\n\n*** Tracing Ungrounded Potentials ***\n");
620  xml_begin_tag(thisAgent, kTagUngroundedPotentials);
621  }
622 
623  /* --- scan through positive potentials, pick out the ones that have
624  a preference we can backtrace through --- */
625  pots_to_bt = NIL;
626  prev_c = NIL;
627  for (c=thisAgent->positive_potentials; c!=NIL; c=next_c) {
628  next_c = c->rest;
629  potential = static_cast<condition_struct *>(c->first);
630  bt_pref = find_clone_for_level (potential->bt.trace,
631  static_cast<goal_stack_level>(grounds_level+1));
632  if (bt_pref) {
633  if (prev_c) prev_c->rest = next_c; else thisAgent->positive_potentials = next_c;
634  c->rest = pots_to_bt; pots_to_bt = c;
635  } else {
636  prev_c = c;
637  }
638  }
639 
640  /* --- if none to BT, exit --- */
641  if (!pots_to_bt) {
642  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
643  xml_end_tag(thisAgent, kTagUngroundedPotentials);
644  }
645  return FALSE;
646  }
647 
648  /* --- backtrace through each one --- */
649  while (pots_to_bt) {
650  c = pots_to_bt;
651  pots_to_bt = pots_to_bt->rest;
652  potential = static_cast<condition_struct *>(c->first);
653  free_cons (thisAgent, c);
654  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
655  print_string (thisAgent, "\nFor ungrounded potential ");
656  xml_begin_tag(thisAgent, kTagUngroundedPotential);
657  print_wme (thisAgent, potential->bt.wme_);
658  print_string (thisAgent, " ");
659  }
660  bt_pref = find_clone_for_level (potential->bt.trace,
661  static_cast<goal_stack_level>(grounds_level+1));
662 
663  /* mvp 5-17-94 */
664  backtrace_through_instantiation (thisAgent, bt_pref->inst, grounds_level,potential, reliable, 0);
665  if (potential->bt.prohibits) {
666  for (prohibits=potential->bt.prohibits; prohibits!=NIL; prohibits=prohibits->rest) {
667  p = static_cast<preference_struct *>(prohibits->first);
668  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
669  print_string (thisAgent, " For prohibit preference: ");
670  xml_begin_tag(thisAgent, kTagProhibitPreference);
671  print_preference (thisAgent, p);
672  }
673  backtrace_through_instantiation (thisAgent, p->inst, grounds_level, potential, reliable, 6);
674 
675  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
676  xml_end_tag(thisAgent, kTagProhibitPreference);
677  }
678  }
679  }
680  /* mvp done */
681  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
682  xml_end_tag(thisAgent, kTagUngroundedPotential);
683  }
684  }
685 
686  if (thisAgent->sysparams[TRACE_BACKTRACING_SYSPARAM]) {
687  xml_end_tag(thisAgent, kTagUngroundedPotentials);
688  }
689 
690  return TRUE;
691 }
692 
693 void report_local_negation (agent* thisAgent, condition* c) {
694  if (thisAgent->sysparams[TRACE_CHUNK_NAMES_SYSPARAM]) {
695  // use the same code as the backtracing above
696  list* negated_to_print = NIL;
697  push (thisAgent, c, negated_to_print);
698 
699  print_string (thisAgent, "\n*** Chunk won't be formed due to local negation in backtrace ***\n");
700  xml_begin_tag(thisAgent, kTagLocalNegation);
701  print_consed_list_of_conditions (thisAgent, negated_to_print, 2);
702  xml_end_tag(thisAgent, kTagLocalNegation);
703 
704  free_list (thisAgent, negated_to_print);
705  }
706 }