Skip to content

:prove performance issues - even using "offline"/"w4-offline" #1204

@linesthatinterlace

Description

@linesthatinterlace

Hi. This is a MWE of an issue I think I'm having elsewhere, which I think is a bottleneck with how :prove converts something to an SMT-lib file.

I have the following module:

module example where

trivial : {n} (fin n) => Bit
property trivial = (zero : [n]) == (zero : [n])

I would like to :prove trivial`{n}, for large fixed n, say. For small n it's obviously very fast - I set :set prover=offline so I could just focus on the SMT-LIB conversion, and every output basically looks like this:

Writing to SMT-Lib file standard output...
To determine the validity of the expression, use an external SMT solver.
; Automatically created by SBV on 2021-05-29 12:49:36.4225209 BST
(set-option :smtlib2_compliant true)
(set-option :diagnostic-output-channel "stdout")
(set-option :produce-models true)
(set-logic QF_BV)
; --- uninterpreted sorts ---
; --- tuples ---
; --- sums ---
; --- literal constants ---
; --- skolem constants ---
; --- constant tables ---
; --- skolemized tables ---
; --- arrays ---
; --- uninterpreted constants ---
; --- user given axioms ---
; --- formula ---
(assert false)
(check-sat)
  • that is, the SMT-Lib file produced is trivial. However, for n > 2^30 (on my machine), I start seeing dramatic slowdown, and indeed on some investigation I think it is roughly O(n) (because moving to 2^31, 2^32 seemed to roughly double the time taken).

This means for large inputs (and in cryptographic contexts the inputs in terms of number of bits can get large enough that it starts to be problematic), the :prove conversion is really slow, even where it feels like it "shouldn't" be.

I get much better performance with using w4-offline (my understanding is that this uses a different backend) but in THIS case, it crashes for larger values of n, around 2^39, with "cryptol: word too wide for memory: 549755813888 bits". Which is reasonable I suppose - this IS a lot of a memory, right - but in this case it feels like it ought not to be strictly necessary if one could only apply some basic rules...

This originally came up in a context where I have functions f : a -> a and g : a -> a, some initial value init : a, and I want to show that take{n} (iterate f init) = take{n} (iterate g init), (where I certainly can prove a property of the form p a = f a == g a) - I had hoped that in some sense a "pattern match" was possible, but it seems that that isn't true, and indeed the above case shows that even in the most trivial case it's tricky - but also that the bottleneck is NOT the SMT solvers but the conversion to SMT-Lib that they perform.

Metadata

Metadata

Assignees

No one assigned

    Labels

    proverIssues related to :sat and :prove

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions