Closed cvick32 closed 11 months ago
We have an undocumented option (set-option :proof-transformation LURPI)
that does some proof optimization before computing interpolants. It seems to already help for your example. The values are LU, RPI, RPILU, and LURPI, where LU (lower units) stands for one optimization, RPI (Recycle Pivots with Intersection) for the other, and RPILU and LURPI are the combination in two different orders. With LURPI, I already get much smaller interpolants.
We also have a formula simplifier that can be enabled with (set-option :simplify-interpolants true)
. You can also call it manually as (simplify (some-big-formula))
, which returns a simplified formula. This uses some fast solving to check if parts of the formula are redundant, which can help a lot for the interpolants we produce. Combining these techniques, I get the following much simpler interpolants:
((and (= 1 i-1) (= 0 pc-1) (<= 0 (+ n-1 (- 3))) (= 0 (select (store a-1 i-1 0) 0))) (and (= 0 pc-2) (and (<= 0 (+ n-2 (- 3))) (let ((.cse0 (store a-2 i-2 0))) (and (= 0 (select .cse0 1)) (and (<= i-2 2) (= (select .cse0 0) 0))))) (<= 0 (+ i-2 (- 2)))) (and (= 0 pc-3) (and (and (and (= 0 (select a-3 1)) (= 0 (select a-3 0))) (and (<= (+ i-3 (- 1)) 2) (= (select a-3 2) 0))) (<= 0 (+ i-3 (- 3)))) (<= 0 (+ n-3 (- 3)))) (or (and (= 1 pc-4) (<= i-4 0) (<= 0 (+ n-4 (- 3))) (and (and (= 0 (select a-4 1)) (= 0 (select a-4 0))) (and (<= (+ n-4 (- 1)) 2) (= (select a-4 2) 0)))) (and (= 0 pc-4) (<= 0 (+ n-4 (- 4))))) (let ((.cse0 (= 1 pc-5))) (or (and .cse0 (and (<= (+ i-5 (- 1)) 0) (<= 0 (+ n-5 (- 3)))) (let ((.cse6 (+ n-5 (- 1)))) (let ((.cse3 (<= .cse6 2)) (.cse4 (select a-5 2))) (let ((.cse1 (select a-5 1)) (.cse2 (select a-5 0)) (.cse5 (and .cse3 (or (< .cse6 2) (= .cse4 0))))) (or (and (and (= 0 .cse1) (= 0 .cse2)) (and .cse3 (= .cse4 1))) (and (= .cse2 1) (= .cse1 0) .cse5) (and (= .cse1 1) (= .cse2 0) .cse5)))))) (let ((.cse7 (+ n-5 (- 4)))) (and (=> .cse0 (<= i-5 .cse7)) (<= 0 .cse7))))) (let ((.cse0 (= 0 pc-6)) (.cse1 (+ n-6 (- 1)))) (and (or .cse0 (<= i-6 .cse1)) (or .cse0 (let ((.cse12 (select a-6 2))) (let ((.cse13 (select a-6 1)) (.cse8 (= .cse12 1)) (.cse6 (select a-6 0))) (let ((.cse10 (or (<= 0 (+ .cse6 (- 2))) (= .cse6 1))) (.cse5 (<= .cse1 2)) (.cse2 (or (<= 0 (+ .cse12 (- 2))) .cse8)) (.cse7 (= .cse13 0)) (.cse11 (or (<= 0 (+ .cse13 (- 2))) (= .cse13 1)))) (let ((.cse4 (or .cse7 .cse11)) (.cse9 (and .cse5 (or (= .cse12 0) .cse2))) (.cse3 (or (= .cse6 0) .cse10))) (or (and .cse2 .cse3 .cse4 .cse5 (<= (+ .cse6 (- 1)) 0) (or .cse7 .cse8)) (and .cse9 .cse10 .cse4) (and .cse9 .cse11 .cse3) (<= i-6 (+ n-6 (- 2))))))))) (<= 0 (+ n-6 (- 3))))) (or (or (and (not (= Z-7 0)) (and (not (= (+ Z-7 (- 1)) 0)) (<= Z-7 1))) (<= 0 (select a-7 Z-7))) (<= n-7 Z-7) (not (= 1 pc-7)) (<= i-7 (+ n-7 (- 1)))))
Both techniques should be relatively fast even for larger proofs/formulas.
You can also disable let
outputs with (set-option :print-terms-cse false)
. However, for larger formulas this will just explode. For the unsimplified interpolants it produces 11 MB of output.
Thanks so much for your response! I'm able to recreate everything except for calling simplify
.
I tried calling it like (simplify (get-interpolants A B C..))
but that throws an error.
Is there another way to call it?
For simplify you need to give the formula directly as argument:
(simplify (let ((.cse4 (+ i-1 (- 1)))) (let ((.cse3 (<= 0 .cse4)) (.cse0 (<= i-1 1))) (ite (= 1 i-1) (and (= 0 pc-1) (<= i-1 (+ n-1 (- 2))) (<= 0 (+ n-1 (- 3))) (or (let ((.cse2 (= 0 0)) (.cse1 (select (store a-1 i-1 0) 0))) (and .cse0 (= .cse1 0) .cse2 (and .cse2 .cse2) .cse2 (= 0 .cse1))) (= 1 0)) .cse3 (not (= 0 1))) (and (not (= .cse4 0)) (ite (<= .cse4 0) (=> (<= i-1 0) .cse3) .cse0))))))
outputs
(and (= 1 i-1) (= 0 pc-1) (<= 0 (+ n-1 (- 3))) (= 0 (select (store a-1 i-1 0) 0)))
So you would first need to parse the output and then send it back to the solver. You can also do it in a different smt script, but then you need to declare all the variables and functions again.
But (set-option :simplify-interpolants true)
is the way you want to use it.
Cool, thanks so much!
I'm encountering some pretty large interpolants for a problem. I've included the problem below, if you want to take a look at the output. I'm wondering if there is anyway to simplify these interpolants from within smtinterpol, or if there is a setting that I can enable that will eliminate
let
statements in the output.I'm mainly interested in seeing how the array functions
select
andstore
are being used in the interpolants and thelet
statements just confuse that.Thanks in advance.