Closed driehle closed 2 years ago
I found these snippets:
@greg0ire has further simplified down the issue to https://psalm.dev/r/53f79d44aa.
I found these snippets:
Reduced even more: https://psalm.dev/r/e79c2894ec
Must be a flaw in boolean module of Psalm. Which I believe is located in FormulaGenerator::getFormula
. It's 400 lines of recursive boolean operations. It's gonna be tricky
I found these snippets:
OK so this is tricky.
($a && $b) || (!$a && $c)
is expanded by Psalm to the conjunctive normal form
($a || $c) && (!$a || $b) && ($b || $c)
This equivalent (to Psalm) version demonstrates the same bug.
But when you enter that CNF into Wolfram Alpha it tells you the last term is unnecessary.
If you remove the unnecessary term the bug disappears.
The buggy method is Algebra::combineOredClauses
, but I don't know how to fix it — combineOredClauses
is a pretty simple method that just applies the standard distributed method for converting DNF to CNF. Then it looks like Algebra::negateFormula
has incorrect behaviour when passed a formula with unnecessary terms, but I don't think that is a bug — negateFormula
expects an optimal CNF.
I don't, honestly, remember how to obviously get the DNF to CNF conversion correct (missing the unnecessary term) on paper — once that was correct, fixing the combineOredClauses
method wouldn't be too difficult. Either way the solution would probably slow down combineOredClauses
.
I found these snippets:
Another example:
These two are functionally similar but give different output: https://psalm.dev/r/8f6b691a68
I found these snippets:
The solution is for me to add a rule to reduce the specific pattern
(A || <set of orred terms X>)
&& (!A || <set of orred terms Y>)
&& (<set of orred terms X> || <set of orred terms Y>)
to
(A || <set of orred terms X>)
&& (!A || <set of orred terms Y>)
i.e. when we have two clauses that negate a term within one another and another clause that's just the two uncontradicted terms together that clause is redundant. Should be a reasonably simple rule to add.
This is fixed on Psalm 5! Thanks Matt!
The following code raises two
ParadoxicalCondition
errors:Rewriting the first if condition in two statements makes the error disappear:
Code example: https://psalm.dev/r/d26bab675e