sub_tables_xsb_i.h

00001 /* File:      sub_tables_xsb_i.h
00002 ** Author(s): Ernie Johnson
00003 ** Contact:   xsb-contact@cs.sunysb.edu
00004 ** 
00005 ** Copyright (C) The Research Foundation of SUNY, 1986, 1993-1998
00006 ** 
00007 ** XSB is free software; you can redistribute it and/or modify it under the
00008 ** terms of the GNU Library General Public License as published by the Free
00009 ** Software Foundation; either version 2 of the License, or (at your option)
00010 ** any later version.
00011 ** 
00012 ** XSB is distributed in the hope that it will be useful, but WITHOUT ANY
00013 ** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00014 ** FOR A PARTICULAR PURPOSE.  See the GNU Library General Public License for
00015 ** more details.
00016 ** 
00017 ** You should have received a copy of the GNU Library General Public License
00018 ** along with XSB; if not, write to the Free Software Foundation,
00019 ** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00020 **
00021 ** $Id: sub_tables_xsb_i.h,v 1.10 2006/01/09 00:06:32 tswift Exp $
00022 ** 
00023 */
00024 
00025 
00026 #include "tst_aux.h"
00027 #include "deref.h"
00028 
00029 
00030 /*=========================================================================*/
00031 
00032 /*
00033  *                Subsumptive Call Check/Insert Operation
00034  *                =======================================
00035  */
00036 
00037 
00038 /*-------------------------------------------------------------------------*/
00039 
00040 /*
00041  * Answer Template Creation
00042  * ------------------------
00043  * There are three ways that the answer template may be created during a
00044  * Subsumptive Call Check/Insert Operation:
00045  * (1) If a producing table entry is found during the lookup of a call,
00046  *     then the template appears in the first several entries of the
00047  *     TrieVarBindings[] array.
00048  * (2) If a subsuming, but non-producing, entry is found during call
00049  *     lookup, then the template for the call must be reconstructed
00050  *     based upon the producer associated with the found entry.
00051  * (3) If no subsuming entry is found, then the call is inserted into
00052  *     the trie, and the template exists on the (trie-specific) Trail.
00053  * See the file slginsts_xsb_i.h for the layout of the answer template.
00054  */
00055 
00056 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00057 
00058 inline static  CPtr extract_template_from_lookup(CTXTdeclc CPtr ans_tmplt) {
00059 
00060   int i;
00061 
00062   i = 0;
00063   while ( TrieVarBindings[i] != (Cell) (& TrieVarBindings[i]) )
00064     *ans_tmplt-- = TrieVarBindings[i++];
00065   *ans_tmplt = makeint(i);
00066   return ans_tmplt;
00067 }
00068 
00069 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00070 
00071 inline static
00072 CPtr reconstruct_template_for_producer(CTXTdeclc TabledCallInfo *call_info,
00073                                        SubProdSF subsumer, CPtr ans_tmplt) {
00074 
00075   int sizeAnsTmplt;
00076   Cell subterm, symbol;
00077 
00078   /*
00079    * Store the symbols along the path of the more general call.
00080    */
00081   SymbolStack_ResetTOS;
00082   SymbolStack_PushPath(subg_leaf_ptr(subsumer));
00083 
00084   /*
00085    * Push the arguments of the subsumed call.
00086    */
00087   TermStack_ResetTOS;
00088   TermStack_PushLowToHighVector(CallInfo_Arguments(*call_info),
00089                                 CallInfo_CallArity(*call_info))
00090 
00091   /*
00092    * Create the answer template while we process.  Since we know we have a
00093    * more general subsuming call, we can greatly simplify the "matching"
00094    * process: we know we either have exact matches of non-variable symbols
00095    * or a variable paired with some subterm of the current call.
00096    */
00097   sizeAnsTmplt = 0;
00098   while ( ! TermStack_IsEmpty ) {
00099     TermStack_Pop(subterm);
00100     XSB_Deref(subterm);
00101     SymbolStack_Pop(symbol);
00102     if ( IsTrieVar(symbol) && IsNewTrieVar(symbol) ) {
00103       *ans_tmplt-- = subterm;
00104       sizeAnsTmplt++;
00105     }
00106     else if ( IsTrieFunctor(symbol) )
00107       TermStack_PushFunctorArgs(subterm)
00108     else if ( IsTrieList(symbol) )
00109       TermStack_PushListArgs(subterm)
00110   }
00111   *ans_tmplt = makeint(sizeAnsTmplt);
00112   return ans_tmplt;
00113 }
00114 
00115 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00116 
00117 inline static  CPtr extract_template_from_insertion(CTXTdeclc CPtr ans_tmplt) {
00118 
00119   int i;
00120 
00121   i = 0;
00122   while ( i < (int) Trail_NumBindings )
00123     *ans_tmplt-- = (Cell)Trail_Base[i++];
00124   *ans_tmplt = makeint(i);
00125   return ans_tmplt;
00126 }
00127 
00128 /*-------------------------------------------------------------------------*/
00129 
00130 /*
00131  * Subsumptive Call Check/Insert
00132  * -----------------------------
00133  * Look for a subsuming call in the table and conditionally create an
00134  * entry for the given one.  An entry for the call is created when
00135  * either
00136  *   1) no subsuming call exists in the table, or
00137  *   2) a more general (not variant) call exists, but its table is
00138  *      incomplete.
00139  * Therefore, no entry is created when either
00140  *  1) a variant call already exists in the table, or
00141  *  2) a more general (not variant) call is found and its table is
00142  *     complete.
00143  * Subsumptive call check/insert statistics are also updated.
00144  *
00145  * This routine relies on a lower-level lookup function rather than the
00146  * interface function subsumptive_trie_lookup() because this latter
00147  * function unwinds the trail, destroying the answer template in certain
00148  * cases.  The supplied template location is assumed to be the Choice
00149  * Point Stack, and in particular, a pointer to the topmost used Cell.
00150  *
00151  * It is assumed that the Call Trie exists (that there is at least a
00152  * root node).
00153  */
00154 
00155 inline static  void subsumptive_call_search(CTXTdeclc TabledCallInfo *callStruct,
00156                                             CallLookupResults *results) {
00157 
00158   BTNptr btRoot, btn;
00159   CPtr answer_template;    /* Initially, the location to create the answer
00160                               template, then a pointer to the template
00161                               itself: INT-encoded size followed by a vector
00162                               of subterms. */
00163   SubProdSF sf_with_ans_set;  /* Pointer to a producer; the subgoal from
00164                                  which the call will consume */
00165   TriePathType path_type;
00166 
00167 
00168 #ifdef DEBUG_CALL_CHK_INS
00169   char *targetGN = "";   /* allows you to spy on a particular predicate */
00170   char *goal_name;
00171 
00172   goal_name = get_name(TIF_PSC(CallInfo_TableInfo(*callStruct)));
00173   if ( strcmp(targetGN,goal_name) == 0 ) {
00174     fprintf(stddbg,"\nCall Check/Insert (#%d overall) on:\n  ",
00175                NumSubOps_CallCheckInsert + 1);
00176     printTabledCall(stddbg,*callStruct);
00177     fprintf(stddbg,"\n");
00178   }
00179 #endif
00180 
00181   NumSubOps_CallCheckInsert++;
00182   btRoot = TIF_CallTrie(CallInfo_TableInfo(*callStruct));
00183   answer_template = CallInfo_VarVectorLoc(*callStruct) - 1;
00184 
00185   /* Handle 0-ary Predicates
00186      ----------------------- */
00187   if (CallInfo_CallArity(*callStruct) == 0) {
00188     xsbBool isNew;
00189 
00190     btn = bt_escape_search(CTXTc btRoot, &isNew);
00191     if ( isNew )
00192       NumSubOps_ProducerCall++;
00193     else {
00194       if ( is_completed(CallTrieLeaf_GetSF(btn)) )
00195         NumSubOps_CallToCompletedTable++;
00196       else
00197         NumSubOps_VariantCall++;
00198     }
00199     CallLUR_VariantFound(*results) = ( ! isNew );
00200     CallLUR_Leaf(*results) = btn;
00201     CallLUR_Subsumer(*results) = CallTrieLeaf_GetSF(btn);
00202     *answer_template = makeint(0);
00203     CallLUR_VarVector(*results) = answer_template;
00204     return;
00205   }
00206 
00207   /* Handle N-ary Predicates, N > 0
00208      ------------------------------ */
00209   TermStack_ResetTOS;
00210   TermStackLog_ResetTOS;
00211   Trail_ResetTOS;
00212   TermStack_PushLowToHighVector(CallInfo_Arguments(*callStruct),
00213                                 CallInfo_CallArity(*callStruct));
00214 
00215   btn = iter_sub_trie_lookup(CTXTc btRoot, &path_type);
00216 
00217   /*
00218    * If this subsuming call maintains its own answer set, then this call
00219    * can consume from it.  Otherwise, this subsuming call is itself
00220    * subsumed and is consuming from some producer.  The new call will
00221    * then consume from this producer, too.  However, the computed answer
00222    * template was for the found subsuming call, not the one from which
00223    * consumption will occur.  Therefore, the template must be
00224    * recomputed.  In either case, if no variant was found AND the
00225    * subsuming call is incomplete, an entry is created in the Call Trie.
00226    */
00227 
00228   if ( path_type == NO_PATH ) {    /* new producer */
00229     NumSubOps_ProducerCall++;
00230     Trail_Unwind_All;
00231     CallLUR_Subsumer(*results) = NULL;  /* no SF found, so no subsumer */
00232     CallLUR_VariantFound(*results) = NO;
00233     CallLUR_Leaf(*results) =
00234       bt_insert(CTXTc btRoot,stl_restore_variant_cont(CTXT),NO_INSERT_SYMBOL);
00235     CallLUR_VarVector(*results) =
00236       extract_template_from_insertion(CTXTc answer_template);
00237     Trail_Unwind_All;
00238 #ifdef DEBUG_CALL_CHK_INS
00239     if ( strcmp(targetGN,goal_name) == 0 ) {
00240       fprintf(stddbg,"New Producer Goal: ");
00241       printTriePath(stddbg,CallLUR_Leaf(*results),NO);
00242       fprintf(stddbg,"\n");
00243     }
00244 #endif
00245     return;
00246   }
00247   else {                           /* consume from producer */
00248   /* Set Correct Answer Template
00249      --------------------------- */
00250     sf_with_ans_set = (SubProdSF)CallTrieLeaf_GetSF(btn);
00251     if ( IsSubsumptiveProducer(sf_with_ans_set) ) {
00252 #ifdef DEBUG_CALL_CHK_INS
00253       if ( strcmp(targetGN,goal_name) == 0 ) {
00254         fprintf(stddbg,"Found producer:\n  ");
00255         sfPrintGoal(stddbg,sf_with_ans_set,YES);
00256         fprintf(stddbg,"\nWith ");   /* continued below */
00257       }
00258 #endif
00259       if ( is_completed(sf_with_ans_set) )
00260         NumSubOps_CallToCompletedTable++;
00261       else {
00262         if ( path_type == VARIANT_PATH )
00263           NumSubOps_VariantCall++;
00264         else
00265           NumSubOps_SubsumedCall++;
00266       }
00267       answer_template = extract_template_from_lookup(CTXTc answer_template);
00268       Trail_Unwind_All;
00269     }
00270     else {                         /* consume from subsumed call */
00271 #ifdef DEBUG_CALL_CHK_INS
00272       if ( strcmp(targetGN,goal_name) == 0 ) {
00273         fprintf(stddbg,"Found entry without own answer table:\n  ");
00274         sfPrintGoal(stddbg,sf_with_ans_set,YES);
00275         fprintf(stddbg,"\nRecomputing template for:\n  ");
00276         sfPrintGoal(stddbg,conssf_producer(sf_with_ans_set),YES);
00277         fprintf(stddbg,"\n");   /* continue with A.T. print, below */
00278       }
00279 #endif
00280       sf_with_ans_set = conssf_producer(sf_with_ans_set);
00281       if ( is_completed(sf_with_ans_set) )
00282         NumSubOps_CallToCompletedTable++;
00283       else
00284         NumSubOps_SubsumedCall++;
00285       Trail_Unwind_All;
00286       answer_template =
00287         reconstruct_template_for_producer(CTXTc callStruct, sf_with_ans_set,
00288                                           answer_template);
00289     }
00290 
00291 #ifdef DEBUG_CALL_CHK_INS
00292     if ( strcmp(targetGN,goal_name) == 0 )
00293       printAnswerTemplate(stddbg,
00294                           answer_template + int_val(*answer_template),
00295                           int_val(*answer_template));
00296 #endif
00297     CallLUR_Subsumer(*results) = (VariantSF)sf_with_ans_set;
00298     CallLUR_Leaf(*results) = btn;
00299     CallLUR_VariantFound(*results) = (path_type == VARIANT_PATH);
00300     CallLUR_VarVector(*results) = answer_template;
00301 
00302     /* Conditionally Create Call Entry
00303        ------------------------------- */
00304     if ( (path_type != VARIANT_PATH) && (! is_completed(sf_with_ans_set)) ) {
00305       NumSubOps_SubsumedCallEntry++;
00306       CallLUR_Leaf(*results) =
00307         bt_insert(CTXTc btRoot,stl_restore_variant_cont(CTXT),NO_INSERT_SYMBOL);
00308       Trail_Unwind_All;
00309 #ifdef DEBUG_CALL_CHK_INS
00310       if ( strcmp(targetGN,goal_name) == 0 ) {
00311         fprintf(stddbg,"Constructed new Call entry:\n  ");
00312         printTriePath(stddbg,CallLUR_Leaf(*results),NO);
00313         fprintf(stddbg,"\n");
00314       }
00315 #endif
00316     }
00317   }
00318 }
00319 
00320 /*=========================================================================*/
00321 
00322 /*
00323  *               Subsumptive Answer Check/Insert Operation
00324  *               =========================================
00325  */
00326 
00327 
00328 /*
00329  * Create an Empty Answer Set, represented as a Time-Stamped Trie.
00330  * Note that the root of the TST is labelled with a ret/n symbol,
00331  * where `n' is the number of terms in an answer.
00332  */
00333 
00334 inline static  void *newAnswerSet(CTXTdeclc int n, TSTNptr Parent) {
00335 
00336   TSTNptr root;
00337   Cell symbol;
00338 
00339   if ( n > 0 )
00340     symbol = EncodeTriePSC(get_ret_psc(n));
00341   else
00342     symbol = EncodeTrieConstant(makestring(get_ret_string()));
00343   New_TSTN(root, TS_ANSWER_TRIE_TT, TRIE_ROOT_NT, symbol, Parent, NULL );
00344   TSTN_TimeStamp(root) = EMPTY_TST_TIMESTAMP;
00345   return root;
00346 }
00347 
00348 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00349 
00350 /*
00351  * Update statistical info, allocate an Answer Set object to house the
00352  * answer if the set was originally empty, conditionally insert the
00353  * answer into the set, and indicate to the caller whether it is new.
00354  */
00355 
00356 inline static
00357 TSTNptr subsumptive_answer_search(CTXTdeclc SubProdSF sf, int nTerms,
00358                                   CPtr answerVector, xsbBool *isNew) {
00359 
00360   TSTNptr root, tstn;
00361 
00362   NumSubOps_AnswerCheckInsert++;
00363   if ( IsNULL(subg_ans_root_ptr(sf)) )
00364     subg_ans_root_ptr(sf) = newAnswerSet(CTXTc nTerms, (TSTNptr) sf);
00365   root = (TSTNptr)subg_ans_root_ptr(sf);
00366   tstn = subsumptive_tst_search( CTXTc root, nTerms, answerVector,
00367                                  ProducerSubsumesSubgoals(sf), isNew );
00368   if ( *isNew )
00369     NumSubOps_AnswerInsert++;
00370   return tstn;
00371 }
00372 
00373 /*=========================================================================*/

Generated on Wed Jul 26 13:30:42 2006 for XSB by  doxygen 1.4.5