1 /*-----------------------------------------------------------------------
2 
3 File  : ccl_pdtrees.c
4 
5 Author: Stephan Schulz
6 
7 Contents
8 
9   Perfect discrimination trees for optimized rewriting.
10 
11   Copyright 1998, 1999 by the author.
12   This code is released under the GNU General Public Licence and
13   the GNU Lesser General Public License.
14   See the file COPYING in the main E directory for details..
15   Run "eprover -h" for contact information.
16 
17 Changes
18 
19 <1> Wed Jun 24 00:55:29 MET DST 1998
20     New
21 <2> Sun Mar  4 21:39:27 CET 2001
22     Completely rewritten
23 
24 -----------------------------------------------------------------------*/
25 
26 #include "ccl_pdtrees.h"
27 
28 
29 /*---------------------------------------------------------------------*/
30 /*                        Global Variables                             */
31 /*---------------------------------------------------------------------*/
32 
33 bool PDTreeUseAgeConstraints  = true;
34 bool PDTreeUseSizeConstraints = true;
35 
36 #ifdef PDT_COUNT_NODES
37 unsigned long PDTNodeCounter = 0;
38 #endif
39 
40 /*---------------------------------------------------------------------*/
41 /*                      Forward Declarations                           */
42 /*---------------------------------------------------------------------*/
43 
44 static long pdt_compute_size_constraint(PDTNode_p node);
45 
46 /*---------------------------------------------------------------------*/
47 /*                         Internal Functions                          */
48 /*---------------------------------------------------------------------*/
49 
50 
51 /*-----------------------------------------------------------------------
52 //
53 // Function: pdtree_default_cell_free()
54 //
55 //   Free a node cell (but not potential children et al.)
56 //
57 // Global Variables: -
58 //
59 // Side Effects    : Memory operations
60 //
61 /----------------------------------------------------------------------*/
62 
pdtree_default_cell_free(PDTNode_p junk)63 static void pdtree_default_cell_free(PDTNode_p junk)
64 {
65    assert(junk);
66    assert(junk->f_alternatives);
67    assert(junk->v_alternatives);
68    assert(!junk->entries);
69 
70    IntMapFree(junk->f_alternatives);
71    PDArrayFree(junk->v_alternatives);
72    PDTNodeCellFree(junk);
73 }
74 
75 
76 /*-----------------------------------------------------------------------
77 //
78 // Function: pdt_select_alt_ref()
79 //
80 //   Return a pointer to the position where the alternative to term is
81 //   stored.
82 //
83 // Global Variables: -
84 //
85 // Side Effects    : -
86 //
87 /----------------------------------------------------------------------*/
88 
pdt_select_alt_ref(PDTree_p tree,PDTNode_p node,Term_p term)89 static void* pdt_select_alt_ref(PDTree_p tree, PDTNode_p node, Term_p term)
90 {
91    void* res;
92 
93    if(TermIsVar(term))
94    {
95       tree->arr_storage_est -= PDArrayStorage(node->v_alternatives);
96       res = &(PDArrayElementP(node->v_alternatives,
97                 -term->f_code));
98       tree->arr_storage_est += PDArrayStorage(node->v_alternatives);
99    }
100    else
101    {
102       tree->arr_storage_est -= IntMapStorage(node->f_alternatives);
103       res = IntMapGetRef(node->f_alternatives, term->f_code);
104       tree->arr_storage_est += IntMapStorage(node->f_alternatives);
105    }
106    return res;
107 }
108 
109 
110 
111 
112 /*-----------------------------------------------------------------------
113 //
114 // Function: pdt_node_succ_stack_create()
115 //
116 //   Create a stack of all children of node and return it (for
117 //   convenient traversal).
118 //
119 // Global Variables: -
120 //
121 // Side Effects    : May reset node->max_var (which has to be at least
122 //                   as big as the largest variable number).
123 //
124 /----------------------------------------------------------------------*/
125 
pdt_node_succ_stack_create(PDTNode_p node)126 static PStack_p pdt_node_succ_stack_create(PDTNode_p node)
127 {
128    PStack_p result = PStackAlloc();
129    FunCode i = 0; /* Stiffle warning */
130    long tmpmaxvar = 0;
131    PDTNode_p next;
132    IntMapIter_p iter;
133 
134    iter = IntMapIterAlloc(node->f_alternatives, 0, LONG_MAX);
135    while((next=IntMapIterNext(iter, &i)))
136    {
137       assert(next);
138       PStackPushP(result, next);
139    }
140    IntMapIterFree(iter);
141    for(i=1; i<=node->max_var; i++)
142    {
143       next = PDArrayElementP(node->v_alternatives, i);
144       if(next)
145       {
146          PStackPushP(result, next);
147          tmpmaxvar = i;
148       }
149    }
150    node->max_var = tmpmaxvar;
151    return result;
152 }
153 
154 
155 
156 /*-----------------------------------------------------------------------
157 //
158 // Function: pos_tree_compute_size_constraint()
159 //
160 //   Find the size of the smallest term at a position in tree.
161 //
162 // Global Variables: -
163 //
164 // Side Effects    : -
165 //
166 /----------------------------------------------------------------------*/
167 
pos_tree_compute_size_constraint(PTree_p tree)168 static long pos_tree_compute_size_constraint(PTree_p tree)
169 {
170    ClausePos_p entry;
171    PTree_p  trav;
172    PStack_p trav_stack;
173    long res = LONG_MAX;
174 
175    trav_stack = PTreeTraverseInit(tree);
176    while((trav = PTreeTraverseNext(trav_stack)))
177    {
178       entry = trav->key;
179       res = MIN(res, TermStandardWeight(ClausePosGetSide(entry)));
180    }
181    PTreeTraverseExit(trav_stack);
182    /* This is a leaf node, size is fixed! */
183 
184    return res;
185 }
186 
187 /*-----------------------------------------------------------------------
188 //
189 // Function: pdt_compute_size_constraint()
190 //
191 //   Compute and set the size constraint of the current node in the PDT
192 //   tree.
193 //
194 // Global Variables: -
195 //
196 // Side Effects    : Sets the updated size constraint, possibly in all
197 //                   children.
198 //
199 /----------------------------------------------------------------------*/
200 
pdt_compute_size_constraint(PDTNode_p node)201 static long pdt_compute_size_constraint(PDTNode_p node)
202 {
203    if(node->entries)
204    {
205       node->size_constr = pos_tree_compute_size_constraint(node->entries);
206    }
207    else
208    {
209       PStack_p iter_stack = pdt_node_succ_stack_create(node);
210       PStackPointer i;
211       long
212          newsize = LONG_MAX,
213          tmpsize;
214          PDTNode_p next_node;
215 
216       for(i = 0; i< PStackGetSP(iter_stack); i++)
217       {
218          next_node = PStackElementP(iter_stack, i);
219          assert(next_node);
220          tmpsize = PDTNodeGetSizeConstraint(next_node);
221          newsize = MIN(newsize, tmpsize);
222       }
223       PStackFree(iter_stack);
224       node->size_constr = newsize;
225    }
226    return node->size_constr;
227 }
228 
229 /*-----------------------------------------------------------------------
230 //
231 // Function: pdt_verify_size_constraint()
232 //
233 //   Verify the size constraint at node, and return the optimal
234 //   value (or -1 if the tree is inconsistent)
235 //
236 // Global Variables: -
237 //
238 // Side Effects    : Sets the updated size constraint, possibly in all
239 //                   children.
240 //
241 /----------------------------------------------------------------------*/
242 
pdt_verify_size_constraint(PDTNode_p node)243 long pdt_verify_size_constraint(PDTNode_p node)
244 {
245    long actual_constr = LONG_MAX;
246 
247    if(node->entries)
248    {
249       actual_constr = pos_tree_compute_size_constraint(node->entries);
250    }
251    else
252    {
253       PStackPointer i;
254       PStack_p  iter_stack = pdt_node_succ_stack_create(node);
255       long      tmpsize;
256       PDTNode_p next_node;
257 
258       for(i = 0; i< PStackGetSP(iter_stack); i++)
259       {
260          next_node = PStackElementP(iter_stack, i);
261          assert(next_node);
262          tmpsize = pdt_verify_size_constraint(next_node);
263          actual_constr = MIN(actual_constr, tmpsize);
264       }
265       PStackFree(iter_stack);
266    }
267    if(node->size_constr == -1 || (node->size_constr == actual_constr))
268    {
269       return actual_constr;
270    }
271    return -1;
272 }
273 
274 
275 /*-----------------------------------------------------------------------
276 //
277 // Function: pos_tree_compute_age_constraint()
278 //
279 //   Find the creation date of the youngst clauss  at a position in
280 //   tree.
281 //
282 // Global Variables: -
283 //
284 // Side Effects    : -
285 //
286 /----------------------------------------------------------------------*/
287 
pos_tree_compute_age_constraint(PTree_p tree)288 static SysDate pos_tree_compute_age_constraint(PTree_p tree)
289 {
290    ClausePos_p entry;
291    PTree_p  trav;
292    PStack_p trav_stack;
293    SysDate res = SysDateCreationTime();
294 
295    trav_stack = PTreeTraverseInit(tree);
296    while((trav = PTreeTraverseNext(trav_stack)))
297    {
298       entry = trav->key;
299       res = SysDateMaximum(res, entry->clause->date);
300    }
301    PTreeTraverseExit(trav_stack);
302    /* This is a leaf node, size is fixed! */
303 
304    return res;
305 }
306 
307 
308 /*-----------------------------------------------------------------------
309 //
310 // Function: pdt_compute_age_constraint()
311 //
312 //   Compute and set the age constraint (i.e. date stamp of the youngest clause
313 //   in the subtree) of the current node in the PDT tree.
314 //
315 // Global Variables: -
316 //
317 // Side Effects    : Sets the updated size constraint, possibly in all
318 //                   children.
319 //
320 /----------------------------------------------------------------------*/
321 
pdt_compute_age_constraint(PDTNode_p node)322 static SysDate pdt_compute_age_constraint(PDTNode_p node)
323 {
324    if(node->entries)
325    {
326       node->age_constr = pos_tree_compute_age_constraint(node->entries);
327    }
328    else
329    {
330       PStack_p iter_stack = pdt_node_succ_stack_create(node);
331       PStackPointer i;
332       SysDate
333          newdate = SysDateCreationTime(),
334          tmpdate;
335       PDTNode_p next_node;
336 
337       for(i = 0; i< PStackGetSP(iter_stack); i++)
338       {
339          next_node = PStackElementP(iter_stack, i);
340          assert(next_node);
341          tmpdate = PDTNodeGetAgeConstraint(next_node);
342          newdate = SysDateMaximum(newdate, tmpdate);
343       }
344       PStackFree(iter_stack);
345       node->age_constr = newdate;
346    }
347    return node->age_constr;
348 }
349 
350 
351 
352 /*-----------------------------------------------------------------------
353 //
354 // Function: pdt_verify_age_constraint()
355 //
356 //   Verify the age constraint at node, and return the optimal
357 //   value (or -1 if the tree is inconsistent)
358 //
359 // Global Variables: -
360 //
361 // Side Effects    : Sets the updated size constraint, possibly in all
362 //                   children.
363 //
364 /----------------------------------------------------------------------*/
365 
pdt_verify_age_constraint(PDTNode_p node)366 SysDate pdt_verify_age_constraint(PDTNode_p node)
367 {
368    SysDate actual_constr = SysDateCreationTime();
369 
370    if(node->entries)
371    {
372       actual_constr = pos_tree_compute_age_constraint(node->entries);
373    }
374    else
375    {
376       PStackPointer i;
377       PStack_p      iter_stack = pdt_node_succ_stack_create(node);
378       PDTNode_p     next_node;
379       SysDate       tmpdate;
380 
381       for(i = 0; i< PStackGetSP(iter_stack); i++)
382       {
383          next_node = PStackElementP(iter_stack, i);
384          assert(next_node);
385          tmpdate = pdt_verify_age_constraint(next_node);
386          actual_constr = SysDateMaximum(actual_constr, tmpdate);
387       }
388       PStackFree(iter_stack);
389    }
390    if(SysDateIsInvalid(node->age_constr) || (node->age_constr == actual_constr))
391    {
392       return actual_constr;
393    }
394    return -1;
395 }
396 
397 
398 /*-----------------------------------------------------------------------
399 //
400 // Function: delete_clause_entries()
401 //
402 //   Consider *root as a PTree of ClausePos_p and delete all entries
403 //   from it that describe a position in clause. Return number of
404 //   clauses.
405 //
406 // Global Variables: -
407 //
408 // Side Effects    : Changes tree
409 //
410 /----------------------------------------------------------------------*/
411 
delete_clause_entries(PTree_p * root,Clause_p clause)412 static long  delete_clause_entries(PTree_p *root, Clause_p clause)
413 {
414    long        res = 0;
415    PStack_p    trav_stack;
416    PStack_p    store = PStackAlloc();
417    PTree_p     handle;
418    ClausePos_p pos;
419 
420    trav_stack = PTreeTraverseInit(*root);
421    while((handle = PTreeTraverseNext(trav_stack)))
422    {
423       pos = handle->key;
424       if(pos->clause == clause)
425       {
426     PStackPushP(store, pos);
427       }
428    }
429    PTreeTraverseExit(trav_stack);
430 
431    while(!PStackEmpty(store))
432    {
433       pos = PStackPopP(store);
434       PTreeDeleteEntry(root, pos);
435       ClausePosCellFree(pos);
436       res++;
437    }
438    PStackFree(store);
439    return res;
440 }
441 
442 
443 /*-----------------------------------------------------------------------
444 //
445 // Function: pdtree_verify_node_constr()
446 //
447 //   Check if the current tree state is consistent with the query
448 //   constraints stored in the tree.
449 //
450 // Global Variables: -
451 //
452 // Side Effects    : -
453 //
454 /----------------------------------------------------------------------*/
455 
pdtree_verify_node_constr(PDTree_p tree)456 static bool pdtree_verify_node_constr(PDTree_p tree)
457 {
458    PDT_COUNT_INC(PDTNodeCounter);
459 
460    /* Is largest term at or beyond node greater than the query term? */
461 
462    if(PDTreeUseSizeConstraints &&
463       (tree->term_weight < PDTNodeGetSizeConstraint(tree->tree_pos)))
464    {
465       return false;
466    }
467 
468    /* Is the youngest clause stored at or beyond node younger than the
469       query terms normal form date ? */
470 
471    if(PDTreeUseAgeConstraints &&
472       !SysDateIsEarlier(tree->term_date,PDTNodeGetAgeConstraint(tree->tree_pos)))
473    {
474       return false;
475    }
476    return true;
477 }
478 
479 
480 /*-----------------------------------------------------------------------
481 //
482 // Function: pdtree_forward()
483 //
484 //   Find the next open possibility and advance to it. If none exists,
485 //   indicate this by setting tree->tree_pos->trav_count to
486 //   PDT_NODE_CLOSED.
487 //
488 // Global Variables: -
489 //
490 // Side Effects    : Changes tree state!
491 //
492 /----------------------------------------------------------------------*/
493 
pdtree_forward(PDTree_p tree,Subst_p subst)494 static void pdtree_forward(PDTree_p tree, Subst_p subst)
495 {
496    PDTNode_p handle = tree->tree_pos, next = NULL;
497    FunCode   i = tree->tree_pos->trav_count, limit;
498    Term_p    term = PStackTopP(tree->term_stack);
499 
500    limit = PDT_NODE_CLOSED(tree,handle);
501    while(i<limit)
502    {
503       if(((i==0)||(i>handle->max_var))&&!TermIsVar(term))
504       {
505     next = IntMapGetVal(handle->f_alternatives,term->f_code);
506     i++;
507     if(next)
508     {
509        PStackPushP(tree->term_proc, term);
510        TermLRTraverseNext(tree->term_stack);
511        next->trav_count = PDT_NODE_INIT_VAL(tree);
512        next->bound      = false;
513        assert(!next->variable);
514        tree->tree_pos = next;
515 #ifdef MEASURE_EXPENSIVE
516        tree->visited_count++;
517 #endif
518        break;
519     }
520       }
521       else
522       {
523     next = PDArrayElementP(handle->v_alternatives,i);
524     i++;
525     if(next)
526     {
527        assert(next->variable);
528        if((!next->variable->binding)&&(!TermCellQueryProp(term,TPPredPos))
529                && next->variable->sort == term->sort)
530        {
531           PStackDiscardTop(tree->term_stack);
532           SubstAddBinding(subst, next->variable, term);
533           next->trav_count   = PDT_NODE_INIT_VAL(tree);
534           next->bound        = true;
535           tree->tree_pos     = next;
536           tree->term_weight  -= (TermStandardWeight(term) -
537                                       TermStandardWeight(next->variable));
538 #ifdef MEASURE_EXPENSIVE
539           tree->visited_count++;
540 #endif
541           break;
542        }
543        else if(next->variable->binding == term)
544        {
545           PStackDiscardTop(tree->term_stack);
546           next->trav_count   = PDT_NODE_INIT_VAL(tree);
547           next->bound        = false;
548           tree->tree_pos     = next;
549           tree->term_weight  -= (TermStandardWeight(term) -
550                                       TermStandardWeight(next->variable));
551 #ifdef MEASURE_EXPENSIVE
552           tree->visited_count++;
553 #endif
554           break;
555        }
556     }
557       }
558    }
559    handle->trav_count = i;
560 }
561 
562 
563 /*-----------------------------------------------------------------------
564 //
565 // Function: pdtree_backtrack()
566 //
567 //   Backtrack to the predecessor node of the current state.
568 //
569 // Global Variables: -
570 //
571 // Side Effects    : Changes tree state
572 //
573 /----------------------------------------------------------------------*/
574 
pdtree_backtrack(PDTree_p tree,Subst_p subst)575 static void pdtree_backtrack(PDTree_p tree, Subst_p subst)
576 {
577    PDTNode_p handle = tree->tree_pos;
578    bool      succ;
579 
580    if(handle->variable)
581    {
582       tree->term_weight  += (TermStandardWeight(handle->variable->binding) -
583                              TermStandardWeight(handle->variable));
584       PStackPushP(tree->term_stack, handle->variable->binding);
585       if(handle->bound)
586       {
587          succ = SubstBacktrackSingle(subst);
588          UNUSED(succ); assert(succ);
589       }
590    }
591    else if(handle->parent)
592    {
593       Term_p t = PStackPopP(tree->term_proc);
594 
595       UNUSED(t); assert(t);
596       TermLRTraversePrev(tree->term_stack,t);
597 
598    }
599    tree->tree_pos = handle->parent;
600 }
601 
602 
603 /*-----------------------------------------------------------------------
604 //
605 // Function: pdt_node_print()
606 //
607 //   Print a PDT node (and subtrees) for debugging.
608 //
609 // Global Variables:
610 //
611 // Side Effects    :
612 //
613 /----------------------------------------------------------------------*/
614 
pdt_node_print(FILE * out,PDTNode_p node,int level)615 void pdt_node_print(FILE* out, PDTNode_p node, int level)
616 {
617    if(node->entries)
618    {
619       PStack_p trav_stack;
620       PTree_p trav;
621       ClausePos_p entry;
622 
623       fprintf(out, "%sleaf size=%ld age=%lu\n", IndentStr(2*level),
624              node->size_constr, node->age_constr);
625       trav_stack = PTreeTraverseInit(node->entries);
626 
627       while((trav = PTreeTraverseNext(trav_stack)))
628       {
629     fprintf(out, "%s: ",IndentStr(2*level));
630          entry = trav->key;
631          ClausePrint(out, entry->clause, true);
632     fprintf(out, "\n");
633       }
634       PTreeTraverseExit(trav_stack);
635    }
636    else
637    {
638       FunCode i = 0; /* Stiffle warning */
639       PDTNode_p next;
640       IntMapIter_p iter;
641 
642       fprintf(out, "%sinternal size=%ld age=%lu f_alts=%p, type=%d\n",
643               IndentStr(2*level),
644               node->size_constr,
645               node->age_constr,
646               node->f_alternatives,
647               node->f_alternatives?node->f_alternatives->type:-1);
648 
649       iter = IntMapIterAlloc(node->f_alternatives, 0, LONG_MAX);
650       while((next=IntMapIterNext(iter, &i)))
651       {
652     fprintf(out, "%sBranch %ld\n", IndentStr(2*level), i);
653          pdt_node_print(out, next, level+1);
654       }
655       IntMapIterFree(iter);
656       for(i=1; i<=node->max_var; i++)
657       {
658     next = PDArrayElementP(node->v_alternatives, i);
659     if(next)
660     {
661             fprintf(out, "%sBranch %ld\n", IndentStr(2*level), -i);
662             pdt_node_print(out, next, level+1);
663     }
664       }
665    }
666 }
667 
668 /*---------------------------------------------------------------------*/
669 /*                         Exported Functions                          */
670 /*---------------------------------------------------------------------*/
671 
672 /*-----------------------------------------------------------------------
673 //
674 // Function: PDTreeAlloc()
675 //
676 //   Allocate an empty, in initialized PDTreeCell (including the
677 //   initial PDTNodeCell().
678 //
679 // Global Variables: -
680 //
681 // Side Effects    : Memory operations
682 //
683 /----------------------------------------------------------------------*/
684 
PDTreeAlloc(void)685 PDTree_p PDTreeAlloc(void)
686 {
687    PDTree_p handle;
688 
689    handle = PDTreeCellAlloc();
690 
691    handle->tree            = PDTNodeAlloc();
692    handle->term_stack      = PStackAlloc();
693    handle->term_proc       = PStackAlloc();
694    handle->tree_pos        = NULL;
695    handle->store_stack     = NULL;
696    handle->term            = NULL;
697    handle->term_date       = SysDateCreationTime();
698    handle->term_weight     = LONG_MAX;
699    handle->prefer_general  = 0; /* Not really necessary, it's
700                   reinitialized in
701                                       PDTreeSearchInit() anyways.*/
702    handle->clause_count    = 0;
703    handle->node_count      = 0;
704    handle->arr_storage_est = 0;
705    handle->match_count     = 0;
706    handle->visited_count   = 0;
707 
708    return handle;
709 }
710 
711 
712 /*-----------------------------------------------------------------------
713 //
714 // Function: PDTreeFree()
715 //
716 //   Completely free a PDTree.
717 //
718 // Global Variables: -
719 //
720 // Side Effects    : Memory operations
721 //
722 /----------------------------------------------------------------------*/
723 
PDTreeFree(PDTree_p tree)724 void PDTreeFree(PDTree_p tree)
725 {
726 
727    assert(tree);
728    PDTNodeFree(tree->tree);
729    PStackFree(tree->term_stack);
730    PStackFree(tree->term_proc);
731    assert(!tree->store_stack);
732    PDTreeCellFree(tree);
733 }
734 
735 
736 /*-----------------------------------------------------------------------
737 //
738 // Function: PDTNodeAlloc()
739 //
740 //   Return an initialized node in a PDTree.
741 //
742 // Global Variables: -
743 //
744 // Side Effects    : Memory operations
745 //
746 /----------------------------------------------------------------------*/
747 
PDTNodeAlloc(void)748 PDTNode_p PDTNodeAlloc(void)
749 {
750    PDTNode_p handle;
751 
752 
753    handle = PDTNodeCellAlloc();
754 
755    handle->f_alternatives = IntMapAlloc();
756    handle->v_alternatives = PDArrayAlloc(PDNODE_VAR_INIT_ALT,
757                 PDNODE_VAR_GROW_ALT);
758    handle->max_var        = 0;
759    handle->size_constr    = LONG_MAX;
760    handle->age_constr     = SysDateCreationTime();
761    handle->parent         = NULL;
762    handle->ref_count      = 0;
763    handle->entries        = NULL;
764    handle->trav_count     = 0;
765    handle->variable       = NULL;
766    handle->bound          = false;
767 
768    return handle;
769 }
770 
771 
772 /*-----------------------------------------------------------------------
773 //
774 // Function: PDTNodeFree()
775 //
776 //   Free a PDTreeNode (including all referenced term positions.
777 //
778 // Global Variables: -
779 //
780 // Side Effects    : Memory operations
781 //
782 /----------------------------------------------------------------------*/
783 
PDTNodeFree(PDTNode_p tree)784 void PDTNodeFree(PDTNode_p tree)
785 {
786    FunCode      i;
787    IntMapIter_p iter;
788    ClausePos_p  tmp;
789    PDTNode_p     subtree;
790 
791 
792    iter = IntMapIterAlloc(tree->f_alternatives, 0, LONG_MAX);
793    while((subtree = IntMapIterNext(iter, &i)))
794    {
795       assert(subtree);
796    }
797    IntMapIterFree(iter);
798    for(i=1; i<=tree->max_var; i++)
799    {
800       subtree = PDArrayElementP(tree->v_alternatives, i);
801       if(subtree)
802       {
803          PDTNodeFree(subtree);
804       }
805    }
806    while(tree->entries)
807    {
808       tmp = PTreeExtractRootKey(&tree->entries);
809       ClausePosCellFree(tmp);
810    }
811    pdtree_default_cell_free(tree);
812 
813 }
814 
815 
816 /*-----------------------------------------------------------------------
817 //
818 // Function: TermLRTraverseInit()
819 //
820 //   Initialize a stack for term traversal.
821 //
822 // Global Variables: -
823 //
824 // Side Effects    : -
825 //
826 /----------------------------------------------------------------------*/
827 
TermLRTraverseInit(PStack_p stack,Term_p term)828 void TermLRTraverseInit(PStack_p stack, Term_p term)
829 {
830    PStackReset(stack);
831    PStackPushP(stack,term);
832 }
833 
834 
835 /*-----------------------------------------------------------------------
836 //
837 // Function: TermLRTraverseNext()
838 //
839 //   Return the next term node in LR-ordering and update the
840 //   stack. Return NULL if term traveral is complete.
841 //
842 // Global Variables: -
843 //
844 // Side Effects    : Stack changes
845 //
846 /----------------------------------------------------------------------*/
847 
TermLRTraverseNext(PStack_p stack)848 Term_p TermLRTraverseNext(PStack_p stack)
849 {
850    int    i;
851    Term_p handle;
852 
853    if(PStackEmpty(stack))
854    {
855       return NULL;
856    }
857    handle = PStackPopP(stack);
858    for(i=handle->arity-1; i>=0; i--)
859    {
860       PStackPushP(stack, handle->args[i]);
861    }
862 
863    return handle;
864 }
865 
866 
867 /*-----------------------------------------------------------------------
868 //
869 // Function: TermLRTraversePrev()
870 //
871 //   Undo a TermLRTraverseNext() operation by replacing terms args on
872 //   the stack with term.
873 //
874 // Global Variables: -
875 //
876 // Side Effects    : Stack changes
877 //
878 /----------------------------------------------------------------------*/
879 
TermLRTraversePrev(PStack_p stack,Term_p term)880 Term_p TermLRTraversePrev(PStack_p stack, Term_p term)
881 {
882    Term_p tmp;
883    int    i;
884 
885    for(i=0; i<term->arity; i++)
886    {
887       tmp = PStackPopP(stack);
888       UNUSED(tmp); assert(tmp == term->args[i]);
889    }
890    PStackPushP(stack, term);
891 
892    return term;
893 }
894 
895 
896 
897 /*-----------------------------------------------------------------------
898 //
899 // Function: PDTreeInsert()
900 //
901 //   Insert a new demodulator into the tree.
902 //
903 // Global Variables: -
904 //
905 // Side Effects    : Changes index
906 //
907 /----------------------------------------------------------------------*/
908 
PDTreeInsert(PDTree_p tree,ClausePos_p demod_side)909 void PDTreeInsert(PDTree_p tree, ClausePos_p demod_side)
910 {
911    Term_p    term, curr;
912    PDTNode_p node, *next;
913    bool      res;
914    long      tmp;
915 
916    assert(tree);
917    assert(tree->tree);
918    assert(demod_side);
919 
920    term = ClausePosGetSide(demod_side);
921    TermLRTraverseInit(tree->term_stack, term);
922    node              = tree->tree;
923    tmp = TermStandardWeight(term);
924    if(!SysDateIsInvalid(node->age_constr))
925    {
926       node->age_constr  = SysDateMaximum(demod_side->clause->date,
927                                          node->age_constr);
928    }
929    /* We need no guard here, since invalid = -1 will win out in either
930       case. */
931    node->size_constr = MIN(tmp, node->size_constr);
932    node->ref_count++;
933 
934    curr = TermLRTraverseNext(tree->term_stack);
935 
936    while(curr)
937    {
938       next = pdt_select_alt_ref(tree, node, curr);
939 
940       if(!(*next))
941       {
942     *next = PDTNodeAlloc();
943          tree->arr_storage_est+= (IntMapStorage((*next)->f_alternatives)+
944                                   PDArrayStorage((*next)->v_alternatives));
945     (*next)->parent = node;
946     tree->node_count++;
947     if(TermIsVar(curr))
948     {
949        (*next)->variable = curr;
950        node->max_var = MAX(node->max_var, -curr->f_code);
951     }
952       }
953       node = *next;
954       tmp = TermStandardWeight(term);
955       node->size_constr = MIN(tmp, node->size_constr);
956       if(!SysDateIsInvalid(node->age_constr))
957       {
958          node->age_constr  = SysDateMaximum(demod_side->clause->date,
959                                             node->age_constr);
960       }
961       node->ref_count++;
962       curr = TermLRTraverseNext(tree->term_stack);
963    }
964    assert(node);
965    res = PTreeStore(&(node->entries), demod_side);
966    tree->clause_count++;
967    UNUSED(res); assert(res);
968    //printf("ISizeConstr %p: %ld\n", tree, pdt_verify_size_constraint(tree->tree));
969    //printf("IDateConstr %p: %ld\n", tree, pdt_verify_age_constraint(tree->tree));
970 }
971 
972 
973 /*-----------------------------------------------------------------------
974 //
975 // Function: PDTreeDelete()
976 //
977 //   Delete all index entries of clause indexed by term from
978 //   tree. Return number of entries deleted.
979 //
980 // Global Variables: -
981 //
982 // Side Effects    : Changes index
983 //
984 /----------------------------------------------------------------------*/
985 
PDTreeDelete(PDTree_p tree,Term_p term,Clause_p clause)986 long PDTreeDelete(PDTree_p tree, Term_p term, Clause_p clause)
987 {
988    long res;
989    PStack_p  del_stack = PStackAlloc();
990    Term_p    curr;
991    PDTNode_p node, prev, *next, *del;
992 
993    assert(tree);
994    assert(tree->tree);
995    assert(term);
996    assert(clause);
997 
998    /* printf("\nRemoving: ");
999    ClausePrint(stdout, clause, true);
1000    if(clause->literals)
1001    {
1002       printf("-- term: ");
1003       TBPrintTerm(stdout, clause->literals->bank, term, true);
1004    }
1005    printf("\n"); */
1006 
1007    TermLRTraverseInit(tree->term_stack, term);
1008    node = tree->tree;
1009    curr = TermLRTraverseNext(tree->term_stack);
1010 
1011    while(curr)
1012    {
1013       next = pdt_select_alt_ref(tree, node, curr);
1014       assert(next);
1015       PStackPushP(del_stack, next);
1016 
1017       node = *next;
1018       curr = TermLRTraverseNext(tree->term_stack);
1019    }
1020    assert(node);
1021 
1022    res = delete_clause_entries(&(node->entries), clause);
1023 
1024    if(term->weight == node->size_constr)
1025    {
1026       node->size_constr = -1;
1027    }
1028    if(SysDateEqual(node->age_constr, clause->date))
1029    {
1030       node->age_constr = SysDateInvalidTime();
1031    }
1032 
1033    while(node->parent)
1034    {
1035       prev = node->parent;
1036       del  = PStackPopP(del_stack);
1037       node->ref_count -= res;
1038       if(!node->ref_count)
1039       {
1040          tree->arr_storage_est -= (IntMapStorage(node->f_alternatives)+
1041                                    PDArrayStorage(node->v_alternatives));
1042 
1043     pdtree_default_cell_free(node);
1044     tree->node_count--;
1045     *del = NULL;
1046       }
1047       node = prev;
1048 
1049       if(term->weight == node->size_constr)
1050       {
1051          node->size_constr = -1;
1052       }
1053       if(SysDateEqual(node->age_constr, clause->date))
1054       {
1055          node->age_constr = SysDateInvalidTime();
1056       }
1057    }
1058    PStackFree(del_stack);
1059    tree->clause_count-=res;
1060    /* printf("...removed\n"); */
1061 
1062    // printf("DSizeConstr %p: %ld\n", tree, pdt_verify_size_constraint(tree->tree));
1063    // printf("DDateConstr %p: %ld\n", tree, pdt_verify_age_constraint(tree->tree));
1064    return res;
1065 }
1066 
1067 
1068 /*-----------------------------------------------------------------------
1069 //
1070 // Function: PDTreeSearchInit()
1071 //
1072 //   Initialize a PDTree for searching for matching terms.
1073 //
1074 // Global Variables: -
1075 //
1076 // Side Effects    : Changes state of the tree.
1077 //
1078 /----------------------------------------------------------------------*/
1079 
PDTreeSearchInit(PDTree_p tree,Term_p term,SysDate age_constr,bool prefer_general)1080 void PDTreeSearchInit(PDTree_p tree, Term_p term, SysDate age_constr,
1081             bool prefer_general)
1082 {
1083    assert(!tree->term);
1084 
1085    TermLRTraverseInit(tree->term_stack, term);
1086    PStackReset(tree->term_proc);
1087    tree->tree_pos         = tree->tree;
1088    tree->prefer_general   = prefer_general?1:0;
1089    tree->tree->trav_count = PDT_NODE_INIT_VAL(tree);
1090    tree->term             = term;
1091    tree->term_date        = age_constr;
1092    assert(TermStandardWeight(term) == TermWeight(term,DEFAULT_VWEIGHT,DEFAULT_FWEIGHT));
1093    tree->term_weight      = TermStandardWeight(term);
1094    tree->match_count++;
1095 }
1096 
1097 /*-----------------------------------------------------------------------
1098 //
1099 // Function: PDTreeSearchExit()
1100 //
1101 //   Mark a PDTree as not currently used in a search.
1102 //
1103 // Global Variables: -
1104 //
1105 // Side Effects    : -
1106 //
1107 /----------------------------------------------------------------------*/
1108 
PDTreeSearchExit(PDTree_p tree)1109 void PDTreeSearchExit(PDTree_p tree)
1110 {
1111    assert(tree->term);
1112 
1113    if(tree->store_stack)
1114    {
1115       PTreeTraverseExit(tree->store_stack);
1116       tree->store_stack = NULL;
1117    }
1118    tree->term = NULL;
1119 }
1120 
1121 
1122 /*-----------------------------------------------------------------------
1123 //
1124 // Function: PDTreeFindNextIndexedLeaf()
1125 //
1126 //   Given a search state encoded in the tree and a (partial)
1127 //   substitution, find the next leaf node and return it. Extend subst
1128 //   to a suitable substitution.
1129 //
1130 // Global Variables: PDTPreferGeneral
1131 //
1132 // Side Effects    : Changes tree state
1133 //
1134 /----------------------------------------------------------------------*/
1135 
PDTreeFindNextIndexedLeaf(PDTree_p tree,Subst_p subst)1136 PDTNode_p PDTreeFindNextIndexedLeaf(PDTree_p tree, Subst_p subst)
1137 {
1138    while(tree->tree_pos)
1139    {
1140       if(!pdtree_verify_node_constr(tree)||
1141     (tree->tree_pos->trav_count==PDT_NODE_CLOSED(tree,tree->tree_pos)))
1142       {
1143     pdtree_backtrack(tree, subst);
1144       }
1145       else if(tree->tree_pos->entries) /* Leaf node */
1146       {
1147     tree->tree_pos->trav_count = PDT_NODE_CLOSED(tree,tree->tree_pos);
1148     break;
1149       }
1150       else
1151       {
1152     pdtree_forward(tree, subst);
1153       }
1154    }
1155    return tree->tree_pos;
1156 }
1157 
1158 /*-----------------------------------------------------------------------
1159 //
1160 // Function: PDTreeFindNextDemodulator()
1161 //
1162 //   Return the next matching clause position in the tree search
1163 //   represented by tree.
1164 //
1165 // Global Variables:
1166 //
1167 // Side Effects    :
1168 //
1169 /----------------------------------------------------------------------*/
1170 
PDTreeFindNextDemodulator(PDTree_p tree,Subst_p subst)1171 ClausePos_p PDTreeFindNextDemodulator(PDTree_p tree, Subst_p subst)
1172 {
1173    PTree_p res_cell = NULL;
1174 
1175    assert(tree->tree_pos);
1176    while(tree->tree_pos)
1177    {
1178       if(tree->store_stack)
1179       {
1180     res_cell = PTreeTraverseNext(tree->store_stack);
1181     if(res_cell)
1182     {
1183        return res_cell->key;
1184     }
1185     else
1186     {
1187        PTreeTraverseExit(tree->store_stack);
1188        tree->store_stack = NULL;
1189     }
1190       }
1191       PDTreeFindNextIndexedLeaf(tree, subst);
1192       if(tree->tree_pos)
1193       {
1194     tree->store_stack =
1195        PTreeTraverseInit(tree->tree_pos->entries);
1196       }
1197    }
1198    return NULL;
1199 }
1200 
1201 
1202 /*-----------------------------------------------------------------------
1203 //
1204 // Function: PDTreePrint()
1205 //
1206 //   Print a PD tree in human-readable form (for debugging).
1207 //
1208 // Global Variables: -
1209 //
1210 // Side Effects    : -
1211 //
1212 /----------------------------------------------------------------------*/
1213 
PDTreePrint(FILE * out,PDTree_p tree)1214 void PDTreePrint(FILE* out, PDTree_p tree)
1215 {
1216    pdt_node_print(out, tree->tree, 0);
1217 }
1218 
1219 
1220 
1221 /*---------------------------------------------------------------------*/
1222 /*                        End of File                                  */
1223 /*---------------------------------------------------------------------*/
1224 
1225 
1226 
1227 
1228 
1229 
1230 
1231 
1232