Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

backtrace.c

Go to the documentation of this file.
00001 /*************************************************************************
00002  *
00003  *  file:  backtrace.c
00004  *
00005  * =======================================================================
00006  *  
00007  *  Backtracing structures and routines.  See also explain.c
00008  *  
00009  *  
00010  * =======================================================================
00011  *
00012  * Copyright 1995-2003 Carnegie Mellon University,
00013  *                                                                               University of Michigan,
00014  *                                                                               University of Southern California/Information
00015  *                                                                               Sciences Institute. All rights reserved.
00016  *                                                                              
00017  * Redistribution and use in source and binary forms, with or without
00018  * modification, are permitted provided that the following conditions are met:
00019  *
00020  * 1.   Redistributions of source code must retain the above copyright notice,
00021  *              this list of conditions and the following disclaimer. 
00022  * 2.   Redistributions in binary form must reproduce the above copyright notice,
00023  *              this list of conditions and the following disclaimer in the documentation
00024  *              and/or other materials provided with the distribution. 
00025  *
00026  * THIS SOFTWARE IS PROVIDED BY THE SOAR CONSORTIUM ``AS IS'' AND ANY EXPRESS OR
00027  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00028  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
00029  * EVENT SHALL THE SOAR CONSORTIUM  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00030  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00031  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00032  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00033  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00034  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036  * The views and conclusions contained in the software and documentation are
00037  * those of the authors and should not be interpreted as representing official
00038  * policies, either expressed or implied, of Carnegie Mellon University, the
00039  * University of Michigan, the University of Southern California/Information
00040  * Sciences Institute, or the Soar consortium.
00041  * =======================================================================
00042  */
00043 
00044 /* ====================================================================
00045                         Backtracing routines
00046    ==================================================================== */
00047 
00048 #include "soarkernel.h"
00049 
00050 #include <ctype.h>
00051 
00052 #include "explain.h"
00053 
00054 /* ====================================================================
00055 
00056                             Backtracing
00057 
00058    Four sets of conditions are maintained during backtracing:  locals,
00059    grounds, positive potentials, and negateds.  Negateds are really
00060    potentials, but we keep them separately throughout backtracing, and
00061    ground them at the very end.  Note that this means during backtracing,
00062    the grounds, positive potentials, and locals are all instantiated
00063    top-level positive conditions, so they all have a bt.wme on them.
00064 
00065    In order to avoid backtracing through the same instantiation twice,
00066    we mark each instantiation as we BT it, by setting
00067    inst->backtrace_number = backtrace_number (this is a global variable
00068    which gets incremented each time we build a chunk).
00069 
00070    Locals, grounds, and positive potentials are kept on lists (see the
00071    global variables below).  These are consed lists of the conditions
00072    (that is, the original instantiated conditions).  Furthermore,
00073    we mark the bt.wme's on each condition so we can quickly determine
00074    whether a given condition is already in a given set.  The "grounds_tc",
00075    "potentials_tc", "locals_tc", and "chunker_bt_pref" fields on wme's
00076    are used for this.  Wmes are marked as "in the grounds" by setting
00077    wme->grounds_tc = grounds_tc.  For potentials and locals, we also
00078    must set wme->chunker_bt_pref:  if the same wme was tested by two
00079    instantiations created at different times--times at which the wme
00080    was supported by two different preferences--then we really need to
00081    BT through *both* preferences.  Marking the wmes with just "locals_tc"
00082    or "potentials_tc" alone would prevent the second preference from
00083    being BT'd.
00084 
00085    The add_to_grounds(), add_to_potentials(), and add_to_locals()
00086    macros below are used to add conditions to these sets.  The negated
00087    conditions are maintained in the chunk_cond_set "negated_set."
00088 
00089    As we backtrace, each instantiation that has some Nots is added to
00090    the list instantiations_with_nots.  We have to go back afterwards
00091    and figure out which Nots are between identifiers that ended up in
00092    the grounds.
00093 ==================================================================== */
00094 
00095 #define add_to_grounds(cond) { \
00096   if ((cond)->bt.wme->grounds_tc != current_agent(grounds_tc)) { \
00097     (cond)->bt.wme->grounds_tc = current_agent(grounds_tc); \
00098     push ((cond), current_agent(grounds)); } }
00099 
00100 #define add_to_potentials(cond) { \
00101   if ((cond)->bt.wme->potentials_tc != current_agent(potentials_tc)) { \
00102     (cond)->bt.wme->potentials_tc = current_agent(potentials_tc); \
00103     (cond)->bt.wme->chunker_bt_pref = (cond)->bt.trace; \
00104     push ((cond), current_agent(positive_potentials)); \
00105   } else if ((cond)->bt.wme->chunker_bt_pref != (cond)->bt.trace) { \
00106     push ((cond), current_agent(positive_potentials)); } }
00107 
00108 #define add_to_locals(cond) { \
00109   if ((cond)->bt.wme->locals_tc != current_agent(locals_tc)) { \
00110     (cond)->bt.wme->locals_tc = current_agent(locals_tc); \
00111     (cond)->bt.wme->chunker_bt_pref = (cond)->bt.trace; \
00112     push ((cond), current_agent(locals)); \
00113   } else if ((cond)->bt.wme->chunker_bt_pref != (cond)->bt.trace) { \
00114     push ((cond), current_agent(locals)); } }
00115 
00116 /* -------------------------------------------------------------------
00117                      Backtrace Through Instantiation
00118 
00119    This routine BT's through a given instantiation.  The general method
00120    is as follows:
00121 
00122      1. If we've already BT'd this instantiation, then skip it.
00123      2. Mark the TC (in the instantiated conditions) of all higher goal
00124         ids tested in top-level positive conditions
00125      3. Scan through the instantiated conditions; add each one to the
00126         appropriate set (locals, positive_potentials, grounds, negated_set).
00127      4. If the instantiation has any Nots, add this instantiation to
00128         the list of instantiations_with_nots.
00129 ------------------------------------------------------------------- */
00130 
00131 /* mvp 5-17-94 */
00132 void print_consed_list_of_conditions(list * c, int indent)
00133 {
00134     for (; c != NIL; c = c->rest) {
00135         if (get_printer_output_column() >= COLUMNS_PER_LINE - 20)
00136             print("\n      ");
00137 
00138         /* mvp 5-17-94 */
00139         print_spaces(indent);
00140         print_condition(c->first);
00141     }
00142 }
00143 
00144 /* mvp 5-17-94 */
00145 void print_consed_list_of_condition_wmes(list * c, int indent)
00146 {
00147     for (; c != NIL; c = c->rest) {
00148         if (get_printer_output_column() >= COLUMNS_PER_LINE - 20)
00149             print("\n      ");
00150 
00151         /* mvp 5-17-94 */
00152         print_spaces(indent);
00153         print("     ");
00154         print_wme(((condition *) (c->first))->bt.wme);
00155     }
00156 }
00157 
00158 /* This is the wme which is causing this production to be backtraced through. 
00159    It is NULL when backtracing for a result preference.                   */
00160 
00161 /* mvp 5-17-94 */
00162 void backtrace_through_instantiation(instantiation * inst,
00163                                      goal_stack_level grounds_level, condition * trace_cond, int indent)
00164 {
00165 
00166     tc_number tc;               /* use this to mark ids in the ground set */
00167     tc_number tc2;              /* use this to mark other ids we see */
00168     condition *c;
00169     list *grounds_to_print, *pots_to_print, *locals_to_print, *negateds_to_print;
00170     bool need_another_pass;
00171     backtrace_str temp_explain_backtrace;
00172 
00173 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00174 
00175     if (current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM]) {
00176 
00177         /* mvp 5-17-94 */
00178         print_spaces(indent);
00179         print("... BT through instantiation of ");
00180         if (inst->prod)
00181             print_with_symbols("%y\n", inst->prod->name);
00182         else
00183             print_string("[dummy production]\n");
00184     }
00185 #endif
00186 
00187     /* --- if the instantiation has already been BT'd, don't repeat it --- */
00188     if (inst->backtrace_number == current_agent(backtrace_number)) {
00189 
00190 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00191         if (current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM]) {
00192 
00193             /* mvp 5-17-94 */
00194             print_spaces(indent);
00195             print_string("(We already backtraced through this instantiation.)\n");
00196         }
00197 #endif
00198 
00199         return;
00200     }
00201     inst->backtrace_number = current_agent(backtrace_number);
00202 
00203     /* Record information on the production being backtraced through */
00204     /* if (current_agent(explain_flag)) { */
00205     if (current_agent(sysparams)[EXPLAIN_SYSPARAM]) {
00206         temp_explain_backtrace.trace_cond = trace_cond; /* Not copied yet */
00207         if (trace_cond == NULL) /* Backtracing for a result */
00208             temp_explain_backtrace.result = TRUE;
00209         else
00210             temp_explain_backtrace.result = FALSE;
00211 
00212         temp_explain_backtrace.grounds = NIL;
00213         temp_explain_backtrace.potentials = NIL;
00214         temp_explain_backtrace.locals = NIL;
00215         temp_explain_backtrace.negated = NIL;
00216 
00217         if (inst->prod) {
00218             strncpy(temp_explain_backtrace.prod_name, inst->prod->name->sc.name, PROD_NAME_SIZE);
00219         } else {
00220             strncpy(temp_explain_backtrace.prod_name, "Dummy production", PROD_NAME_SIZE);
00221         }
00222         temp_explain_backtrace.prod_name[PROD_NAME_SIZE - 1] = 0;       /* in case the strncpy truncated the string */
00223 
00224         temp_explain_backtrace.next_backtrace = NULL;
00225     }
00226 
00227     /* --- check okay_to_variablize flag --- */
00228     if (!inst->okay_to_variablize)
00229         current_agent(variablize_this_chunk) = FALSE;
00230 
00231     /* --- mark transitive closure of each higher goal id that was tested in
00232        the id field of a top-level positive condition --- */
00233     tc = get_new_tc_number();
00234     tc2 = get_new_tc_number();
00235     need_another_pass = FALSE;
00236 
00237     for (c = inst->top_of_instantiated_conditions; c != NIL; c = c->next) {
00238         Symbol *id, *value;
00239 
00240         if (c->type != POSITIVE_CONDITION)
00241             continue;
00242         id = referent_of_equality_test(c->data.tests.id_test);
00243 
00244         if (id->id.tc_num == tc) {
00245             /* --- id is already in the TC, so add in the value --- */
00246             value = referent_of_equality_test(c->data.tests.value_test);
00247             if (value->common.symbol_type == IDENTIFIER_SYMBOL_TYPE) {
00248                 /* --- if we already saw it before, we're going to have to go back
00249                    and make another pass to get the complete TC --- */
00250                 if (value->id.tc_num == tc2)
00251                     need_another_pass = TRUE;
00252                 value->id.tc_num = tc;
00253             }
00254         } else if ((id->id.isa_goal) && (c->bt.level <= grounds_level)) {
00255             /* --- id is a higher goal id that was tested: so add id to the TC --- */
00256             id->id.tc_num = tc;
00257             value = referent_of_equality_test(c->data.tests.value_test);
00258             if (value->common.symbol_type == IDENTIFIER_SYMBOL_TYPE) {
00259                 /* --- if we already saw it before, we're going to have to go back
00260                    and make another pass to get the complete TC --- */
00261                 if (value->id.tc_num == tc2)
00262                     need_another_pass = TRUE;
00263                 value->id.tc_num = tc;
00264             }
00265         } else {
00266             /* --- as far as we know so far, id shouldn't be in the tc: so mark it
00267                with number "tc2" to indicate that it's been seen already --- */
00268             id->id.tc_num = tc2;
00269         }
00270     }
00271 
00272     /* --- if necessary, make more passes to get the complete TC through the
00273        top-level positive conditions (recall that they're all super-simple
00274        wme tests--all three fields are equality tests --- */
00275     while (need_another_pass) {
00276         Symbol *value;
00277 
00278         need_another_pass = FALSE;
00279         for (c = inst->top_of_instantiated_conditions; c != NIL; c = c->next) {
00280             if (c->type != POSITIVE_CONDITION)
00281                 continue;
00282             if (referent_of_equality_test(c->data.tests.id_test)->id.tc_num != tc)
00283                 continue;
00284             value = referent_of_equality_test(c->data.tests.value_test);
00285             if (value->common.symbol_type == IDENTIFIER_SYMBOL_TYPE)
00286                 if (value->id.tc_num != tc) {
00287                     value->id.tc_num = tc;
00288                     need_another_pass = TRUE;
00289                 }
00290         }                       /* end of for loop */
00291     }                           /* end of while loop */
00292 
00293     /* --- scan through conditions, collect grounds, potentials, & locals --- */
00294     grounds_to_print = NIL;
00295     pots_to_print = NIL;
00296     locals_to_print = NIL;
00297     negateds_to_print = NIL;
00298 
00299     /* Record the conds in the print_lists even if not going to be printed */
00300 
00301     for (c = inst->top_of_instantiated_conditions; c != NIL; c = c->next) {
00302         if (c->type == POSITIVE_CONDITION) {
00303 
00304             /* REW: begin 11.22.97 */
00305             /* print ("\n Checking...");print_wme(c->bt.wme);
00306                if (c->bt.trace) print ("c->bt.trace exists..."); else print("\n    no c->bt.trace...");
00307                if (c->bt.wme) { 
00308                print ("c->bt.wme....");
00309                if  (c->bt.wme->preference)
00310                print("c->bt.wme->preference");
00311                else 
00312                print("\n no c->bt.wme->preference");
00313                }      else
00314                print ("\nNo WME No Preference!!!!!!");
00315                print("\n"); 
00316                if ((c->bt.trace) && (c->bt.wme->preference)){
00317                if (c->bt.trace != c->bt.wme->preference) {
00318                print("\n bt.trace and WME preferences not equal:\n");
00319                print("\nWME:"); print_wme(c->bt.wme);
00320                print("\n bt.trace:"); 
00321                if (c->bt.trace) print_preference(c->bt.trace); else print(" NIL\n");
00322                print("\n bt.wme->preference:"); 
00323                if (c->bt.wme->preference) print_preference(c->bt.wme->preference);
00324                else print(" NIL\n");
00325                c->bt.trace = c->bt.wme->preference;
00326                c->bt.level = c->bt.wme->id->id.level;
00327                }
00328                } */
00329             /* REW: end   11.22.97 */
00330             /* --- positive cond's are grounds, potentials, or locals --- */
00331             if (referent_of_equality_test(c->data.tests.id_test)->id.tc_num == tc) {
00332                 add_to_grounds(c);
00333 
00334 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00335                 if (current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM] || current_agent(sysparams)[EXPLAIN_SYSPARAM])
00336 #else
00337                 if (current_agent(sysparams)[EXPLAIN_SYSPARAM])
00338 #endif
00339                     push(c, grounds_to_print);
00340             } else if (c->bt.level <= grounds_level) {
00341                 add_to_potentials(c);
00342                 if (current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM] || current_agent(sysparams)[EXPLAIN_SYSPARAM])
00343                     push(c, pots_to_print);
00344             } else {
00345                 add_to_locals(c);
00346 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00347                 if (current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM] || current_agent(sysparams)[EXPLAIN_SYSPARAM])
00348 #else
00349                 if (current_agent(sysparams)[EXPLAIN_SYSPARAM])
00350 #endif
00351                     push(c, locals_to_print);
00352             }
00353         } else {
00354             /* --- negative or nc cond's are either grounds or potentials --- */
00355             add_to_chunk_cond_set(&current_agent(negated_set), make_chunk_cond_for_condition(c));
00356 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00357             if (current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM] || current_agent(sysparams)[EXPLAIN_SYSPARAM])
00358 #else
00359             if (current_agent(sysparams)[EXPLAIN_SYSPARAM])
00360 #endif
00361                 push(c, negateds_to_print);
00362         }
00363     }                           /* end of for loop */
00364 
00365     /* --- add new nots to the not set --- */
00366     if (inst->nots)
00367         push(inst, current_agent(instantiations_with_nots));
00368 
00369     /* Now record the sets of conditions.  Note that these are not necessarily */
00370     /* the final resting place for these wmes.  In particular potentials may   */
00371     /* move over to become grounds, but since all we really need for explain is */
00372     /* the list of wmes, this will do as a place to record them.               */
00373 
00374     if (current_agent(sysparams)[EXPLAIN_SYSPARAM])
00375         explain_add_temp_to_backtrace_list(&temp_explain_backtrace, grounds_to_print,
00376                                            pots_to_print, locals_to_print, negateds_to_print);
00377 
00378 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00379 
00380     /* --- if tracing BT, print the resulting conditions, etc. --- */
00381     if (current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM]) {
00382         not *not1;
00383 
00384         /* mvp 5-17-94 */
00385         print_spaces(indent);
00386         print_string("  -->Grounds:\n");
00387         print_consed_list_of_condition_wmes(grounds_to_print, indent);
00388         print("\n");
00389         print_spaces(indent);
00390         print_string("\n  -->Potentials:\n");
00391         print_consed_list_of_condition_wmes(pots_to_print, indent);
00392         print("\n");
00393         print_spaces(indent);
00394         print_string("  -->Locals:\n");
00395         print_consed_list_of_condition_wmes(locals_to_print, indent);
00396         print("\n");
00397         print_spaces(indent);
00398         print_string("  -->Negated:\n");
00399         print_consed_list_of_conditions(negateds_to_print, indent);
00400         print("\n");
00401         print_spaces(indent);
00402         print_string("  -->Nots:\n");
00403         /* mvp done */
00404 
00405         for (not1 = inst->nots; not1 != NIL; not1 = not1->next)
00406             print_with_symbols("    %y <> %y\n", not1->s1, not1->s2);
00407     }
00408 #endif
00409 
00410     /* Moved these free's down to here, to ensure they are cleared even if we're 
00411        not printing these lists     */
00412 
00413     free_list(grounds_to_print);
00414     free_list(pots_to_print);
00415     free_list(locals_to_print);
00416     free_list(negateds_to_print);
00417 }
00418 
00419 /* ---------------------------------------------------------------
00420                              Trace Locals
00421 
00422    This routine backtraces through locals, and keeps doing so until
00423    there are no more locals to BT.
00424 --------------------------------------------------------------- */
00425 
00426 void trace_locals(goal_stack_level grounds_level)
00427 {
00428 
00429     /* mvp 5-17-94 */
00430     cons *c, *prohibits;
00431     condition *cond;
00432     preference *bt_pref, *p;
00433 
00434 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00435     if (current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM])
00436         print_string("\n\n*** Tracing Locals ***\n");
00437 #endif
00438 
00439     while (current_agent(locals)) {
00440         c = current_agent(locals);
00441         current_agent(locals) = current_agent(locals)->rest;
00442         cond = c->first;
00443         free_cons(c);
00444 
00445 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00446 
00447         if (current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM]) {
00448             print_string("\nFor local ");
00449             print_wme(cond->bt.wme);
00450             print_string(" ");
00451         }
00452 #endif
00453 
00454         bt_pref = find_clone_for_level(cond->bt.trace, (goal_stack_level) (grounds_level + 1));
00455         /* --- if it has a trace at this level, backtrace through it --- */
00456         if (bt_pref) {
00457 
00458 #ifdef NO_TOP_JUST
00459             if (bt_pref->inst) {
00460 
00461                 /* mvp 5-17-94 */
00462                 backtrace_through_instantiation(bt_pref->inst, grounds_level, cond, 0);
00463 
00464                 /* check if any prohibit preferences */
00465                 if (cond->bt.prohibits) {
00466                     for (prohibits = cond->bt.prohibits; prohibits != NIL; prohibits = prohibits->rest) {
00467                         p = prohibits->first;
00468 
00469 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00470                         if (current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM]) {
00471                             print_string("     For prohibit preference: ");
00472                             print_preference(p);
00473                         }
00474 #endif
00475                         if (p->inst)
00476                             backtrace_through_instantiation(p->inst, grounds_level, cond, 6);
00477                     }
00478                 }
00479                 /* mvp done */
00480             }
00481 #else
00482 
00483             /* mvp 5-17-94 */
00484             backtrace_through_instantiation(bt_pref->inst, grounds_level, cond, 0);
00485 
00486             /* check if any prohibit preferences */
00487             if (cond->bt.prohibits) {
00488                 for (prohibits = cond->bt.prohibits; prohibits != NIL; prohibits = prohibits->rest) {
00489                     p = prohibits->first;
00490 
00491 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00492                     if (current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM]) {
00493                         print_string("     For prohibit preference: ");
00494                         print_preference(p);
00495                     }
00496 #endif
00497                     backtrace_through_instantiation(p->inst, grounds_level, cond, 6);
00498                 }
00499             }
00500             /* mvp done */
00501 
00502 #endif
00503             continue;
00504         }
00505 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00506         if (current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM])
00507             print_string("...no trace, can't BT");
00508 #endif
00509 
00510         /* --- for augmentations of the local goal id, either handle the
00511            "^quiescence t" test or discard it --- */
00512         if (referent_of_equality_test(cond->data.tests.id_test)->id.isa_goal) {
00513             if ((referent_of_equality_test(cond->data.tests.attr_test) ==
00514                  current_agent(quiescence_symbol)) &&
00515                 (referent_of_equality_test(cond->data.tests.value_test) ==
00516                  current_agent(t_symbol)) && (!cond->test_for_acceptable_preference)) {
00517                 current_agent(variablize_this_chunk) = FALSE;
00518                 current_agent(quiescence_t_flag) = TRUE;
00519             }
00520             continue;
00521         }
00522 
00523         /* --- otherwise add it to the potential set --- */
00524 
00525 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00526         if (current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM])
00527             print_string(" --> make it a potential.");
00528 #endif
00529         add_to_potentials(cond);
00530 
00531     }                           /* end of while locals loop */
00532 }
00533 
00534 /* ---------------------------------------------------------------
00535                        Trace Grounded Potentials
00536 
00537    This routine looks for positive potentials that are in the TC
00538    of the ground set, and moves them over to the ground set.  This
00539    process is repeated until no more positive potentials are in
00540    the TC of the grounds.
00541 --------------------------------------------------------------- */
00542 
00543 void trace_grounded_potentials(void)
00544 {
00545     tc_number tc;
00546     cons *c, *next_c, *prev_c;
00547     condition *pot;
00548     bool need_another_pass;
00549 
00550 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00551 
00552     if (current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM])
00553         print_string("\n\n*** Tracing Grounded Potentials ***\n");
00554 #endif
00555 
00556     /* --- setup the tc of the ground set --- */
00557     tc = get_new_tc_number();
00558     for (c = current_agent(grounds); c != NIL; c = c->rest)
00559         add_cond_to_tc(c->first, tc, NIL, NIL);
00560 
00561     need_another_pass = TRUE;
00562     while (need_another_pass) {
00563         need_another_pass = FALSE;
00564         /* --- look for any potentials that are in the tc now --- */
00565         prev_c = NIL;
00566         for (c = current_agent(positive_potentials); c != NIL; c = next_c) {
00567             next_c = c->rest;
00568             pot = c->first;
00569             if (cond_is_in_tc(pot, tc)) {
00570                 /* --- pot is a grounded potential, move it over to ground set --- */
00571 
00572 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00573                 if (current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM]) {
00574                     print_string("\n-->Moving to grounds: ");
00575                     print_wme(pot->bt.wme);
00576                 }
00577 #endif
00578                 if (prev_c)
00579                     prev_c->rest = next_c;
00580                 else
00581                     current_agent(positive_potentials) = next_c;
00582                 if (pot->bt.wme->grounds_tc != current_agent(grounds_tc)) {     /* add pot to grounds */
00583                     pot->bt.wme->grounds_tc = current_agent(grounds_tc);
00584                     c->rest = current_agent(grounds);
00585                     current_agent(grounds) = c;
00586                     add_cond_to_tc(pot, tc, NIL, NIL);
00587                     need_another_pass = TRUE;
00588                 } else {        /* pot was already in the grounds, do don't add it */
00589                     free_cons(c);
00590                 }
00591             } else {
00592                 prev_c = c;
00593             }
00594         }                       /* end of for c */
00595     }                           /* end of while need_another_pass */
00596 }
00597 
00598 /* ---------------------------------------------------------------
00599                      Trace Ungrounded Potentials
00600 
00601    This routine backtraces through ungrounded potentials.  At entry,
00602    all potentials must be ungrounded.  This BT's through each
00603    potential that has some trace (at the right level) that we can
00604    BT through.  Other potentials are left alone.  TRUE is returned
00605    if anything was BT'd; FALSE if nothing changed.
00606 --------------------------------------------------------------- */
00607 
00608 bool trace_ungrounded_potentials(goal_stack_level grounds_level)
00609 {
00610 
00611     /* mvp 5-17-94 */
00612     cons *c, *next_c, *prev_c, *prohibits;
00613     cons *pots_to_bt;
00614     condition *potential;
00615     preference *bt_pref, *p;
00616 
00617 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00618     if (current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM])
00619         print_string("\n\n*** Tracing Ungrounded Potentials ***\n");
00620 #endif
00621 
00622     /* --- scan through positive potentials, pick out the ones that have
00623        a preference we can backtrace through --- */
00624     pots_to_bt = NIL;
00625     prev_c = NIL;
00626     for (c = current_agent(positive_potentials); c != NIL; c = next_c) {
00627         next_c = c->rest;
00628         potential = c->first;
00629         bt_pref = find_clone_for_level(potential->bt.trace, (goal_stack_level) (grounds_level + 1));
00630         if (bt_pref) {
00631             if (prev_c)
00632                 prev_c->rest = next_c;
00633             else
00634                 current_agent(positive_potentials) = next_c;
00635             c->rest = pots_to_bt;
00636             pots_to_bt = c;
00637         } else {
00638             prev_c = c;
00639         }
00640     }
00641 
00642     /* --- if none to BT, exit --- */
00643     if (!pots_to_bt)
00644         return FALSE;
00645 
00646     /* --- backtrace through each one --- */
00647     while (pots_to_bt) {
00648         c = pots_to_bt;
00649         pots_to_bt = pots_to_bt->rest;
00650         potential = c->first;
00651         free_cons(c);
00652 
00653 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00654         if (current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM]) {
00655             print_string("\nFor ungrounded potential ");
00656             print_wme(potential->bt.wme);
00657             print_string(" ");
00658         }
00659 #endif
00660 
00661         bt_pref = find_clone_for_level(potential->bt.trace, (goal_stack_level) (grounds_level + 1));
00662 
00663 #ifdef NO_TOP_JUST
00664         if (bt_pref->inst)
00665             backtrace_through_instantiation(bt_pref->inst, grounds_level, potential, 0);
00666 #else
00667 
00668         /* mvp 5-17-94 */
00669         backtrace_through_instantiation(bt_pref->inst, grounds_level, potential, 0);
00670 #endif
00671 
00672         if (potential->bt.prohibits) {
00673             for (prohibits = potential->bt.prohibits; prohibits != NIL; prohibits = prohibits->rest) {
00674                 p = prohibits->first;
00675 
00676 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00677                 if (current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM]) {
00678                     print_string("     For prohibit preference: ");
00679                     print_preference(p);
00680                 }
00681 #endif
00682 
00683 #ifdef NO_TOP_JUST
00684                 if (p->inst)
00685                     backtrace_through_instantiation(p->inst, grounds_level, potential, 6);
00686 #else
00687                 backtrace_through_instantiation(p->inst, grounds_level, potential, 6);
00688 #endif
00689 
00690             }
00691         }
00692         /* mvp done */
00693     }
00694     return TRUE;
00695 }

Generated on Thu Dec 11 13:00:14 2003 for Soar Kernel by doxygen 1.3.5