-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Purity check #37
Comments
Are the benchmarks available anywhere? In a coming update, Inox will be assuming everything is pure when used as a backend for Stainless so this should disappear for purity checks within the solver. |
I was able to find a pattern that creates a blowup. The inlining creates an exponential blowup of the the size of It takes about 10 seconds to generate the verification conditions (not counting verification) with
When we remove the purity check, generation of verification conditions is almost instant (< 1s), import scala.language.postfixOps
import stainless.lang._
import stainless.collection._
object Nesting {
@inline
def lvl1(n: BigInt) = {
require (n >= 0)
true
} holds
@inline
def lvl2(n: BigInt) = {
require (n >= 0)
lvl1(0)
lvl1(0)
true
} holds
@inline
def lvl3(n: BigInt) = {
require(n >= 0)
lvl2(0)
lvl2(0)
true
} holds
@inline
def lvl4(n: BigInt) = {
require (n >= 0)
lvl3(0)
lvl3(0)
true
} holds
@inline
def lvl5(n: BigInt) = {
require (n >= 0)
lvl4(0)
lvl4(0)
true
} holds
@inline
def lvl6(n: BigInt) = {
require (n >= 0)
lvl5(0)
lvl5(0)
true
} holds
@inline
def lvl7(n: BigInt) = {
require (n >= 0)
lvl6(0)
lvl6(0)
true
} holds
} |
Unfortunately, I don't think I can provide a perfect "fix" to this issue other than disabling simplifications. I've added a cache to the Let simplifications in 7204d2a which makes your example much faster but there are probably still some edge cases where the blowup will occur. I thought of dropping the simplifications at some point but we have large speedups on some other benchmarks thanks to these so I ended up keeping them. You can try to use the --nosimplifications option to turn most simplifications off. |
I'm thinking about two points where perhaps we could improve the performance: 1) do we need to call For 1), I'm thinking that we could traverse the whole program once (bottom-up), and mark all For 2), can you explain a bit how the simplification works? |
|
So the worst-case execution time for simplify is exponential in the size of the formula? Don't you also need to call simplify again after that, since the lambda applications could give |
Yes, the worst case is exponential in the number of lets in the formula. I believe that in practice, the runtime shouldn't have to be exponential because lets almost never need to be re-simplified. The cache I added seems to support this claim, at least for the example you gave me. Yes, s/lambda application/beta-reduction/g. The simplifications that may occur due to beta-reductions will take place "locally" (when simplifying the application). When the simplifier sees an application with a known caller, it re-simplifies the inlined body, but this isn't exponential (I believe) because the re-simplification can only trigger once per application within an expression. |
Closing this as I can't see a way to fix it more than what we currently have. |
I'm opening this issue so that we remember that the
isPure
check ininox/src/main/scala/inox/ast/SymbolOps.scala
Line 1332 in 082081b
takes very long sometimes (some benchmarks that I will add take minutes
to run).
After doing some tests, it looks like the problem comes from the fact that
purity is checked by simplifying the whole formula. More precisely, the slowdown
seem to be coming from the simplification of Let's in
simplify
(https://github.com/epfl-lara/inox/blob/082081b77e80a0e95696c8649bdfb3d7f25a9d1d/src/main/scala/inox/transformers/SimplifierWithPC.scala lines 295-342).The text was updated successfully, but these errors were encountered: