25#include "StackProver.hpp"
46, action(InferenceItemType::Start)
48, current_depth_limit(0)
50, depth_limit_reached(false)
52, tptp_conversion_string()
56, proof_printer(&stack)
58, output_interval(
params::output_frequency)
64, conjecture_true(false)
65, conjecture_false(false)
66, conjecture_missing(false)
67, negated_conjecture_removed(false)
68, fof_has_axioms(false)
69, simplified_fof_has_axioms(false)
75 path.set_num_preds(n);
79 bool& found_conjecture,
103 if (params::show_clauses) {
104 std::exit(EXIT_SUCCESS);
107 if (
status !=
string(
"") && params::first_parse) {
108 show(1,
string(
"Problem status found: "));
111 if (equality && params::add_equality_axioms) {
112 if (params::first_parse) {
113 show(1,
string(
"Problem involves equality: adding axioms for =."),
true);
114 params::first_parse =
false;
117 if (params::equality_axioms_at_start) {
139 uint32_t max_arity = max_fun_arity;
140 if (max_pred_arity > max_arity)
141 max_arity = max_pred_arity;
146 string xvar(
"__eqx_");
147 string yvar(
"__eqy_");
148 for (
size_t i = 0; i < max_arity; i++) {
160 bool pol = !params::positive_representation;
161 uint32_t n_added = 0;
166 ref.push_back(xs[0]);
167 ref.push_back(xs[0]);
168 Literal reflexive(equals_predicate, ref, 2, pol);
182 Literal sym1(equals_predicate, xy, 2, !pol);
183 Literal sym2(equals_predicate, yx, 2, pol);
198 Literal tr1(equals_predicate, xy, 2, !pol);
199 Literal tr2(equals_predicate, yz, 2, !pol);
200 Literal tr3(equals_predicate, xz, 2, pol);
217 for (
size_t i = 0; i < ar; i++) {
218 x1xn.push_back(xs[i]);
219 y1yn.push_back(ys[i]);
221 xiyi.push_back(xs[i]);
222 xiyi.push_back(ys[i]);
223 Literal eq_lit(equals_predicate, xiyi, 2, !pol);
229 Literal f_lit(equals_predicate, t, 2, pol);
241 if (ar > 0 && p != equals_predicate) {
245 for (
size_t i = 0; i < ar; i++) {
246 x1xn.push_back(xs[i]);
247 y1yn.push_back(ys[i]);
249 xiyi.push_back(xs[i]);
250 xiyi.push_back(ys[i]);
251 Literal eq_lit(equals_predicate, xiyi, 2, !pol);
254 Literal p_lit1(p, x1xn, ar, !pol);
255 Literal p_lit2(p, y1yn, ar, pol);
266 if (!params::no_distinct_objects && min_arity == 0) {
267 vector<Term*> all_distinct_constants;
268 vector<Term*> empty_args;
274 string prefix = name.string::substr(0,params::unique_skolem_prefix.length());
275 bool is_skolem = (params::unique_skolem_prefix.string::compare(0, string::npos, prefix) == 0) &&
276 (params::unique_skolem_prefix.length() < name.length());
277 bool is_quoted = (name[0] ==
'\"' && name[name.size() - 1] ==
'\"');
280 (params::all_distinct_objects || is_quoted)) {
282 all_distinct_constants.push_back(t);
285 size_t s = all_distinct_constants.size();
287 for (
size_t i = s - 1; i > 0; i--) {
288 for (
size_t j = 0; j < i; j++) {
291 args.push_back(all_distinct_constants[i]);
292 args.push_back(all_distinct_constants[j]);
293 Literal eq_lit(equals_predicate, args, 2, !pol);
308 if (params::use_regularity_test && !path.test_for_regularity(
new_C))
323 if (params::use_lemmata) {
324 if (params::limit_lemmata)
359 UnificationOutcome outcome;
370 case InferenceItemType::Lemma:
376 if (params::limit_bt_lemmas)
377 stack[
si].restrict_backtrack();
388 stack.emplace_back(StackItemType::Lemmata,
new_C, path,
399 case InferenceItemType::Reduction:
405 if (params::limit_bt_reductions)
406 stack[
si].restrict_backtrack();
424 stack.emplace_back(StackItemType::Reduction,
new_C, path,
435 case InferenceItemType::Extension:
473 outcome =
u(neg_lit, ext_L);
486 stack.emplace_back(StackItemType::LeftBranch,
new_C, path,
491 cerr <<
"PANIC!!! You should only have a lemmata, reduction or an extension here!"
541 if (params::limit_bt_extensions) {
542 stack[
stack[
si].bt_restriction_index].restrict_backtrack();
597 if (!params::limit_bt_extensions ||
598 ((params::limit_bt_extensions || params::limit_bt_all) &&
599 !params::limit_bt_extensions_left_tree)) {
605 stack.back().clear();
626 if (params::limit_bt_extensions_left_tree) {
627 size_t target_index =
stack[
si].bt_restriction_index;
628 size_t current_index =
stack.size() - 1;
629 while (current_index > target_index) {
631 case StackItemType::Lemmata:
633 case StackItemType::Reduction:
636 case StackItemType::LeftBranch:
640 case StackItemType::RightBranch:
643 cerr <<
"Something is VERY WRONG!" << endl;
670 return ProverResult::TimeOut;
675 cout << cursor_symbols::Cursor::to_column(1);
679 cout <<
" Stack size: " <<
stack.size();
697 case StackItemType::Start:
699 if (
stack[
si].no_more_inferences())
700 return ProverResult::OptionsExhausted;
711 case StackItemType::Lemmata:
723 return ProverResult::Valid;
735 else if (
stack[
si].no_more_inferences())
769 case StackItemType::Reduction:
779 return ProverResult::Valid;
791 else if (
stack[
si].no_more_inferences())
826 case StackItemType::LeftBranch:
836 else if (
stack[
si].no_more_inferences())
860 case StackItemType::RightBranch:
867 return ProverResult::Valid;
873 else if (
stack[
si].no_more_inferences())
890 cerr <<
"Something is VERY WRONG!" << endl;
894 return ProverResult::Error;
917 if (params::all_start) {
918 for (
size_t i = 0; i < m_size; i++) {
919 results.push_back(StartClauseStatus::Start);
923 bool first_clause_included =
false;
930 if (params::all_pos_neg_start && !params::conjecture_start) {
931 for (
size_t i = 0; i < m_size; i++) {
939 (!(params::restrict_start && first_clause_included))
941 results.push_back(StartClauseStatus::Start);
942 first_clause_included =
true;
945 results.push_back(StartClauseStatus::NoStart);
952 else if (!params::all_pos_neg_start && params::conjecture_start) {
953 for (
size_t i = 0; i < m_size; i++) {
956 (!(params::restrict_start && first_clause_included))) {
957 results.push_back(StartClauseStatus::Start);
958 first_clause_included =
true;
961 results.push_back(StartClauseStatus::NoStart);
972 for (
size_t i = 0; i < m_size; i++) {
981 !(params::restrict_start && first_clause_included)) {
982 results.push_back(StartClauseStatus::Start);
983 first_clause_included =
true;
986 results.push_back(StartClauseStatus::NoStart);
1000 if (!first_clause_included) {
1001 if (params::verbosity > 2) {
1002 cout <<
"Note: you're asking for a conjecture to start, but there are none!" << endl;
1003 cout <<
" depending on the other parameter settings, we will use one or " << endl;
1004 cout <<
" all of the negative clauses." << endl;
1009 for (
size_t i = 0; i < m_size; i++) {
1015 !(params::restrict_start && first_clause_included)) {
1016 results.push_back(StartClauseStatus::Start);
1017 first_clause_included =
true;
1020 results.push_back(StartClauseStatus::NoStart);
1036 if (params::deterministic_reorder) {
1039 if (params::random_reorder) {
1042 if (params::random_reorder_literals) {
1050 if (!start_clause.first) {
1051 return ProverOutcome::False;
1062 bool switched_to_complete =
false;
1071 && !switched_to_complete) {
1079 switched_to_complete =
true;
1082 show(1, cs(
"Switching to complete search.").orange(),
true);
1085 show(1,
string(
"SEARCH TO DEPTH: "));
1091 size_t start_clause_index = 0;
1096 if (
results[start_clause_index] == StartClauseStatus::NoStart
1097 ||
results[start_clause_index] == StartClauseStatus::False) {
1098 start_clause_index++;
1120 show(1,
string(
"START from clause "));
1121 show(1, std::to_string(start_clause_index + 1));
1122 show(1,
string(
" of "));
1124 show(2,
string(
": "));
1133 stack.push_back(start_item);
1144 ProverResult result =
go();
1150 case ProverResult::Valid:
1152 if (params::build_proof) {
1153 if (params::generate_LaTeX_proof) {
1158 if (params::generate_Prolog_proof) {
1159 fs::path prolog_path = params::Prolog_proof_path;
1164 show(1,
string(
": Found proof number "));
1166 return ProverOutcome::Valid;
1168 case ProverResult::Error:
1169 return ProverOutcome::Error;
1171 case ProverResult::TimeOut:
1172 return ProverOutcome::TimeOut;
1174 case ProverResult::OptionsExhausted:
1180 show(1,
string(
": Depth limited"),
true);
1188 results[start_clause_index] = StartClauseStatus::False;
1189 show(1,
string(
": False"),
true);
1192 start_clause_index++;
1195 return ProverOutcome::Error;
1211 bool all_false =
true;
1212 for (StartClauseStatus& outcome :
results) {
1213 if (outcome == StartClauseStatus::Start) {
1219 return ProverOutcome::False;
1224 return ProverOutcome::PathLenLimit;
1231void StackProver::show_stack() {
1232 cout <<
"--------------------------------------------------------" << endl;
1233 cout <<
"Stack:" << endl;
1234 cout <<
"--------------------------------------------------------" << endl;
1235 for (
auto s :
stack) {
1238 cout <<
"--------------------------------------------------------" << endl;
1241void StackProver::show_right_stack() {
1242 cout <<
"--------------------------------------------------------" << endl;
1243 cout <<
"Right Stack:" << endl;
1244 cout <<
"--------------------------------------------------------" << endl;
1248 cout <<
"--------------------------------------------------------" << endl;
1253 show(1,
string(
"Reductions: "));
1255 show(1,
string(
" Extensions: "));
1257 show(1,
string(
" Lemmata: "));
1259 show(1,
string(
" Right branches: "));
1265 double s =
static_cast<double>(ms) / 1000.0;
1270 double total_rate = (
static_cast<double>(total) / s);
1271 cout <<
"Reductions: " << setw(15) <<
reductions_tried <<
" (" <<
static_cast<size_t>(red_rate) <<
"/s)" << endl;
1272 cout <<
"Extensions: " << setw(15) <<
extensions_tried <<
" (" <<
static_cast<size_t>(ext_rate) <<
"/s)" << endl;
1273 cout <<
"Lemmas: " << setw(15) <<
lemmata_tried <<
" (" <<
static_cast<size_t>(lem_rate) <<
"/s)" << endl;
1274 cout <<
"Right branches: " << setw(15) <<
right_branches_started <<
" (" <<
static_cast<size_t>(right_rate) <<
"/s)" << endl;
1275 cout <<
"Total: " << setw(15) << total <<
" (" <<
static_cast<size_t>(total_rate) <<
"/s)" << endl;
1278ostream& operator<<(ostream& out,
const StackProver& p) {
1279 out <<
"Current state of the RecursiveProver object" << endl;
1280 out <<
"-------------------------------------------" << endl << endl;
1284 out << p.
path << endl;
Representation of clauses.
Clause make_copy_with_new_vars(VariableIndex &, TermIndex &) const
Make a copy of an entire clause, introducing new variables.
void add_lit(const Literal &)
Add a literal, making sure you don't duplicate.
size_t size() const
Straightforward get method.
string to_string(bool=false) const
Convert to a string.
void drop_literal(LitNum)
Get rid of the specified Literal.
Basic representation of functions.
Arity get_arity() const
Most basic access function.
string get_name() const
Most basic access function.
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.
Representation of the lemma list.
void find_initial_lemmata(vector< InferenceItem > &, Clause &)
Find all lemmata that are applicable, but only for the initial Literal in a Clause.
void find_all_lemmata(vector< InferenceItem > &, Clause &)
Find all lemmata that are applicable, given a Clause.
void push_back(const Literal &)
Self-explanatory.
Basic representation of literals, bundling together (pointers to) a Predicate, a collection of argume...
void move_equals_to_start()
Self-explanatory.
ClauseNum get_num_clauses() const
Straightforward get method.
string make_LaTeX(bool=false) const
Make a usable LaTeX representation.
void get_literal_clause_pair(LitNum, size_t, Literal &, Clause &) const
Get a literal and clause from the index.
void add_clause(Clause &, string="")
Add a Clause to the Matrix and update the index accordingly.
bool is_negative(size_t i) const
Is a particular Clause negative?
bool is_conjecture(size_t i) const
Is a particular Clause a conjecture?
void write_to_prolog_file(const path &) const
Write to a file that can be read by Prolog.
void set_num_equals(uint32_t n)
Straightforward set method.
bool is_positive(size_t i) const
Is a particular Clause positive?
void set_num_preds(size_t)
Make an empty index.
pair< bool, size_t > find_start() const
Use a simple heuristic to find a good start clause.
bool is_ground(size_t i) const
Is a particular Clause ground?
Basic representation of predicates: here just names, ids and arities.
Arity get_arity() const
Basic get method.
size_t get_num_preds() const
Basic get method.
Arity find_maximum_arity() const
Find the largest arity appearing in the index.
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.
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.
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.
vector< StackItem > stack
Main stack: this is constructed by the search process and, if completed, represents a proof.
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.
PredicateIndex pred_index
This class needs one of each kind of index to keep track of Variables, Terms etc.
vector< StackItem > right_branch_stack
We build the proof by trying the left branches of extensions first: this stack keeps track of the rig...
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 depth_limited()
Test for the depth limit.
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?
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.
bool axiom() const
Test to see if you're at an axiom.
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.
Term * add_function_term(Function *, const vector< Term * > &)
Self-explanatory: add a Term containing a function to the index.
Term * add_variable_term(Variable *)
Self-explanatory: add a Term containing a variable to the index.
void backtrack()
Apply the backtracking process to the substitution that has been constructed.
Substitution get_substitution() const
Trivial get methods for the result.
Basic representation of variables.
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.
void backtrack()
Backtrack to the last marker.
void add_backtrack_point()
Add a backtrack point.
Simple addition of colour to strings and ostreams.
static string erase_line(uint8_t n)
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.
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.
size_t index_to_LC
Estensions are performance-critical. We store the index into the literal_clause_index,...
size_t index_in_LC_index
Estensions are performance-critical. We store the index into the literal_clause_index,...
InferenceItemType T
What kind of inference is this?
Stack items: each contains its own material for generating possible next inferences.
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.