Connect++ 0.6.1
A fast, readable connection prover for first-order logic.
Loading...
Searching...
No Matches
StackProver.cpp
1/*
2
3Copyright © 2023-25 Sean Holden. All rights reserved.
4
5*/
6/*
7
8This file is part of Connect++.
9
10Connect++ is free software: you can redistribute it and/or modify it
11under the terms of the GNU General Public License as published by the
12Free Software Foundation, either version 3 of the License, or (at your
13option) any later version.
14
15Connect++ is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18more details.
19
20You should have received a copy of the GNU General Public License along
21with Connect++. If not, see <https://www.gnu.org/licenses/>.
22
23*/
24
25#include "StackProver.hpp"
26
31
32//----------------------------------------------------------------------
34: num_preds(0)
35, var_index()
36, fun_index()
37, term_index()
38, pred_index()
39, sub_stack()
40, results()
41, matrix()
42, clause_cache()
43, path()
44, new_C()
45, lemmata()
46, u()
47, action(InferenceItemType::Start)
48, si(0)
49, current_depth_limit(0)
50, current_depth(1)
51, depth_limit_reached(false)
52, status()
53, tptp_conversion_string()
54, stack()
55, right_branch_stack()
56, backtrack(false)
57, proof_printer(&stack)
58, problem_path()
59, output_interval(params::output_frequency)
60, proof_count(0)
61, use_timeout(false)
62, end_time()
63, show(params::verbosity)
64, cnf_only(false)
65, conjecture_true(false)
66, conjecture_false(false)
67, conjecture_missing(false)
68, negated_conjecture_removed(false)
69, fof_has_axioms(false)
70, simplified_fof_has_axioms(false)
71{}
72//----------------------------------------------------------------------
74 num_preds = n;
76 path.set_num_preds(n);
77}
78//----------------------------------------------------------------------
79void StackProver::read_from_tptp_file(const string& file_name,
80 bool& found_conjecture,
81 size_t& fof_size) {
83 parser.parse_tptp_from_file(file_name);
84 status = parser.get_problem_status();
85 bool equality = parser.equality_used();
86 found_conjecture = parser.conjecture_present();
87 fof_size = parser.number_of_fof_formulas();
88 Predicate* equals_predicate = parser.get_equals_predicate();
97 parser.clear();
99 /*
100 * num_preds for Matrix is set by parser.
101 */
102 path.set_num_preds(num_preds);
103
104 if (params::show_clauses) {
105 std::exit(EXIT_SUCCESS);
106 }
107
108 if (status != string("") && params::first_parse) {
109 show(1, string("Problem status found: "));
110 show(1, status, true);
111 }
112 if (equality && params::add_equality_axioms) {
113 if (params::first_parse) {
114 show(1, string("Problem involves equality: adding axioms for =."), true);
115 params::first_parse = false;
116 }
117 add_equality_axioms(equals_predicate);
118 if (params::equality_axioms_at_start) {
120 }
121 }
122 /*
123 * Any further variables will be anonymous.
124 */
126 }
127//----------------------------------------------------------------------
129 /*
130 * Equality axioms as described in Handbook of Automated
131 * Reasoning, Volume 1, page 615.
132 */
133 Arity max_fun_arity = fun_index.find_maximum_arity();
134 Arity max_pred_arity = pred_index.find_maximum_arity();
135 /*
136 * You need at least three variables to describe these, and
137 * twice as many as the arity of the biggest predicate or
138 * function.
139 */
140 uint32_t max_arity = max_fun_arity;
141 if (max_pred_arity > max_arity)
142 max_arity = max_pred_arity;
143 if (max_arity < 3)
144 max_arity = 3;
145 vector<Term*> xs;
146 vector<Term*> ys;
147 string xvar("__eqx_");
148 string yvar("__eqy_");
149 for (size_t i = 0; i < max_arity; i++) {
150 Variable* xvarp = var_index.add_named_var(xvar + std::to_string(i));
151 Variable* yvarp = var_index.add_named_var(yvar + std::to_string(i));
152 xs.push_back(term_index.add_variable_term(xvarp));
153 ys.push_back(term_index.add_variable_term(yvarp));
154 }
155 /*
156 * How you construct these depends on which representation you're using.
157 * It's easy enough to show that the difference is only a case
158 * of swapping negations. See for example "Equality Preprocessing in
159 * Connection Calculi", Oliver and Otten.
160 */
161 bool pol = !params::positive_representation;
162 uint32_t n_added = 0;
163 /*
164 * Axiom for reflexivity.
165 */
166 vector<Term*> ref;
167 ref.push_back(xs[0]);
168 ref.push_back(xs[0]);
169 Literal reflexive(equals_predicate, ref, 2, pol);
170 Clause ref_c;
171 ref_c.add_lit(reflexive);
172 matrix.add_clause(ref_c, "equality");
173 n_added++;
174 /*
175 * Axiom for symmetry.
176 */
177 vector<Term*> xy;
178 xy.push_back(xs[0]);
179 xy.push_back(xs[1]);
180 vector<Term*> yx;
181 yx.push_back(xs[1]);
182 yx.push_back(xs[0]);
183 Literal sym1(equals_predicate, xy, 2, !pol);
184 Literal sym2(equals_predicate, yx, 2, pol);
185 Clause sym_c;
186 sym_c.add_lit(sym1);
187 sym_c.add_lit(sym2);
188 matrix.add_clause(sym_c, "equality");
189 n_added++;
190 /*
191 * Axiom for transitivity.
192 */
193 vector<Term*> yz;
194 yz.push_back(xs[1]);
195 yz.push_back(xs[2]);
196 vector<Term*> xz;
197 xz.push_back(xs[0]);
198 xz.push_back(xs[2]);
199 Literal tr1(equals_predicate, xy, 2, !pol);
200 Literal tr2(equals_predicate, yz, 2, !pol);
201 Literal tr3(equals_predicate, xz, 2, pol);
202 Clause tr_c;
203 tr_c.add_lit(tr1);
204 tr_c.add_lit(tr2);
205 tr_c.add_lit(tr3);
206 matrix.add_clause(tr_c, "equality");
207 n_added++;
208 /*
209 * Function substitution.
210 */
211 for (size_t j = 0; j < fun_index.get_size(); j++) {
212 Function* p = fun_index[j];
213 Arity ar = p->get_arity();
214 if (ar > 0) {
215 Clause c;
216 vector<Term*> x1xn;
217 vector<Term*> y1yn;
218 for (size_t i = 0; i < ar; i++) {
219 x1xn.push_back(xs[i]);
220 y1yn.push_back(ys[i]);
221 vector<Term*> xiyi;
222 xiyi.push_back(xs[i]);
223 xiyi.push_back(ys[i]);
224 Literal eq_lit(equals_predicate, xiyi, 2, !pol);
225 c.add_lit(eq_lit);
226 }
227 vector<Term*> t;
228 t.push_back(term_index.add_function_term(p, x1xn));
229 t.push_back(term_index.add_function_term(p, y1yn));
230 Literal f_lit(equals_predicate, t, 2, pol);
231 c.add_lit(f_lit);
232 matrix.add_clause(c, "equality");
233 n_added++;
234 }
235 }
236 /*
237 * Predicate substitution.
238 */
239 for (size_t j = 0; j < pred_index.get_num_preds(); j++) {
240 Predicate* p = pred_index[j];
241 Arity ar = p->get_arity();
242 if (ar > 0 && p != equals_predicate) {
243 Clause c;
244 vector<Term*> x1xn;
245 vector<Term*> y1yn;
246 for (size_t i = 0; i < ar; i++) {
247 x1xn.push_back(xs[i]);
248 y1yn.push_back(ys[i]);
249 vector<Term*> xiyi;
250 xiyi.push_back(xs[i]);
251 xiyi.push_back(ys[i]);
252 Literal eq_lit(equals_predicate, xiyi, 2, !pol);
253 c.add_lit(eq_lit);
254 }
255 Literal p_lit1(p, x1xn, ar, !pol);
256 Literal p_lit2(p, y1yn, ar, pol);
257 c.add_lit(p_lit1);
258 c.add_lit(p_lit2);
259 matrix.add_clause(c, "equality");
260 n_added++;
261 }
262 }
263 /*
264 * Distinct objects
265 */
266 Arity min_arity = fun_index.find_minimum_arity();
267 if (!params::no_distinct_objects && min_arity == 0) {
268 vector<Term*> all_distinct_constants;
269 vector<Term*> empty_args;
270 for (size_t i = 0; i < fun_index.get_size(); i++) {
271 Function* p = fun_index[i];
272 Arity ar = p->get_arity();
273 // Remember, you don't want to do this for Skolem constants.
274 string name = p->get_name();
275 string prefix = name.string::substr(0,params::unique_skolem_prefix.length());
276 bool is_skolem = (params::unique_skolem_prefix.string::compare(0, string::npos, prefix) == 0) &&
277 (params::unique_skolem_prefix.length() < name.length());
278 bool is_quoted = (name[0] == '\"' && name[name.size() - 1] == '\"');
279 if (ar == 0 &&
280 !is_skolem &&
281 (params::all_distinct_objects || is_quoted)) {
282 Term* t = term_index.add_function_term(p, empty_args);
283 all_distinct_constants.push_back(t);
284 }
285 }
286 size_t s = all_distinct_constants.size();
287 if (s > 1) {
288 for (size_t i = s - 1; i > 0; i--) {
289 for (size_t j = 0; j < i; j++) {
290 Clause c;
291 vector<Term*> args;
292 args.push_back(all_distinct_constants[i]);
293 args.push_back(all_distinct_constants[j]);
294 Literal eq_lit(equals_predicate, args, 2, !pol);
295 c.add_lit(eq_lit);
296 matrix.add_clause(c, "distinct_objects");
297 n_added++;
298 }
299 }
300 }
301 }
302 matrix.set_num_equals(n_added);
303}
304//----------------------------------------------------------------------
306 /*
307 * Don't waste your time if the regularity test applies.
308 */
309 if (params::use_regularity_test && !path.test_for_regularity(new_C))
310 return;
311 /*
312 * Don't try to populate axioms.
313 */
314 if (new_C.size() == 0) {
315 return;
316 }
317 /*
318 * Extensions, reductions and lemmas.
319 */
320 stack[si].initialize(matrix);
321}
322//----------------------------------------------------------------------
324 return stack[si].c.empty();
325}
326//----------------------------------------------------------------------
328 /*
329 * Add a new StackItem using the next action from the list stored
330 * in the StackItem currently in play. If necessary, also
331 * add something to right_branch_stack. Populate the new list of
332 * actions and update si.
333 */
335 /*
336 * Why are the scope rules for switch so odd???
337 */
338 Clause old_C;
339 Lemmata old_Lem;
340 Literal neg_lit;
341 UnificationOutcome outcome;
342 Substitution sig;
343 Literal ext_L;
344 switch (action.T) {
345 //----------------------------------------------------------------------
346 //----------------------------------------------------------------------
347 //----------------------------------------------------------------------
348 // Lemmas.
349 //----------------------------------------------------------------------
350 //----------------------------------------------------------------------
351 //----------------------------------------------------------------------
352 case InferenceItemType::Lemma:
354 /*
355 * If you are restricting backtracking for lemmas then
356 * at this point you can remove all alternatives.
357 */
358 if (params::limit_bt_lemmas)
359 stack[si].restrict_backtrack();
360 /*
361 * Work out the new state.
362 */
363 new_C = stack[si].c;
365 path = stack[si].p;
366 lemmata = stack[si].l;
367 /*
368 * Extend the stack.
369 */
370 stack.emplace_back(StackItemType::Lemmata, new_C, path,
373 break;
374 //----------------------------------------------------------------------
375 //----------------------------------------------------------------------
376 //----------------------------------------------------------------------
377 // Reduction.
378 //----------------------------------------------------------------------
379 //----------------------------------------------------------------------
380 //----------------------------------------------------------------------
381 case InferenceItemType::Reduction:
383 /*
384 * If you are restricting backtracking for reductions then
385 * at this point you can remove all alternatives.
386 */
387 if (params::limit_bt_reductions)
388 stack[si].restrict_backtrack();
389 /*
390 * Reductions have a substitution, so apply it and remember
391 * in case you need to undo it later.
392 */
395 /*
396 * Work out the new state.
397 */
398 new_C = stack[si].c;
400 path = stack[si].p;
401 lemmata = stack[si].l;
403 /*
404 * Extend the stack.
405 */
406 stack.emplace_back(StackItemType::Reduction, new_C, path,
409 break;
410 //----------------------------------------------------------------------
411 //----------------------------------------------------------------------
412 //----------------------------------------------------------------------
413 // Extension.
414 //----------------------------------------------------------------------
415 //----------------------------------------------------------------------
416 //----------------------------------------------------------------------
417 case InferenceItemType::Extension:
419 /*
420 * You're going to generate new variables, so remember where to
421 * backtrack to.
422 */
423 //var_index.add_backtrack_point();
424 /*
425 * This is an Extension, so you're going to add something to
426 * right_branch_stack.
427 */
428 path = stack[si].p;
429 old_C = stack[si].c;
431 old_Lem = stack[si].l;
432 old_Lem.push_back(action.L);
433 /*
434 * DON'T do populate_stack_item here! That can wait until you actually
435 * use the right branch. In fact it *has* to wait because we might
436 * apply substitutions that affect it.
437 */
438 right_branch_stack.emplace_back(StackItemType::RightBranch, old_C,
439 path, old_Lem, current_depth);
440 /*
441 * The right branch needs to know where to restrict backtracking.
442 */
444 /*
445 * Now you can deal with the left branch.
446 */
447
448 //matrix.get_literal_clause_pair(action.index_in_LC_index, action.index_to_LC, ext_L, new_C);
449 //new_C.make_copy_with_new_vars(ext_L, new_C, var_index, term_index);
450
452 ext_L = new_C[action.Lprime];
454 /*
455 * Extensions have a substitution, so apply it and remember
456 * in case you need to undo it later.
457 */
458 neg_lit = action.L;
459 neg_lit.invert();
460 outcome = u(neg_lit, ext_L);
461 sig = u.get_substitution();
462 u.backtrack();
463 sig.apply();
464 sub_stack.push_all(sig);
465 /*
466 * Work out the new state.
467 */
468 path.push(action.L);
469 lemmata = stack[si].l;
470 /*
471 * Extend the stack.
472 */
473 stack.emplace_back(StackItemType::LeftBranch, new_C, path,
474 lemmata, sig, current_depth);
476 break;
477 default:
478 cerr << "PANIC!!! You should only have a lemmata, reduction or an extension here!"
479 << endl;
480 break;
481 }
482 /*
483 * Finally, move si on and work out the next bunch of possible actions.
484 */
485 si++;
487}
488//----------------------------------------------------------------------
490 /*
491 * When you're moving forward in the search and you hit an axiom,
492 * you need to see whether there are right branches still needing
493 * to be dealt with.
494 *
495 * Note that an empty right_branch_stack - meaning that you've
496 * found a proof - is dealt with by go().
497 *
498 * this_action does not get populated for the new StackItem in
499 * this case.
500 */
502 /*
503 * Move the next right branch to the stack.
504 */
507 /*
508 * Reset si.
509 */
510 si++;
511 /*
512 * Set up the new state.
513 */
514 new_C = stack[si].c;
515 path = stack[si].p;
516 lemmata = stack[si].l;
517 current_depth = stack[si].depth;
518 /*
519 * We deliberately delayed doing this, so do it now. (See
520 * documentation for StackProver::extend_with_action.)
521 */
523 /*
524 * At this point you are starting a right branch, so
525 * if you are restricting backtracking you remove all
526 * alternatives from the relevant point in the stack.
527 */
528 if (params::limit_bt_extensions) {
529 stack[stack[si].bt_restriction_index].restrict_backtrack();
530 }
531}
532//----------------------------------------------------------------------
534 backtrack = true;
535 stack.pop_back();
536 si--;
537 current_depth = stack[si].depth;
538}
539//----------------------------------------------------------------------
544//----------------------------------------------------------------------
548//----------------------------------------------------------------------
550 /*
551 * You're backtracking through a left branch, so you
552 * need to remember to get rid of the corresponding
553 * right branch as well.
554 */
556 //var_index.backtrack();
560}
561//----------------------------------------------------------------------
579 /*
580 * If you're not limiting backtracking for extensions, or
581 * you *are*, but you're still exploring left trees, then this
582 * is straightforward: just put the item back on right_branch_stack
583 * so that it gets explored again later.
584 */
585 if (!params::limit_bt_extensions ||
586 ((params::limit_bt_extensions || params::limit_bt_all) &&
587 !params::limit_bt_extensions_left_tree)) {
588 /*
589 * Why is this necessary? After we backtrack we may make different
590 * substitutions, so in revisiting the right branch different
591 * possibilties may apply, so we re-compute them later.
592 */
595 return;
596 }
597 /*
598 * We know we are limiting backtracking for extensions, and we
599 * are not exploring the left tree.
600 *
601 * Care is needed if you're not backtracking within the left
602 * part of the tree. You need to move back down the stack,
603 * deleting everything while also making sure that sub_stack
604 * and var_index are correctly maintained. Also, you don't
605 * want to return anything to right_branch_stack.
606 *
607 * This goes back to where the relevant literal was selected.
608 * Thus if you are not limiting the possibilities to only those
609 * for the first literal, it's open to the backtracking
610 * restriction to leave other possibilites to be tried, and
611 * they get picked up from this point.
612 */
613 if (params::limit_bt_extensions_left_tree) {
614 size_t target_index = stack[si].bt_restriction_index;
615 size_t current_index = stack.size() - 1;
616 while (current_index > target_index) {
617 switch (stack[si].item_type) {
618 case StackItemType::Lemmata:
619 break;
620 case StackItemType::Reduction:
622 break;
623 case StackItemType::LeftBranch:
624 //var_index.backtrack();
627 break;
628 case StackItemType::RightBranch:
629 break;
630 default:
631 cerr << "Something is VERY WRONG!" << endl;
632 break;
633 }
635 current_index--;
636 }
637 }
638}
639//----------------------------------------------------------------------
640ProverResult StackProver::go() {
641 /*
642 * Having set up a single entry on the stack, containing a start
643 * state, search for a proof.
644 *
645 * Either you return by ending at the start state with nothing left
646 * to try, by finding a proof, by depth limiting or by timing out.
647 *
648 * The backtrack variable is important here - when true you are
649 * (surprise surprise) backtracking. So mostly each case in the
650 * following switch is divided according to whether you're going
651 * forward or backtracking.
652 */
653 while(true) {
654 /*
655 * Test for and deal with a timeout.
656 */
657 if (use_timeout && chrono::steady_clock::now() > end_time)
658 return ProverResult::TimeOut;
659 /*
660 * Say what's going on.
661 */
662 if (output_interval.tick() && params::verbosity >= 2) {
663 cout << cursor_symbols::Cursor::to_column(1);
665 cout << "Reductions: " << reductions_tried << " Extensions: " << extensions_tried;
666 cout << " Lemmata: " << lemmata_tried << " Right branches: " << right_branches_started;
667 cout << " Stack size: " << stack.size();
668 cout.flush();
669 }
670 /*
671 * si must point to the back of the stack at this point.
672 *
673 * Remember that extend_with_action will deal with this for you.
674 */
675 switch (stack[si].item_type) {
676 //----------------------------------------------------------------
677 //----------------------------------------------------------------
678 //----------------------------------------------------------------
679 // Deal with the start state. Essentially straightforward. Just
680 // deal with a completed search, otherwise work out the
681 // possibly actions and get on with it.
682 //----------------------------------------------------------------
683 //----------------------------------------------------------------
684 //----------------------------------------------------------------
685 case StackItemType::Start:
686 backtrack = false;
687 action = stack[si].get_next_inference(matrix, u);
688 if (action.T == InferenceItemType::None)
689 return ProverResult::OptionsExhausted;
690 else
692 break;
693 //----------------------------------------------------------------
694 //----------------------------------------------------------------
695 //----------------------------------------------------------------
696 // Lemmas. Again, mostly straightforward.
697 //----------------------------------------------------------------
698 //----------------------------------------------------------------
699 //----------------------------------------------------------------
700 case StackItemType::Lemmata:
701 /*
702 * Operation is essentially similar to the reduction case.
703 *
704 * First deal with moving forward.
705 */
706 if (!backtrack) {
707 if (axiom()) {
708 /*
709 * Either you've found a proof or you try a right branch.
710 */
712 return ProverResult::Valid;
713 else
715 }
716 /*
717 * Backtrack because there's nothing left to try.
718 */
719 else {
720 action = stack[si].get_next_inference(matrix, u);
721 if (action.T == InferenceItemType::None)
723 /*
724 * There must be something left to try, so try it.
725 */
726 else
728 }
729 }
730 /*
731 * We are moving down the stack.
732 */
733 else {
734 /*
735 * If you're backtracking then you need to jump over axioms.
736 */
737 if (axiom())
739 /*
740 * If you're not at an axiom then you can start going forward
741 * again.
742 */
743 else
744 backtrack = false;
745 }
746 break;
747 //----------------------------------------------------------------
748 //----------------------------------------------------------------
749 //----------------------------------------------------------------
750 // Reduction. Almost identical to Lemmas, but note the
751 // slightly different backtracking requirement to take account
752 // of undoing the substitution.
753 //----------------------------------------------------------------
754 //----------------------------------------------------------------
755 //----------------------------------------------------------------
756 case StackItemType::Reduction:
757 /*
758 * We are moving up the stack.
759 */
760 if (!backtrack) {
761 if (axiom()) {
762 /*
763 * Either you've found a proof or you try a right branch.
764 */
766 return ProverResult::Valid;
767 else
769 }
770 /*
771 * Backtrack because there's nothing left to try.
772 */
773 else {
774 action = stack[si].get_next_inference(matrix, u);
775 if (action.T == InferenceItemType::None)
777 /*
778 * There must be something left to try, so try it.
779 */
780 else
782 }
783 }
784 /*
785 * We are moving down the stack.
786 */
787 else {
788 /*
789 * If you're backtracking then you need to jump over axioms.
790 */
791 if (axiom())
793 /*
794 * If you're not at an axiom then you can start going forward
795 * again.
796 */
797 else
798 backtrack = false;
799 }
800 break;
801 //----------------------------------------------------------------
802 //----------------------------------------------------------------
803 //----------------------------------------------------------------
804 // Left branch of Extension. Mostly similar to the Reduction
805 // and Lemma cases, but the backtrack is again different to
806 // take care of the new variables, the substitution, and the
807 // right_branch_stack.
808 //----------------------------------------------------------------
809 //----------------------------------------------------------------
810 //----------------------------------------------------------------
811 case StackItemType::LeftBranch:
812 /*
813 * Operation is essentially similar to the Reduction and
814 * Lemma cases. See those for corresponding comments.
815 */
816 if (!backtrack) {
817 if (axiom())
819 /*
820 * A little more involved here as it's where we deal with depth
821 * limiting.
822 */
823 else if ((stack[si].p.length() >= current_depth_limit)
824 && !matrix.is_ground(stack[si].this_action.C_2)) {
825 depth_limit_reached = true;
827 }
828 else {
829 action = stack[si].get_next_inference(matrix, u);
830 if (action.T == InferenceItemType::None)
832 else
834 }
835 }
836 /*
837 * We are moving down the stack.
838 */
839 else {
840 if (axiom())
842 else
843 backtrack = false;
844 }
845 break;
846 //----------------------------------------------------------------
847 //----------------------------------------------------------------
848 //----------------------------------------------------------------
849 // Right branch of Extension. Mostly similar to the Reduction
850 // and Lemmata cases, but the backtrack is now much more
851 // delicate. See the documentation for right_extension_backtrack.
852 //----------------------------------------------------------------
853 //----------------------------------------------------------------
854 //----------------------------------------------------------------
855 case StackItemType::RightBranch:
856 /*
857 * Operation is essentially similar to the reduction case.
858 */
859 if (!backtrack) {
860 if (axiom()) {
862 return ProverResult::Valid;
863 else
865 }
866 else {
867 action = stack[si].get_next_inference(matrix, u);
868 if (action.T == InferenceItemType::None)
870 else
872 }
873 }
874 /*
875 * We are moving down the stack.
876 */
877 else {
878 if (axiom())
880 else
881 backtrack = false;
882 }
883 break;
884 //----------------------------------------------------------------
885 default:
886 cerr << "Something is VERY WRONG!" << endl;
887 break;
888 }
889 }
890 return ProverResult::Error;
891}
892//----------------------------------------------------------------------
893// Set start clauses according to current options.
894//
895// Note that restrict_start with !all_pos_neg_start and !conjecture_start
896// should never be available as it would make no sense.
897//
898// all_pos_neg_start along with conjecture_start are on a best-effort
899// basis - you may end up with nothing.
900//----------------------------------------------------------------------
902 results.clear();
903 size_t m_size = matrix.get_num_clauses();
904 /*
905 * Make sure noone has messed up and not set any start
906 * clause optionss.
907 */
910 /*
911 * The allstart option overides everything else so this is easy.
912 */
913 if (params::all_start) {
914 for (size_t i = 0; i < m_size; i++) {
915 results.push_back(StartClauseStatus::Start);
916 }
917 return;
918 }
919 bool first_clause_included = false;
920 /*
921 * params::all_pos_neg_start indicates use of positive
922 * or negative start clauses according to the representation.
923 * When you don't also have conjecture_start, either include
924 * all, or just the first possibility found.
925 */
926 if (params::all_pos_neg_start && !params::conjecture_start) {
927 for (size_t i = 0; i < m_size; i++) {
928 if (
929 (
930 (params::positive_representation && matrix.is_positive(i))
931 ||
932 (!params::positive_representation && matrix.is_negative(i))
933 )
934 &&
935 (!(params::restrict_start && first_clause_included))
936 ) {
937 results.push_back(StartClauseStatus::Start);
938 first_clause_included = true;
939 }
940 else {
941 results.push_back(StartClauseStatus::NoStart);
942 }
943 }
944 }
945 /*
946 * Similar case if you have conjecture_start but not all_pos_neg_start.
947 */
948 else if (!params::all_pos_neg_start && params::conjecture_start) {
949 for (size_t i = 0; i < m_size; i++) {
950 if (matrix.is_conjecture(i)
951 &&
952 (!(params::restrict_start && first_clause_included))) {
953 results.push_back(StartClauseStatus::Start);
954 first_clause_included = true;
955 }
956 else {
957 results.push_back(StartClauseStatus::NoStart);
958 }
959 }
960 }
961 /*
962 * The tricky case is when you want to combine pos/neg clauses,
963 * conjecture clauses, and restriction in some other way.
964 *
965 * Assume here that you have all_pos_neg_start and conjecture_start.
966 */
967 else {
968 for (size_t i = 0; i < m_size; i++) {
969 if (matrix.is_conjecture(i)
970 &&
971 (
972 (params::positive_representation && matrix.is_positive(i))
973 ||
974 (!params::positive_representation && matrix.is_negative(i))
975 )
976 &&
977 !(params::restrict_start && first_clause_included)) {
978 results.push_back(StartClauseStatus::Start);
979 first_clause_included = true;
980 }
981 else {
982 results.push_back(StartClauseStatus::NoStart);
983 }
984 }
985 }
986 /*
987 * There's a rare possibility that---because either there was no
988 * (negated) conjecture clause in the problem, or they were
989 * simplified out---at this point no start clause has been
990 * selected. If that's the case, either use all positive/negative
991 * clauses or just the first, according to the parameters set.
992 *
993 * Note: this must choose at least one start clause because problems
994 * without a positive and negative clause have already been solved.
995 */
996 if (!first_clause_included) {
997 if (params::verbosity > 2) {
998 cout << "Note: you're asking for a conjecture to start, but there are none!" << endl;
999 cout << " depending on the other parameter settings, we will use one or " << endl;
1000 cout << " all of the negative clauses." << endl;
1001 }
1002 // Don't forget this! If you get here you have a whole bunch of
1003 // NoStart in results!
1004 results.clear();
1005 for (size_t i = 0; i < m_size; i++) {
1006 if ((
1007 (params::positive_representation && matrix.is_positive(i))
1008 ||
1009 (!params::positive_representation && matrix.is_negative(i))
1010 ) &&
1011 !(params::restrict_start && first_clause_included)) {
1012 results.push_back(StartClauseStatus::Start);
1013 first_clause_included = true;
1014 }
1015 else {
1016 results.push_back(StartClauseStatus::NoStart);
1017 }
1018 }
1019 }
1020}
1021//----------------------------------------------------------------------
1022//----------------------------------------------------------------------
1023//----------------------------------------------------------------------
1024// Find a single proof using iterative deepening search.
1025//----------------------------------------------------------------------
1026//----------------------------------------------------------------------
1027//----------------------------------------------------------------------
1028ProverOutcome StackProver::prove() {
1032 if (params::deterministic_reorder) {
1033 deterministic_reorder(params::number_of_reorders);
1034 }
1035 if (params::random_reorder) {
1037 }
1038 if (params::random_reorder_literals) {
1040 }
1041 pair<bool, size_t> start_clause = matrix.find_start();
1042 /*
1043 * If the initial clauses don't have a positive and a negative
1044 * clause then the problem is trivial.
1045 */
1046 if (!start_clause.first) {
1047 return ProverOutcome::False;
1048 }
1049 /*
1050 * You now have a complete matrix and you know its size.
1051 * This means you can set up caching of clause copies
1052 * properly.
1053 */
1056 /*
1057 * Deal with the possible ways to set up start clause(s) according to
1058 * the options. Keep track of which start clauses are in use, and if
1059 * necessary what outcomes for them have been seen so far.
1060 */
1062 /*
1063 * Main loop for iterative deepening search.
1064 */
1065 bool switched_to_complete = false;
1066 for (current_depth_limit = params::start_depth;
1067 current_depth_limit <= params::depth_limit;
1068 current_depth_limit += params::depth_increment) {
1069 /*
1070 * See if the parameters dictate that it's time to convert to
1071 * a complete search.
1072 */
1073 if (current_depth_limit >= params::switch_to_complete
1074 && !switched_to_complete) {
1076 /*
1077 * You may have changed some parameters, so make sure all relevant
1078 * start clauses now get tried.
1079 */
1081 current_depth_limit = params::start_depth;
1082 switched_to_complete = true;
1083 colour_string::ColourString cs(params::use_colours);
1084 show.nl(1);
1085 show(1, cs("Switching to complete search.").orange(), true);
1086 }
1087 show.nl(1);
1088 show(1, string("SEARCH TO DEPTH: "));
1089 show(1, std::to_string(current_depth_limit), true);
1090 /*
1091 * Generate each possible start move, and try to prove from
1092 * it.
1093 */
1094 size_t start_clause_index = 0;
1095 for (const Clause& C : matrix) {
1096 /*
1097 * Find the next start clause.
1098 */
1099 if (results[start_clause_index] == StartClauseStatus::NoStart
1100 || results[start_clause_index] == StartClauseStatus::False) {
1101 start_clause_index++;
1102 continue;
1103 }
1104 /*
1105 * Reset everything to use the current start clause.
1106 *
1107 * TODO: this is slightly messy at present because
1108 * the var_index doesn't necessarily get reset in the
1109 * most efficient way possible if a previous schedule
1110 * attempt timed out. (You'd need to go back down
1111 * the stack and backtrack it as necessary.) This is
1112 * of course irrelevant
1113 * because it just means you might not get full re-use of
1114 * new variable names, but all the same it would be nice
1115 * to fix.
1116 */
1117 //var_index.add_backtrack_point();
1119 //new_C = C.make_copy_with_new_vars(var_index, term_index);
1121 /*
1122 * Say what's going on.
1123 */
1124 show(1, string("START from clause "));
1125 show(1, std::to_string(start_clause_index + 1));
1126 show(1, string(" of "));
1127 show(1, std::to_string(matrix.get_num_clauses()));
1128 show(2, string(": "));
1129 show(2, new_C.to_string(), true);
1130 cout.flush();
1131 /*
1132 * Set up the initial stack item containing the start clause, and
1133 * populate it.
1134 */
1135 StackItem start_item(StackItemType::Start, new_C, path, lemmata, 1);
1136 start_item.set_this_action(InferenceItem(InferenceItemType::Start, start_clause_index));
1137 stack.push_back(start_item);
1138 si = 0;
1140 /*
1141 * Start with depth 1, as this makes sense when reading output if you're
1142 * using depth of recursion or path length.
1143 */
1144 current_depth = 1;
1145 /*
1146 * Liftoff!!!
1147 */
1148 ProverResult result = go();
1149 /*
1150 * Dealing with the outcome takes some care and depends on
1151 * the parameters being used.
1152 */
1153 switch (result) {
1154 case ProverResult::Valid:
1155 proof_count++;
1156 if (params::build_proof) {
1157 if (params::generate_LaTeX_proof) {
1158 proof_printer.make_LaTeX(params::LaTeX_proof_path,
1160 matrix.make_LaTeX());
1161 }
1162 if (params::generate_LaTeX_tableau_proof) {
1163 proof_printer.make_LaTeX_connection_tableau(params::LaTeX_tableau_proof_path,
1165 matrix.make_LaTeX());
1166 }
1167 if (params::generate_Prolog_proof) {
1168 fs::path prolog_path = params::Prolog_proof_path;
1169 proof_printer.make_Prolog(prolog_path);
1170 matrix.write_to_prolog_file(params::Prolog_matrix_path);
1171 }
1172 }
1173 show(1, string(": Found proof number "));
1174 show(1, std::to_string(proof_count), true);
1175 return ProverOutcome::Valid;
1176 break;
1177 case ProverResult::Error:
1178 return ProverOutcome::Error;
1179 break;
1180 case ProverResult::TimeOut:
1181 return ProverOutcome::TimeOut;
1182 break;
1183 case ProverResult::OptionsExhausted:
1184 /*
1185 * If you ran out of options because you reached the depth
1186 * limit then you still need to continue.
1187 */
1188 if (depth_limit_reached) {
1189 show(1, string(": Depth limited"), true);
1190 }
1191 /*
1192 * If you ran out of options without reaching the depth limit, then
1193 * what you do depends on whether or not the search is complete.
1194 */
1195 else {
1197 results[start_clause_index] = StartClauseStatus::False;
1198 show(1, string(": False"), true);
1199 }
1200 }
1201 start_clause_index++;
1202 break;
1203 default:
1204 return ProverOutcome::Error;
1205 break;
1206 }
1207 /*
1208 * This is necessary. Yes, I've checked. Think about it: you need
1209 * one extra backtrack to undo the new variables generated when you
1210 * make a start clause.
1211 */
1213 //var_index.backtrack();
1214 }
1215 /*
1216 * Loop for start moves ends here.
1217 *
1218 * If everything was False then the theorem is False, otherwise
1219 * at least one attempt was depth-limited.
1220 */
1221 bool all_false = true;
1222 for (StartClauseStatus& outcome : results) {
1223 if (outcome == StartClauseStatus::Start) {
1224 all_false = false;
1225 break;
1226 }
1227 }
1228 if (all_false)
1229 return ProverOutcome::False;
1230 }
1231 /*
1232 * Iterative deepening loop ends here.
1233 */
1234 return ProverOutcome::PathLenLimit;
1235}
1236//----------------------------------------------------------------------
1237vector<pair<string, vector<size_t>>> StackProver::get_internal_proof() const {
1239}
1240//----------------------------------------------------------------------
1241void StackProver::show_stack() {
1242 cout << "--------------------------------------------------------" << endl;
1243 cout << "Stack:" << endl;
1244 cout << "--------------------------------------------------------" << endl;
1245 cout << stack << endl;
1246 cout << "--------------------------------------------------------" << endl;
1247}
1248//----------------------------------------------------------------------
1249void StackProver::show_right_stack() {
1250 cout << "--------------------------------------------------------" << endl;
1251 cout << "Right Stack:" << endl;
1252 cout << "--------------------------------------------------------" << endl;
1253 cout << right_branch_stack << endl;
1254 cout << "--------------------------------------------------------" << endl;
1255}
1256//----------------------------------------------------------------------
1258 verbose_print::VPrint show(params::verbosity);
1259 show(1, string("Reductions: "));
1260 show(1, std::to_string(reductions_tried));
1261 show(1, string(" Extensions: "));
1262 show(1, std::to_string(extensions_tried));
1263 show(1, string(" Lemmata: "));
1264 show(1, std::to_string(lemmata_tried));
1265 show(1, string(" Right branches: "));
1266 show(1, std::to_string(right_branches_started), true);
1267}
1268//----------------------------------------------------------------------
1271 double s = static_cast<double>(ms) / 1000.0;
1272 double ext_rate = (static_cast<double>(extensions_tried) / s);
1273 double red_rate = (static_cast<double>(reductions_tried) / s);
1274 double lem_rate = (static_cast<double>(lemmata_tried) / s);
1275 double right_rate = (static_cast<double>(right_branches_started) / s);
1276 double total_rate = (static_cast<double>(total) / s);
1277 cout << "Reductions: " << setw(15) << reductions_tried << " (" << static_cast<size_t>(red_rate) << "/s)" << endl;
1278 cout << "Extensions: " << setw(15) << extensions_tried << " (" << static_cast<size_t>(ext_rate) << "/s)" << endl;
1279 cout << "Lemmas: " << setw(15) << lemmata_tried << " (" << static_cast<size_t>(lem_rate) << "/s)" << endl;
1280 cout << "Right branches: " << setw(15) << right_branches_started << " (" << static_cast<size_t>(right_rate) << "/s)" << endl;
1281 cout << "Total: " << setw(15) << total << " (" << static_cast<size_t>(total_rate) << "/s)" << endl;
1282}
1283//----------------------------------------------------------------------
1284ostream& operator<<(ostream& out, const StackProver& p) {
1285 out << "Current state of the RecursiveProver object" << endl;
1286 out << "-------------------------------------------" << endl << endl;
1287 out << p.var_index << endl;
1288 out << p.fun_index << endl;
1289 out << p.term_index << endl;
1290 out << p.path << endl;
1291 out << p.matrix << endl;
1292 return out;
1293}
void make_copy_with_new_variables(size_t, Clause &, const Matrix &, VariableIndex &, TermIndex &)
If there is a copy cached, replace the parameter with it. Otherwise, use the parameter to actually ma...
void set_size(size_t _s)
Set the number of clauses we need cached copies for.
void backtrack()
Backtracking is just looking at the last copy supplied and undoing that action.
void reset(const Matrix &, VariableIndex &, TermIndex &)
This is for any actual initialisation, when you either (1) intially know what you're dealing with,...
Representation of clauses.
Definition Clause.hpp:52
void add_lit(const Literal &)
Add a literal, making sure you don't duplicate.
Definition Clause.cpp:96
size_t size() const
Straightforward get method.
Definition Clause.hpp:78
string to_string(bool=false) const
Convert to a string.
Definition Clause.cpp:257
void drop_literal(LitNum)
Get rid of the specified Literal.
Definition Clause.cpp:168
Basic representation of functions.
Definition Function.hpp:54
Arity get_arity() const
Most basic access function.
Definition Function.hpp:88
string get_name() const
Most basic access function.
Definition Function.hpp:84
Arity find_minimum_arity() const
Find the smallest arity appearing for any Function in the index.
size_t get_size() const
Self-explanatory.
Arity find_maximum_arity() const
Find the largest arity appearing for any Function in the index.
bool tick()
Definition Interval.hpp:52
Representation of the lemma list.
Definition Lemmata.hpp:49
void push_back(const Literal &)
Self-explanatory.
Definition Lemmata.cpp:28
Basic representation of literals, bundling together (pointers to) a Predicate, a collection of argume...
Definition Literal.hpp:50
void move_equals_to_start()
Self-explanatory.
Definition Matrix.cpp:208
ClauseNum get_num_clauses() const
Straightforward get method.
Definition Matrix.hpp:225
string make_LaTeX(bool=false) const
Make a usable LaTeX representation.
Definition Matrix.cpp:259
void add_clause(Clause &, string="")
Add a Clause to the Matrix and update the index accordingly.
Definition Matrix.cpp:97
bool is_negative(size_t i) const
Is a particular Clause negative?
Definition Matrix.hpp:279
bool is_conjecture(size_t i) const
Is a particular Clause a conjecture?
Definition Matrix.cpp:49
void write_to_prolog_file(const path &) const
Write to a file that can be read by Prolog.
Definition Matrix.cpp:274
void set_num_equals(uint32_t n)
Straightforward set method.
Definition Matrix.hpp:297
bool is_positive(size_t i) const
Is a particular Clause positive?
Definition Matrix.hpp:273
void set_num_preds(size_t)
Make an empty index.
Definition Matrix.cpp:44
pair< bool, size_t > find_start() const
Use a simple heuristic to find a good start clause.
Definition Matrix.cpp:54
bool is_ground(size_t i) const
Is a particular Clause ground?
Definition Matrix.hpp:285
Basic representation of predicates: here just names, ids and arities.
Definition Predicate.hpp:51
Arity get_arity() const
Basic get method.
Definition Predicate.hpp:90
size_t get_num_preds() const
Basic get method.
Arity find_maximum_arity() const
Find the largest arity appearing in the index.
void make_LaTeX_connection_tableau(const path &, const path &, const string &)
Convert to LaTeX in the connection tableau calculus and store in the specified file.
void make_Prolog(const path &)
Convert to a form suitable for use by the Prolog proof checker and write to a file.
void make_LaTeX(const path &, const path &, const string &)
Convert to LaTeX and store in the specified file.
vector< pair< string, vector< size_t > > > make_internal() const
Make a simple data structure representing the proof stack.
void emplace_back(StackItemType sit, const Clause &_c, const SimplePath &_p, const Lemmata &_l, uint32_t _d)
(Almost!) exact analogue of the same function for vector<>.
Definition Stack.hpp:132
size_t size() const
Exact analogue of the same function for vector<>.
Definition Stack.hpp:94
bool empty() const
Exact analogue of the same function for vector<>.
Definition Stack.hpp:88
void push_back(const StackItem &_item)
Exact analogue of the same function for vector<>.
Definition Stack.hpp:100
void pop_back()
Exact analogue of the same function for vector<>. BUT - importantly - avoid calling the StackItem des...
Definition Stack.hpp:116
StackItem & back()
Exact analogue of the same function for vector<>.
Definition Stack.hpp:109
Prover using a pair of stacks to conduct the proof search.
void set_num_preds(size_t)
Set the number of predicates.
bool depth_limit_reached
Self-explanatary.
void process_axiom_forward()
Start a right branch to continue from an axiom.
string status
Problem status, if found in input file.
void read_from_tptp_file(const string &, bool &, size_t &)
Obviously, reads a problem from a TPTP file.
vector< StartClauseStatus > results
This is populated by the StackProver::set_up_start_clauses method.
bool negated_conjecture_removed
Keep track of whether the parser simplified the conjecture away.
static uint32_t lemmata_tried
We'll be keeping some simple statistics about the search process.
void show_full_statistics(size_t) const
Display counts of number of extensions tried and so on, as well as numbers per second.
void lemmata_backtrack()
One of several different kinds of backtracking.
Stack stack
Main stack: this is constructed by the search process and, if completed, represents a proof.
ClauseCopyCache clause_cache
Manages caching of copies of clauses from the matrix.
void reset_for_start()
Reset everything so that you can start from a specified start clause.
void random_reorder()
Randomly reorder the matrix.
uint32_t current_depth_limit
Self-explanatary.
InferenceItem action
Stores the next action from the current StackItem.
void set_up_start_clauses()
The start clauses to use depend on the settings, and the settings can change.
size_t num_preds
How many prdicates does the problem of interest have?
bool fof_has_axioms
Keep track of whether the parser found that it's an FOF problem with axioms before simplification.
ProverResult go()
This runs the proof search from a given Start Move.
Matrix matrix
A copy of the matrix you're working with.
void deterministic_reorder(uint32_t n)
Deterministically reorder the matrix n times.
bool axiom()
Test to see if you're at an axiom.
PredicateIndex pred_index
This class needs one of each kind of index to keep track of Variables, Terms etc.
ProofPrinter proof_printer
You need one of these to print LaTeX output or any kind of proof certificate.
void extend_with_action()
Take a single inference (action) and update the stacks accordingly.
bool cnf_only
Keep track of whether there were any FOF formulas in the problem file.
SimplePath path
At any point in the search process this is a copy of the path for the current node in the proof being...
FunctionIndex fun_index
This class needs one of each kind of index to keep track of Variables, Terms etc.
void populate_stack_item()
Fill the vector of possible actions with everything available.
Lemmata lemmata
At any point in the search process this is a copy of the list of lemmas for the current node in the p...
void show_statistics() const
Display counts of number of extensions tried and so on.
static uint32_t extensions_tried
We'll be keeping some simple statistics about the search process.
uint32_t current_depth
Self-explanatary.
string tptp_conversion_string
TPTP-friendly description of the clause conversion.
void add_equality_axioms(Predicate *)
After reading a problem in which = and/or != appears, add the axioms for equality.
bool simplified_fof_has_axioms
Keep track of whether the parser found that it's an FOF problem with axioms after simplification.
bool conjecture_missing
Keep track of whether the parser found a conjecture in the problem file.
TermIndex term_index
This class needs one of each kind of index to keep track of Variables, Terms etc.
uint32_t proof_count
If we're searching for multiple proofs, keep count of which one this is.
bool conjecture_false
Keep track of whether the parser found the conjecture to be false.
VariableIndex var_index
This class needs one of each kind of index to keep track of Variables, Terms etc.
void random_reorder_literals()
Randomly reorder the literals in each clause in the matrix.
size_t si
Index of the current StackItem.
void backtrack_once()
Basic, single step backtrack on the stack.
bool conjecture_true
Keep track of whether the parser found the conjecture to be true.
void left_extension_backtrack()
One of several different kinds of backtracking.
static uint32_t right_branches_started
We'll be keeping some simple statistics about the search process.
bool backtrack
Are we moving up or down the stack?
chrono::steady_clock::time_point end_time
When do we stop because of a timeout?
vector< pair< string, vector< size_t > > > get_internal_proof() const
Get an internal representation of the proof stack.
Clause new_C
At any point in the search process this is a copy of the clause for the current node in the proof bei...
void right_extension_backtrack()
One of several different kinds of backtracking.
fs::path problem_path
Path for the problem of interest.
StackProver()
You only need a basic constructor.
bool use_timeout
Are we using a timeout?
Stack right_branch_stack
We build the proof by trying the left branches of extensions first: this stack keeps track of the rig...
void reduction_backtrack()
One of several different kinds of backtracking.
static uint32_t reductions_tried
We'll be keeping some simple statistics about the search process.
SubstitutionStack sub_stack
There is a separate stack to make application and removal of substitutions straightforward.
verbose_print::VPrint show
Set up printing according to verbosity.
Unifier u
We need a single Unifier to use throughout the process.
ProverOutcome prove()
Here is where the magic happens.
Interval output_interval
How often do you output updates about progress?
General representation of a substitution.
void apply() const
Apply a substitution everywhere.
void backtrack()
Remove variables from the stack, and remove substitutions as you go, as far back as the most recent b...
void push_all(Substitution &)
Take all the substitutions provided and add the corresponding variables to the stack.
Wrap up everything the TPTP parser needs to do inside a single class.
bool simplified_fof_has_axioms() const
Where there any axioms for an FOF problem after simplification?
string get_problem_status()
The parse tries to identify the problem status.
void clear()
Clear everything associated with the TPTP parser.
bool parse_tptp_from_file(const string &)
Main method to parse from a TPTP file to the data structures needed by the prover.
bool fof_conjecture_is_missing() const
Was there a conjecture clause in the problem file?
bool equality_used()
Did equality turn up anywhere in the parse?
bool conjecture_present() const
Did a conjecture turn up anywhere in the parse?
bool fof_has_axioms() const
Where there any axioms for an FOF problem before simplification?
string get_tptp_conversion_string() const
Self-explanatory.
bool fof_conjecture_is_false() const
Self-explanatory.
bool fof_conjecture_is_true() const
Self-explanatory.
Predicate * get_equals_predicate() const
If equality turned up anywhere in the parse it will have been turned into an actual Predicate,...
bool problem_is_cnf_only() const
Self-explanatory.
size_t number_of_fof_formulas() const
How many first-order formulas turned up in the parse?
bool fof_negated_conjecture_removed() const
Was there a conjecture clause that got simplified away?
General representation of terms.
Definition Term.hpp:62
Term * add_function_term(Function *, const vector< Term * > &)
Self-explanatory: add a Term containing a function to the index.
Definition TermIndex.cpp:56
Term * add_variable_term(Variable *)
Self-explanatory: add a Term containing a variable to the index.
Definition TermIndex.cpp:41
void backtrack()
Apply the backtracking process to the substitution that has been constructed.
Definition Unifier.cpp:195
Substitution get_substitution() const
Trivial get methods for the result.
Definition Unifier.hpp:122
Basic representation of variables.
Definition Variable.hpp:58
Variable * add_named_var(const string &)
Add a variable with the specified name to the index.
void set_all_names_added()
Call this to indicate that only anonymous variables can now be created.
Simple addition of colour to strings and ostreams.
static string erase_line(uint8_t n)
Definition cursor.hpp:158
void nl(uint8_t, uint8_t=1)
Full representation of inferences, beyond just the name.
LitNum Lindex
The index of the literal within the clause being used.
LitNum Lprime
The index of the literal in C_2 being used.
Substitution sigma
A copy of the substitution that makes the rule applicable. This may or may not be reusable,...
Literal L
The Literal that is used to make the inference.
ClauseNum C_2
For extensions, the number of the clause for which a fresh copy is being made.
InferenceItemType T
What kind of inference is this?
Stack items: each contains its own material for generating possible next inferences.
Definition StackItem.hpp:54
void set_bt_restriction_index(size_t i)
Basic set method.
void set_this_action(const InferenceItem &inf_i)
Basic set method.
Structure containing all the command line and other options.
static void set_complete_parameters()
Change the parameters to make the search complete.
static bool no_start_options()
Self-explanatory.
static void correct_missing_start_options()
Self-explanatory.
static bool search_is_complete()
Self-explanatory.