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