-
Notifications
You must be signed in to change notification settings - Fork 58
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
prop
and theorem
forget their quantifier?
#254
Comments
I'm with you. I was also confused. But I don't see how What do you suggest? |
I think the current stream-based interpretation is fine, as long as we also remember the associated quantifier. I don't know that I would necessarily expect a run-time interpretation of these properties, but they are certainly an important distinction when proving properties about a spec. It's important not to assume an existential property as though it is universal (which is unsound); and the proof techniques one can use for universal properties are different than for existential (induction vs model checking). In principle, one could interpret a universal property as a safety property and monitor it, but the trigger mechanism already basically does that. |
Here is a test case that demonstrates the issue: {-# LANGUAGE NoImplicitPrelude #-}
module Main (main) where
import Data.Foldable
import Data.Functor
import Copilot.Theorem.What4
import Language.Copilot
trueThenFalses :: Stream Bool
trueThenFalses = [True] ++ constant False
spec :: Spec
spec = do
void $ prop "forAll trueThenFalses (should be invalid)" (forAll trueThenFalses)
void $ prop "exists trueThenFalses (should be valid)" (exists trueThenFalses)
main :: IO ()
main = do
spec' <- reify spec
results <- prove Z3 spec'
forM_ results $ \(nm, res) -> do
putStr $ nm <> ": "
case res of
Valid -> putStrLn "valid"
Invalid -> putStrLn "invalid"
Unknown -> putStrLn "unknown" As its name suggests, |
Here is the Kind2 equivalent of the program above: {-# LANGUAGE NoImplicitPrelude #-}
module Main (main) where
import Data.Functor
import Copilot.Theorem.Kind2
import Copilot.Theorem.Prove
import Language.Copilot
trueThenFalses :: Stream Bool
trueThenFalses = [True] ++ constant False
spec :: Spec
spec = do
void $ theorem "t1" (forAll trueThenFalses) (check (kind2Prover def))
void $ theorem "t2" (exists trueThenFalses) (check (kind2Prover def))
main :: IO ()
main = void $ reify spec
Both the |
Looking at the datatypes involved in the high-level and low-level
Spec
datatypes (e.g.SpecItem
), it seems to me that properties and theorems are both represented as a bare stream of booleans. It strikes me as odd that we don't retain information about which quantifier was used to state the property, as it makes it impossible later to determine what semantics where intended; in particular, the quantifier for the property is not passed to theaskProver
method ofCopilot.Theorem.Prove.prove
, which strikes me as very strange. Am I missing something here?The text was updated successfully, but these errors were encountered: