table_stats.c

00001 /* File:      table_stats.c
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: table_stats.c,v 1.22 2006/03/24 16:40:29 tswift Exp $
00022 ** 
00023 */
00024 
00025 
00026 #include "xsb_config.h"
00027 #include "xsb_debug.h"
00028 
00029 #include <stdio.h>
00030 
00031 #include "auxlry.h"
00032 #include "cell_xsb.h"
00033 #include "psc_xsb.h"
00034 #include "table_stats.h"
00035 #include "trie_internals.h"
00036 #include "macro_xsb.h"
00037 #include "error_xsb.h"
00038 #include "flags_xsb.h"
00039 #include "debug_xsb.h"
00040 #include "thread_xsb.h"
00041 
00042 /*==========================================================================*/
00043 
00044 /*
00045  *                T A B L I N G   S T A T I S T I C S
00046  *                ===================================
00047  */
00048 
00049 
00050 /*
00051  *                      Recording Current Usage
00052  *                      -----------------------
00053  */
00054 
00055 
00056 NodeStats node_statistics(Structure_Manager *sm) {
00057 
00058   NodeStats stats;
00059 
00060 
00061   SM_CurrentCapacity(*sm, NodeStats_NumBlocks(stats),
00062                      NodeStats_NumAllocNodes(stats));
00063   SM_CountFreeStructs(*sm, NodeStats_NumFreeNodes(stats));
00064   NodeStats_NodeSize(stats) = SM_StructSize(*sm);
00065 
00066   return stats;
00067 }
00068 
00069 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00070 
00071 HashStats hash_statistics(Structure_Manager *sm) {
00072 
00073   HashStats ht_stats;
00074   counter num_used_hdrs;
00075   BTHTptr pBTHT;
00076   BTNptr *ppBTN;
00077 
00078 
00079   ht_stats.hdr = node_statistics(sm);
00080 
00081   num_used_hdrs = 0;
00082   HashStats_NumBuckets(ht_stats) = 0;
00083   HashStats_TotalOccupancy(ht_stats) = 0;
00084   HashStats_NonEmptyBuckets(ht_stats) = 0;
00085   HashStats_BucketSize(ht_stats) = sizeof(void *);
00086   pBTHT = (BTHTptr)SM_AllocList(*sm);
00087   while ( IsNonNULL(pBTHT) ) {
00088 #ifdef DEBUG_ASSERTIONS
00089     /* Counter for contents of current hash table
00090        ------------------------------------------ */
00091     counter num_contents = 0;
00092 #endif
00093     num_used_hdrs++;
00094     HashStats_NumBuckets(ht_stats) += BTHT_NumBuckets(pBTHT);
00095     HashStats_TotalOccupancy(ht_stats) += BTHT_NumContents(pBTHT);
00096     for ( ppBTN = BTHT_BucketArray(pBTHT);
00097           ppBTN < BTHT_BucketArray(pBTHT) + BTHT_NumBuckets(pBTHT);
00098           ppBTN++ )
00099       if ( IsNonNULL(*ppBTN) ) {
00100 #ifdef DEBUG_ASSERTIONS
00101         /* Count the objects in each bucket
00102            -------------------------------- */
00103         BTNptr pBTN = *ppBTN;
00104         do {
00105           num_contents++;
00106           pBTN = BTN_Sibling(pBTN);
00107         } while ( IsNonNULL(pBTN) );
00108 #endif
00109         HashStats_NonEmptyBuckets(ht_stats)++;
00110       }
00111 #ifdef DEBUG_ASSERTIONS
00112     /* Compare counter and header values
00113        --------------------------------- */
00114     if ( num_contents != BTHT_NumContents(pBTHT) )
00115       xsb_warn("Inconsistent %s Usage Calculations:\n"
00116                "\tHash table occupancy mismatch.", SM_StructName(*sm));
00117 #endif
00118     pBTHT = BTHT_NextBTHT(pBTHT);
00119   }
00120   if ( HashStats_NumAllocHeaders(ht_stats) !=
00121        (num_used_hdrs + HashStats_NumFreeHeaders(ht_stats)) )
00122     xsb_warn("Inconsistent %s Usage Calculations:\n"
00123              "\tHeader count mismatch:  Alloc: %d  Used: %d  Free: %d",
00124              SM_StructName(*sm), HashStats_NumAllocHeaders(ht_stats),
00125              num_used_hdrs,  HashStats_NumFreeHeaders(ht_stats));
00126 
00127   return ht_stats;
00128 }
00129 
00130 
00131 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00132 
00133 NodeStats subgoal_statistics(CTXTdeclc Structure_Manager *sm) {
00134 
00135   NodeStats sg_stats;
00136   TIFptr tif;
00137   int nSubgoals;
00138   VariantSF pProdSF;
00139   SubConsSF pConsSF;
00140 
00141   sg_stats = node_statistics(sm);
00142   nSubgoals = 0;
00143   SYS_MUTEX_LOCK( MUTEX_TABLE );                                
00144   if ( sm == &smVarSF ) {
00145     for ( tif = tif_list.first;  IsNonNULL(tif);  tif = TIF_NextTIF(tif) )
00146       if ( IsVariantPredicate(tif) )
00147         for ( pProdSF = TIF_Subgoals(tif);  IsNonNULL(pProdSF);
00148               pProdSF = (VariantSF)subg_next_subgoal(pProdSF) )
00149           nSubgoals++;
00150   }
00151   /* No shared smProdSF or smConsSF in MT engine */
00152   else if ( sm == &smProdSF ) {
00153     for ( tif = tif_list.first;  IsNonNULL(tif);  tif = TIF_NextTIF(tif) )
00154       if ( IsSubsumptivePredicate(tif) )
00155         for ( pProdSF = TIF_Subgoals(tif);  IsNonNULL(pProdSF);
00156               pProdSF = (VariantSF)subg_next_subgoal(pProdSF) )
00157           nSubgoals++;
00158   }
00159   else if ( sm == &smConsSF ) {
00160     for ( tif = tif_list.first;  IsNonNULL(tif);  tif = TIF_NextTIF(tif) )
00161       if ( IsSubsumptivePredicate(tif) )
00162         for ( pProdSF = TIF_Subgoals(tif);  IsNonNULL(pProdSF);
00163               pProdSF = (VariantSF)subg_next_subgoal(pProdSF) )
00164           for ( pConsSF = subg_consumers(pProdSF);  IsNonNULL(pConsSF); 
00165                 pConsSF = conssf_consumers(pConsSF) )
00166             nSubgoals++;
00167   }
00168   else {
00169     SYS_MUTEX_UNLOCK( MUTEX_TABLE );                            
00170     xsb_dbgmsg((LOG_DEBUG, "Incorrect use of subgoal_statistics()\n"
00171                "SM does not contain subgoal frames"));
00172     return sg_stats;
00173   }
00174 
00175   SYS_MUTEX_UNLOCK( MUTEX_TABLE );                              
00176   if ( NodeStats_NumUsedNodes(sg_stats) != (counter) nSubgoals )
00177     xsb_warn("Inconsistent Subgoal Frame Usage Calculations:\n"
00178              "\tSubgoal Frame count mismatch");
00179 
00180   return sg_stats;
00181 }
00182 
00183 /*-------------------------------------------------------------------------*/
00184 
00185 /*
00186  *                      Displaying Current Usage
00187  *                      ------------------------
00188  */
00189 
00190 void print_detailed_tablespace_stats(CTXTdecl) {
00191 
00192   NodeStats
00193     btn,                /* Basic Trie Nodes */
00194     tstn,               /* Time Stamp Trie Nodes */
00195     aln,                /* Answer List Nodes */
00196     tsi,                /* Time Stamp Indices (Index Entries/Nodes) */
00197     varsf,              /* Variant Subgoal Frames */
00198     prodsf,             /* Subsumptive Producer Subgoal Frames */
00199     conssf;             /* Subsumptive Consumer Subgoal Frames */
00200 
00201   HashStats
00202     btht,               /* Basic Trie Hash Tables */
00203     tstht;              /* Time Stamp Trie Hash Tables */
00204   
00205 
00206   btn = node_statistics(&smTableBTN);
00207   btht = hash_statistics(&smTableBTHT);
00208   varsf = subgoal_statistics(CTXTc &smVarSF);
00209   prodsf = subgoal_statistics(CTXTc &smProdSF);
00210   conssf = subgoal_statistics(CTXTc &smConsSF);
00211   aln = node_statistics(&smALN);
00212   tstn = node_statistics(&smTSTN);
00213   tstht = hash_statistics(&smTSTHT);
00214   tsi = node_statistics(&smTSIN);
00215 
00216   printf("\n"
00217          "Table Space Usage\n");
00218   printf("  Current Total Allocation:   %12u bytes\n"
00219          "  Current Total Usage:        %12u bytes\n",
00220          CurrentTotalTableSpaceAlloc(btn,btht,varsf,prodsf,conssf,aln,
00221                                      tstn,tstht,tsi),
00222          CurrentTotalTableSpaceUsed(btn,btht,varsf,prodsf,conssf,aln,
00223                                     tstn,tstht,tsi));
00224   printf("\n"
00225          "  Basic Tries\n");
00226   printf("    Basic Trie Nodes (%u blocks)\n"
00227          "      Allocated:   %10u  (%8u bytes)\n"
00228          "      Used:        %10u  (%8u bytes)\n"
00229          "      Free:        %10u  (%8u bytes)\n",
00230          NodeStats_NumBlocks(btn),
00231          NodeStats_NumAllocNodes(btn),  NodeStats_SizeAllocNodes(btn),
00232          NodeStats_NumUsedNodes(btn),  NodeStats_SizeUsedNodes(btn),
00233          NodeStats_NumFreeNodes(btn),  NodeStats_SizeFreeNodes(btn));
00234   printf("    Basic Trie Hash Tables (%u blocks)\n"
00235          "      Headers:     %10u  (%8u bytes)\n"
00236          "        Used:      %10u  (%8u bytes)\n"
00237          "        Free:      %10u  (%8u bytes)\n"
00238          "      Buckets:     %10u  (%8u bytes)\n"
00239          "        Used:      %10u\n"
00240          "        Empty:     %10u\n"
00241          "      Occupancy:   %10u BTNs\n",
00242          HashStats_NumBlocks(btht),
00243          HashStats_NumAllocHeaders(btht),  HashStats_SizeAllocHeaders(btht),
00244          HashStats_NumUsedHeaders(btht),  HashStats_SizeUsedHeaders(btht),
00245          HashStats_NumFreeHeaders(btht),  HashStats_SizeFreeHeaders(btht),
00246          HashStats_NumBuckets(btht),  HashStats_SizeAllocBuckets(btht),
00247          HashStats_NonEmptyBuckets(btht),  HashStats_EmptyBuckets(btht),
00248          HashStats_TotalOccupancy(btht));
00249   printf("\n"
00250          "  Subgoal Frames\n"
00251          "    Variant Subgoal Frames (%u blocks)\n"
00252          "      Allocated:     %10u  (%8u bytes)\n"
00253          "      Used:          %10u  (%8u bytes)\n"
00254          "      Free:          %10u  (%8u bytes)\n"
00255          "    Subsumptive Producer Subgoal Frames (%u blocks)\n"
00256          "      Allocated:     %10u  (%8u bytes)\n"
00257          "      Used:          %10u  (%8u bytes)\n"
00258          "      Free:          %10u  (%8u bytes)\n"
00259          "    Subsumptive Consumer Subgoal Frames (%u blocks)\n"
00260          "      Allocated:     %10u  (%8u bytes)\n"
00261          "      Used:          %10u  (%8u bytes)\n"
00262          "      Free:          %10u  (%8u bytes)\n",
00263          NodeStats_NumBlocks(varsf),
00264          NodeStats_NumAllocNodes(varsf),  NodeStats_SizeAllocNodes(varsf),
00265          NodeStats_NumUsedNodes(varsf),  NodeStats_SizeUsedNodes(varsf),
00266          NodeStats_NumFreeNodes(varsf),  NodeStats_SizeFreeNodes(varsf),
00267          NodeStats_NumBlocks(prodsf),
00268          NodeStats_NumAllocNodes(prodsf),  NodeStats_SizeAllocNodes(prodsf),
00269          NodeStats_NumUsedNodes(prodsf),  NodeStats_SizeUsedNodes(prodsf),
00270          NodeStats_NumFreeNodes(prodsf),  NodeStats_SizeFreeNodes(prodsf),
00271          NodeStats_NumBlocks(conssf),
00272          NodeStats_NumAllocNodes(conssf),  NodeStats_SizeAllocNodes(conssf),
00273          NodeStats_NumUsedNodes(conssf),  NodeStats_SizeUsedNodes(conssf),
00274          NodeStats_NumFreeNodes(conssf),  NodeStats_SizeFreeNodes(conssf));
00275   printf("\n"
00276          "  Answer List Nodes (%u blocks)\n"
00277          "    Allocated:     %10u  (%8u bytes)\n"
00278          "    Used:          %10u  (%8u bytes)\n"
00279          "    Free:          %10u  (%8u bytes)\n",
00280          NodeStats_NumBlocks(aln),
00281          NodeStats_NumAllocNodes(aln),  NodeStats_SizeAllocNodes(aln),
00282          NodeStats_NumUsedNodes(aln),  NodeStats_SizeUsedNodes(aln),
00283          NodeStats_NumFreeNodes(aln),  NodeStats_SizeFreeNodes(aln));
00284   printf("\n"
00285          "  Time Stamp Tries\n"
00286          "    Time Stamp Trie Nodes (%u blocks)\n"
00287          "      Allocated:   %10u  (%8u bytes)\n"
00288          "      Used:        %10u  (%8u bytes)\n"
00289          "      Free:        %10u  (%8u bytes)\n",
00290          NodeStats_NumBlocks(tstn),
00291          NodeStats_NumAllocNodes(tstn),  NodeStats_SizeAllocNodes(tstn),
00292          NodeStats_NumUsedNodes(tstn),  NodeStats_SizeUsedNodes(tstn),
00293          NodeStats_NumFreeNodes(tstn) ,  NodeStats_SizeFreeNodes(tstn));
00294   printf("    Time Stamp Trie Hash Tables (%u blocks)\n"
00295          "      Headers:     %10u  (%8u bytes)\n"
00296          "        Used:      %10u  (%8u bytes)\n"
00297          "        Free:      %10u  (%8u bytes)\n"
00298          "      Buckets:     %10u  (%8u bytes)\n"
00299          "        Used:      %10u\n"
00300          "        Empty:     %10u\n"
00301          "      Occupancy:   %10u TSTNs\n",
00302          HashStats_NumBlocks(tstht),
00303          HashStats_NumAllocHeaders(tstht),  HashStats_SizeAllocHeaders(tstht),
00304          HashStats_NumUsedHeaders(tstht),  HashStats_SizeUsedHeaders(tstht),
00305          HashStats_NumFreeHeaders(tstht),  HashStats_SizeFreeHeaders(tstht),
00306          HashStats_NumBuckets(tstht),  HashStats_SizeAllocBuckets(tstht),
00307          HashStats_NonEmptyBuckets(tstht),  HashStats_EmptyBuckets(tstht),
00308          HashStats_TotalOccupancy(tstht));
00309   printf("    Time Stamp Trie Index Nodes (%u blocks)\n"
00310          "      Allocated:   %10u  (%8u bytes)\n"
00311          "      Used:        %10u  (%8u bytes)\n"
00312          "      Free:        %10u  (%8u bytes)\n",
00313          NodeStats_NumBlocks(tsi),
00314          NodeStats_NumAllocNodes(tsi),  NodeStats_SizeAllocNodes(tsi),
00315          NodeStats_NumUsedNodes(tsi),  NodeStats_SizeUsedNodes(tsi),
00316          NodeStats_NumFreeNodes(tsi),  NodeStats_SizeFreeNodes(tsi));
00317 
00318   if (flags[TRACE_STA]) {
00319     /* Report Maximum Usages
00320        --------------------- */
00321     update_maximum_tablespace_stats(&btn,&btht,&varsf,&prodsf,&conssf,
00322                                     &aln,&tstn,&tstht,&tsi);
00323     printf("\n"
00324            "Maximum Total Usage:        %12ld bytes\n",
00325            maximum_total_tablespace_usage());
00326     printf("Maximum Structure Usage:\n"
00327            "  ALNs:            %10u  (%8u bytes)\n"
00328            "  TSINs:           %10u  (%8u bytes)\n",
00329            maximum_answer_list_nodes(),
00330            maximum_answer_list_nodes() * NodeStats_NodeSize(aln),
00331            maximum_timestamp_index_nodes(),
00332            maximum_timestamp_index_nodes() * NodeStats_NodeSize(tsi));
00333   }
00334   printf("\n");
00335 }
00336 
00337 /*-------------------------------------------------------------------------*/
00338 
00339 /*
00340  *                       Recording Maximum Usage
00341  *                       -----------------------
00342  */
00343 
00344 /*
00345  * Most of the data structures used in tabling are persistent: table
00346  * info frames, subgoal frames, and the trie nodes and hash tables
00347  * (basic and time-stamped).  Therefore, the maximum usage of each of
00348  * these structures at any particular time during an evaluation is the
00349  * same as their current usage.  However, there are some structures
00350  * whose usage fluctuates during an evaluation.  In particular,
00351  * TimeStamp Indices and answer list nodes are reclaimed upon
00352  * completion.  Therefore, we explicitly track their maximum usage at
00353  * those times just prior to reclamation.  The following data
00354  * structure maintains the maximum usage for each of these structures.
00355  * And as the (ultimate) maximum usage of a particular structure is
00356  * independent of that of other structures, we also explicitly track
00357  * the maximum utilization of table space.
00358  */
00359 
00360 struct {
00361   counter tsi;                   /* TS Index Nodes */
00362   counter alns;                  /* Answer List Nodes */
00363   unsigned long  total_bytes;    /* total tablespace in bytes */
00364 } maxTableSpaceUsage = {0,0,0};
00365 
00366 
00367 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00368 
00369 void reset_maximum_tablespace_stats() {
00370 
00371   maxTableSpaceUsage.tsi = maxTableSpaceUsage.alns = 0;
00372   maxTableSpaceUsage.total_bytes = 0;
00373 }
00374 
00375 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00376 
00377 /*
00378  * To be used to facilitate statistical recordings, but in situations
00379  * where one is not currently inspecting results, e.g., when reclaiming
00380  * table space at completion.  This procedure queries the current state
00381  * of usage of all table components, and tests whether this is a new
00382  * maximum.
00383  */
00384 
00385 void compute_maximum_tablespace_stats(CTXTdecl) {
00386 
00387   NodeStats tstn, btn, aln, tsi;
00388   NodeStats varsf, prodsf, conssf;
00389   HashStats tstht, btht;
00390 
00391   btn = node_statistics(&smTableBTN);
00392   btht = hash_statistics(&smTableBTHT);
00393   varsf = subgoal_statistics(CTXTc &smVarSF);
00394   prodsf = subgoal_statistics(CTXTc &smProdSF);
00395   conssf = subgoal_statistics(CTXTc &smConsSF);
00396   tstn = node_statistics(&smTSTN);
00397   tstht = hash_statistics(&smTSTHT);
00398   tsi = node_statistics(&smTSIN);
00399   aln = node_statistics(&smALN);
00400 
00401   update_maximum_tablespace_stats(&btn,&btht,&varsf,&prodsf,&conssf,
00402                                   &aln,&tstn,&tstht,&tsi);
00403 }
00404 
00405 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00406 
00407 /*
00408  * To be used to facilitate statistical reporting at the moment -- when
00409  * one is currently inspecting results.  Presumably one would want to
00410  * independently query the current state of usage of all table
00411  * components for such reporting, so we use these results rather than
00412  * recompute them.
00413  */
00414 
00415 void update_maximum_tablespace_stats(NodeStats *btn, HashStats *btht,
00416                                      NodeStats *varsf, NodeStats *prodsf,
00417                                      NodeStats *conssf, NodeStats *aln,
00418                                      NodeStats *tstn, HashStats *tstht,
00419                                      NodeStats *tsi) {
00420    unsigned long  byte_size;
00421 
00422    byte_size = CurrentTotalTableSpaceUsed(*btn,*btht,*varsf,*prodsf,*conssf,
00423                                           *aln,*tstn,*tstht,*tsi);
00424    if ( byte_size > maxTableSpaceUsage.total_bytes )
00425      maxTableSpaceUsage.total_bytes = byte_size;
00426    if ( NodeStats_NumUsedNodes(*aln) > maxTableSpaceUsage.alns )
00427      maxTableSpaceUsage.alns = NodeStats_NumUsedNodes(*aln);
00428    if ( NodeStats_NumUsedNodes(*tsi) > maxTableSpaceUsage.tsi )
00429      maxTableSpaceUsage.tsi = NodeStats_NumUsedNodes(*tsi);
00430 }
00431 
00432 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00433 
00434 counter maximum_timestamp_index_nodes() {
00435 
00436   return (maxTableSpaceUsage.tsi);
00437 }
00438 
00439 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00440 
00441 counter maximum_answer_list_nodes() {
00442 
00443   return (maxTableSpaceUsage.alns);
00444 }
00445 
00446 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00447 
00448 unsigned long  maximum_total_tablespace_usage() {
00449 
00450   return (maxTableSpaceUsage.total_bytes);
00451 }
00452 
00453 /*-------------------------------------------------------------------------*/
00454 
00455 /*
00456  *               Recording and Displaying Operational Counts
00457  *               -------------------------------------------
00458  */
00459 
00460 NumSubOps numSubOps = INIT_NUMSUBOPS;
00461 
00462 
00463 void reset_subsumption_stats() {
00464 
00465   NumSubOps initRecord = INIT_NUMSUBOPS;
00466 
00467   numSubOps = initRecord;
00468 }
00469 
00470 
00471 void print_detailed_subsumption_stats() {
00472 
00473   printf("Subsumptive Operations\n"
00474          "  Subsumptive call check/insert ops: %8u\n"
00475          "  * Calls to nonexistent or incomplete tables\n"
00476          "    - Producers:                   %6u\n"
00477          "    - Variants of producers:       %6u\n"
00478          "    - Properly subsumed:           %6u\n"
00479          "        Resulted in call table entry: %u\n"
00480          "  * Calls to completed tables:     %6u\n",
00481          NumSubOps_CallCheckInsert, NumSubOps_ProducerCall,
00482          NumSubOps_VariantCall, NumSubOps_SubsumedCall,
00483          NumSubOps_SubsumedCallEntry, NumSubOps_CallToCompletedTable);
00484   printf("  Answer check/insert operations:    %8u\n"
00485          "  * Actual answer inserts:         %6u\n"
00486          "  * Derivation ratio (New/Total):    %4.2f\n",
00487          NumSubOps_AnswerCheckInsert, NumSubOps_AnswerInsert,
00488          ( (NumSubOps_AnswerCheckInsert != 0)
00489            ? (float)NumSubOps_AnswerInsert / (float)NumSubOps_AnswerCheckInsert
00490            : 0 ));
00491   printf("  Relevant-answer identify ops:      %8u\n"
00492          "  Answer-list consumption ops:       %8u\n",
00493          NumSubOps_IdentifyRelevantAnswers, NumSubOps_AnswerConsumption);
00494 }
00495 
00496 /*==========================================================================*/

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