output proofs in the TPTP fragment of the input problem - #884
output proofs in the TPTP fragment of the input problem#884shalashaska117 wants to merge 6 commits into
Conversation
The proof output language was chosen with hasNonDefaultSorts(), which Problem recomputes from its current unit list. Preprocessing can remove the last unit mentioning a sort, and the property then reports an untyped problem while the proof still contains typed formulas. For the problems in vprover#730 the conjecture normalizes to ~$true, so the arithmetic disappears and the proof is printed as fof even though it contains $is_int. Type declarations are printed from the signature, which only grows, so the two could also disagree inside one proof, giving a tff type declaration followed by fof formulas. TFF subsumes FOF, so print tff unconditionally, or thf for higher-order problems, and drop the property test. TPTPPrinter already did this. Also annotate a quantified variable whose sort is not $i even when the property is false, to match Formula::toString.
cc068d0 to
f7b3617
Compare
MichaelRawson
left a comment
There was a problem hiding this comment.
Cool! I intend to merge after asking a few people about it.
This doesn't seem good: CI passes this test. What system are you using? |
I don't understand it either, I get the same error on main, I used Ubuntu latest version, now I'm not at the computer so can't see the exact version |
|
Uh-oh. Experience suggests that a compiler upgrade finally found a bug that was lurking - if you can, please try to debug the unit test. Otherwise I guess we'll let it play out. |
|
(but it's independent of this change of course, don't worry!) |
I will work on it today. |
|
@MichaelRawson success_3's expected clause was wrong (copy-pasted from success_2), and clang only hides it because it evaluates the two sides of the != in the opposite order to gcc, which makes the produced clause share a subterm with the expected one, and the test comparator returns true on identical subterms without checking that the variable renaming is consistent. |
|
I also like the fix, but I think the issue could also happen for I will open a separate PR with my proposed solution, so that we can discuss. |
I am very curious about your solution, I will look into it |
|
@mezpusz do you have any test idea that I could try to verify your claim about thf problems? trying something but I don't know how to check for all cases to be honest, so if you have better ideas to try to point to errors that I could not find |
|
I've checked it now with an "unsound" preprocessing step that just replaces all units with I pushed the changes for the alternative solution to |
|
@mezpusz any news about how to solve this problem? |
|
@shalashaska117 This is my proposed solution but I need to clear out a few other TPTP issues before I can verify that it works. |
Problem::hasNonDefaultSorts() and Problem::isHigherOrder() are recomputed from the current unit list, so when preprocessing removed the last typed or higher-order unit the proof came out in the wrong language. Instead of always printing tff, record both flags when the parsed problem is set as the main problem and pick fof, tff or thf from the recorded values. The proof stays in the fragment of the input: untyped problems keep fof, and originally higher-order problems keep thf even when preprocessing removes every higher-order construct. Recording the flags was suggested by @mezpusz in the vprover#884 discussion. Variable sort annotations keep the per-formula test (annotate whenever the sort is not $i), so a typed variable is never printed bare, and symbol type declarations follow the same recorded flag as the proof steps, so one proof cannot mix languages. FunctionRelationshipInference temporarily swaps the main problem during FMB sort bound detection, which runs after preprocessing; its two setMainProblem calls pass isInputProblem=false so the recorded fragment survives the swap.
printGeneralSplittingComponent passed getQuantifiedStr a static sort map that nothing ever filled, so the variables of a definition introduced by -gsp on printed without sorts, and a $int variable read back as $i. Collect the sorts from the clause instead, and remove the map-less overload, which is now unused. The proof printers also printed symbol type declarations when the proof itself is fof: the signature can hold a typed symbol that no unit ever used, and its declaration put a tff line in front of an fof proof. Skip the declarations when the recorded fragment is fof.
|
@mezpusz I went through
Two more changes in the same area:
|
Good catch!
The point of this assertion was to enforce callers to fill the map, otherwise @MichaelRawson might know why we want UB in case the assertion fails in release.
I think it should never happen that |
Wouldn't this create more problems?
I can check this easily, but in my test it never occurred. Easy fix to the code. |
I defined Consider e.g. void f(int x) {
if(x < 0) throw Exception("expected positive integer");
// ....
}
void g(int y) {
ASS(y > 0)
f(y);
// ...
}When inlining |
|
@mezpusz agreed on the assertion. I'll add ASS(t == AtomicSort::defaultSort() || env.initiallyHasNonDefaultSorts());at the two sites of the per-formula test ( I could not come up with a counterexample either: theory axioms, induction and FOOL elimination all need the sorts to be in the problem already. For some confidence beyond that I'll run a debug build with the assertion over On @MichaelRawson thanks for the explanation. One detail: in release only |
A non-default sort should never appear in a proof step of an initially untyped problem: every preprocessing step that builds sorted terms (theory axioms, induction, FOOL elimination) needs the sorts to be in the input already. Assert this in getQuantifiedStr and Formula::toString instead of relying on it silently. The disjunction stays as the print condition: ASS compiles to nothing in release, and if a future rule ever breaks the invariant, a release build prints the variable with its sort instead of dropping the annotation and changing the formula, while a debug build fails the assertion and points at the rule.
|
Pushed the assertion in 5bf5aa6: Validation: 97/97 unit tests in debug, The sweep did surface two debug assertion failures that already exist on master (reproduced at 3677326), so they are not from this PR:
I can open issues for these if they are not already known. |
The previous run died before starting: the job was never acquired by a hosted runner.
Oops, yes - evaluating the |
Fixes #730.
InferenceStorechose betweenfofandtffusingProblem::hasNonDefaultSorts(). That property is recomputed from the current unit list (refreshPropertycallsProperty::scan(_units)), so it answers "do the units I am holding right now mention a non-$isort" rather than "which fragment was the input problem in". Preprocessing can delete the last unit mentioning a sort, and the property then reports an untyped problem while the proof still contains typed formulas.The eight problems listed in #730 hit this. The conjecture normalizes to
~$true, the arithmetic disappears, and the proof comes out as:What changed
The first version of this PR printed
tffunconditionally, as @MichaelRawson suggested in #730. It is now the union of that and @mezpusz's counter-proposal onfix-output-tptp-fragment:ProblemrecordsinitiallyHasNonDefaultSortsandinitiallyHigherOrderwhen the input problem is set, and the proof printers pickfof,tfforthffrom those flags. A pure FOF problem keeps itsfofproof.t != defaultSort() || initiallyHasNonDefaultSorts()) ingetQuantifiedStrandFormula::toString, so a$intvariable surviving in a proof step never prints bare and reads back as$i.getQuantifiedStroverload without a sort map is gone. It passed a staticDHMapthat nothing ever filled, andprintGeneralSplittingComponentwent through it:ALWAYS(t_map.find(var,t))on an empty map is undefined behaviour in release, and the general splitting definitions printed their variables without sorts either way. The definition printer now collects the sorts from the clause.FunctionRelationshipInferenceswaps the main problem twice during FMB sort bound detection, which runs after preprocessing, so the flags got recomputed from the preprocessed units and the bug came back for fmb strategies. Those two calls now skip the recording (isInputProblem=false).outputSymbolTypeDeclarationIfNeededfollows the saved flags, and the proof printers skip type declarations entirely when the recorded fragment is fof. The signature can hold a typed symbol that no unit ever used, and its declaration would put atffline in front of anfofproof.-p on,-p smtcheckand-p smt2_proofcheckare untouched, and SAT steps from AVATAR still print ascnf.Testing
checks/sanitypasses. The new checks test both directions: nofofin the proofs of ARI496_1 andmixed-language.p, onlyfoffor PUZ001+1 and for a problem whose signature holds an unused typed symbol, and sort annotations on the gsp definitions (checks/proof/gsp-typed.pfails on master).-sa fmb -fmbdsb on.-p tptpover the checks problems against master: ARI496_1,let-bool.pandmixed-language.pchangefof(totff(,unused-typed-symbol.pdrops the unused declaration, every SZS status is unchanged, and the remaining outputs are identical up to the clause renumbering master already shows between runs.I still have not checked the output against a strict TPTP parser like tptp4X; Vampire's own parser accepted the broken proofs, so round-tripping through Vampire does not catch the old behaviour.