mirror of
https://github.com/Z3Prover/z3
synced 2026-05-25 11:26:21 +00:00
Fix TPTP parsing, arithmetic builtin mapping, and timeout handling
Agent-Logs-Url: https://github.com/Z3Prover/z3/sessions/f2be81f6-e506-47ea-a38a-46d1970add8c Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
This commit is contained in:
parent
ed7c9b7785
commit
4116a8acb0
2 changed files with 89 additions and 12 deletions
|
|
@ -16,6 +16,7 @@
|
||||||
#include "cmd_context/tptp_frontend.h"
|
#include "cmd_context/tptp_frontend.h"
|
||||||
#include "solver/solver.h"
|
#include "solver/solver.h"
|
||||||
#include "util/error_codes.h"
|
#include "util/error_codes.h"
|
||||||
|
#include "util/rational.h"
|
||||||
#include "util/z3_exception.h"
|
#include "util/z3_exception.h"
|
||||||
|
|
||||||
extern bool g_display_statistics;
|
extern bool g_display_statistics;
|
||||||
|
|
@ -49,6 +50,8 @@ enum class token_kind {
|
||||||
nand_tok,
|
nand_tok,
|
||||||
gt_tok,
|
gt_tok,
|
||||||
star_tok,
|
star_tok,
|
||||||
|
slash_tok,
|
||||||
|
minus_tok,
|
||||||
at_tok
|
at_tok
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -220,6 +223,8 @@ public:
|
||||||
case '=': t.kind = token_kind::equal_tok; return t;
|
case '=': t.kind = token_kind::equal_tok; return t;
|
||||||
case '>': t.kind = token_kind::gt_tok; return t;
|
case '>': t.kind = token_kind::gt_tok; return t;
|
||||||
case '*': t.kind = token_kind::star_tok; return t;
|
case '*': t.kind = token_kind::star_tok; return t;
|
||||||
|
case '/': t.kind = token_kind::slash_tok; return t;
|
||||||
|
case '-': t.kind = token_kind::minus_tok; return t;
|
||||||
case '@': t.kind = token_kind::at_tok; return t;
|
case '@': t.kind = token_kind::at_tok; return t;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
@ -279,14 +284,6 @@ class tptp_parser {
|
||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void skip_wrapping_lparens() {
|
|
||||||
while (accept(token_kind::lparen)) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
void skip_wrapping_rparens() {
|
|
||||||
while (accept(token_kind::rparen)) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
void next() { m_curr = m_lex->next(); }
|
void next() { m_curr = m_lex->next(); }
|
||||||
|
|
||||||
bool is(token_kind k) const { return m_curr.kind == k; }
|
bool is(token_kind k) const { return m_curr.kind == k; }
|
||||||
|
|
@ -322,7 +319,7 @@ class tptp_parser {
|
||||||
if (n == "$i") return m_univ;
|
if (n == "$i") return m_univ;
|
||||||
if (n == "$o") return m.mk_bool_sort();
|
if (n == "$o") return m.mk_bool_sort();
|
||||||
if (n == "$int") return m_arith.mk_int();
|
if (n == "$int") return m_arith.mk_int();
|
||||||
if (n == "$real") return m_arith.mk_real();
|
if (n == "$rat" || n == "$real") return m_arith.mk_real();
|
||||||
auto it = m_sorts.find(n);
|
auto it = m_sorts.find(n);
|
||||||
if (it != m_sorts.end()) return it->second;
|
if (it != m_sorts.end()) return it->second;
|
||||||
sort* s = m.mk_uninterpreted_sort(symbol(n));
|
sort* s = m.mk_uninterpreted_sort(symbol(n));
|
||||||
|
|
@ -334,6 +331,15 @@ class tptp_parser {
|
||||||
return s->get_name() == symbol("$tType");
|
return s->get_name() == symbol("$tType");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_decimal_numeral(std::string const& s) {
|
||||||
|
if (s.empty()) return false;
|
||||||
|
for (char c : s) {
|
||||||
|
if (!std::isdigit(static_cast<unsigned char>(c)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static std::string mk_decl_key(std::string const& name, unsigned arity, char tag) {
|
static std::string mk_decl_key(std::string const& name, unsigned arity, char tag) {
|
||||||
return std::to_string(name.size()) + ":" + name + "\x1f" + std::to_string(arity) + "\x1f" + tag;
|
return std::to_string(name.size()) + ":" + name + "\x1f" + std::to_string(arity) + "\x1f" + tag;
|
||||||
}
|
}
|
||||||
|
|
@ -453,10 +459,30 @@ class tptp_parser {
|
||||||
expect(token_kind::rparen, "')'");
|
expect(token_kind::rparen, "')'");
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
if (accept(token_kind::minus_tok)) {
|
||||||
|
expr_ref e = parse_term_primary();
|
||||||
|
if (!m_arith.is_int_real(e))
|
||||||
|
throw parse_error("unary '-' expects arithmetic term");
|
||||||
|
return expr_ref(m_arith.mk_uminus(e), m);
|
||||||
|
}
|
||||||
std::string n = parse_name();
|
std::string n = parse_name();
|
||||||
if (n == "$true") return expr_ref(m.mk_true(), m);
|
if (n == "$true") return expr_ref(m.mk_true(), m);
|
||||||
if (n == "$false") return expr_ref(m.mk_false(), m);
|
if (n == "$false") return expr_ref(m.mk_false(), m);
|
||||||
|
|
||||||
|
if (is_decimal_numeral(n)) {
|
||||||
|
rational num(n.c_str());
|
||||||
|
if (accept(token_kind::slash_tok)) {
|
||||||
|
std::string d = parse_name();
|
||||||
|
if (!is_decimal_numeral(d))
|
||||||
|
throw parse_error("denominator of rational literal must be a decimal numeral");
|
||||||
|
rational den(d.c_str());
|
||||||
|
if (den.is_zero())
|
||||||
|
throw parse_error("denominator of rational literal must be non-zero");
|
||||||
|
return expr_ref(m_arith.mk_numeral(num / den, false), m);
|
||||||
|
}
|
||||||
|
return expr_ref(m_arith.mk_numeral(num, true), m);
|
||||||
|
}
|
||||||
|
|
||||||
expr_ref b(m);
|
expr_ref b(m);
|
||||||
if (is_var_name(n) && find_bound(n, b))
|
if (is_var_name(n) && find_bound(n, b))
|
||||||
return b;
|
return b;
|
||||||
|
|
@ -494,6 +520,29 @@ class tptp_parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (n == "$less" || n == "$lesseq" || n == "$greater" || n == "$greatereq") {
|
||||||
|
if (args.size() != 2) {
|
||||||
|
std::ostringstream out;
|
||||||
|
out << "arithmetic predicate '" << n << "' expects arity 2";
|
||||||
|
throw parse_error(out.str());
|
||||||
|
}
|
||||||
|
expr_ref lhs(args.get(0), m), rhs(args.get(1), m);
|
||||||
|
if (!m_arith.is_int_real(lhs) || !m_arith.is_int_real(rhs)) {
|
||||||
|
std::ostringstream out;
|
||||||
|
out << "arithmetic predicate '" << n << "' expects arithmetic arguments";
|
||||||
|
throw parse_error(out.str());
|
||||||
|
}
|
||||||
|
bool use_real = m_arith.is_real(lhs) || m_arith.is_real(rhs);
|
||||||
|
if (use_real) {
|
||||||
|
if (m_arith.is_int(lhs)) lhs = expr_ref(m_arith.mk_to_real(lhs), m);
|
||||||
|
if (m_arith.is_int(rhs)) rhs = expr_ref(m_arith.mk_to_real(rhs), m);
|
||||||
|
}
|
||||||
|
if (n == "$less") return expr_ref(m_arith.mk_lt(lhs, rhs), m);
|
||||||
|
if (n == "$lesseq") return expr_ref(m_arith.mk_le(lhs, rhs), m);
|
||||||
|
if (n == "$greater") return expr_ref(m_arith.mk_gt(lhs, rhs), m);
|
||||||
|
/* n == "$greatereq"*/ return expr_ref(m_arith.mk_ge(lhs, rhs), m);
|
||||||
|
}
|
||||||
|
|
||||||
expr_ref lhs(m);
|
expr_ref lhs(m);
|
||||||
bool has_lhs = false;
|
bool has_lhs = false;
|
||||||
if (args.empty()) {
|
if (args.empty()) {
|
||||||
|
|
@ -612,11 +661,13 @@ class tptp_parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_type_decl_formula() {
|
void parse_type_decl_formula() {
|
||||||
skip_wrapping_lparens();
|
unsigned num_wrap = 0;
|
||||||
|
while (accept(token_kind::lparen)) ++num_wrap;
|
||||||
std::string name = parse_name();
|
std::string name = parse_name();
|
||||||
expect(token_kind::colon, "':'");
|
expect(token_kind::colon, "':'");
|
||||||
parsed_type t = parse_type_expr();
|
parsed_type t = parse_type_expr();
|
||||||
skip_wrapping_rparens();
|
while (num_wrap-- > 0)
|
||||||
|
expect(token_kind::rparen, "')'");
|
||||||
|
|
||||||
if (t.domain.empty() && is_ttype(t.range)) {
|
if (t.domain.empty() && is_ttype(t.range)) {
|
||||||
m_sorts.insert_or_assign(name, m.mk_uninterpreted_sort(symbol(name)));
|
m_sorts.insert_or_assign(name, m.mk_uninterpreted_sort(symbol(name)));
|
||||||
|
|
@ -724,6 +775,7 @@ public:
|
||||||
m_sorts.emplace("$i", m_univ);
|
m_sorts.emplace("$i", m_univ);
|
||||||
m_sorts.emplace("$o", m.mk_bool_sort());
|
m_sorts.emplace("$o", m.mk_bool_sort());
|
||||||
m_sorts.emplace("$int", m_arith.mk_int());
|
m_sorts.emplace("$int", m_arith.mk_int());
|
||||||
|
m_sorts.emplace("$rat", m_arith.mk_real());
|
||||||
m_sorts.emplace("$real", m_arith.mk_real());
|
m_sorts.emplace("$real", m_arith.mk_real());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -833,6 +885,14 @@ static unsigned read_tptp_stream(std::istream& in, char const* current_file) {
|
||||||
std::cerr << "TPTP parse error: " << ex.what() << "\n";
|
std::cerr << "TPTP parse error: " << ex.what() << "\n";
|
||||||
return ERR_PARSER;
|
return ERR_PARSER;
|
||||||
}
|
}
|
||||||
|
catch (z3_error& ex) {
|
||||||
|
if (ex.error_code() == ERR_TIMEOUT) {
|
||||||
|
std::cout << "% SZS status Timeout\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
std::cerr << "TPTP frontend error: " << ex.what() << "\n";
|
||||||
|
return ERR_INTERNAL_FATAL;
|
||||||
|
}
|
||||||
catch (z3_exception& ex) {
|
catch (z3_exception& ex) {
|
||||||
std::cerr << "TPTP frontend error: " << ex.what() << "\n";
|
std::cerr << "TPTP frontend error: " << ex.what() << "\n";
|
||||||
return ERR_INTERNAL_FATAL;
|
return ERR_INTERNAL_FATAL;
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,24 @@ fof(c1,conjecture, mortal(socrates)).)",
|
||||||
"% SZS status Theorem"},
|
"% SZS status Theorem"},
|
||||||
{"simple-sat",
|
{"simple-sat",
|
||||||
R"(fof(a1,axiom, p(a)).)",
|
R"(fof(a1,axiom, p(a)).)",
|
||||||
"% SZS status Satisfiable"}
|
"% SZS status Satisfiable"},
|
||||||
|
{"tff-negative-literal",
|
||||||
|
R"(tff(c1,conjecture, $less(-2,2)).)",
|
||||||
|
"% SZS status Theorem"},
|
||||||
|
{"tff-rational-literal",
|
||||||
|
R"(tff(c1,conjecture, $less(1/2,2/3)).)",
|
||||||
|
"% SZS status Theorem"},
|
||||||
|
{"tff-type-decl-arrow",
|
||||||
|
R"(tff(p_type,type, p: $int > $o ).
|
||||||
|
tff(a1,axiom, p(1)).
|
||||||
|
tff(c1,conjecture, p(1)).)",
|
||||||
|
"% SZS status Theorem"},
|
||||||
|
{"tff-typed-int-quantifier",
|
||||||
|
R"(tff(c1,conjecture, ? [X: $int] : $less(12,X)).)",
|
||||||
|
"% SZS status Theorem"},
|
||||||
|
{"tff-lesseq-built-in",
|
||||||
|
R"(tff(c1,conjecture, $lesseq(2,2)).)",
|
||||||
|
"% SZS status Theorem"}
|
||||||
};
|
};
|
||||||
for (auto const& c : cases) {
|
for (auto const& c : cases) {
|
||||||
std::string out = run_tptp(c.input);
|
std::string out = run_tptp(c.input);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue