Skip to content
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

Stuttering steps are not inserted for unchanged steps #56

Open
riz0id opened this issue Jan 10, 2023 · 0 comments
Open

Stuttering steps are not inserted for unchanged steps #56

riz0id opened this issue Jan 10, 2023 · 0 comments
Assignees
Labels
bug Something isn't working

Comments

@riz0id
Copy link
Collaborator

riz0id commented Jan 10, 2023

The current algorithm for checking the "eventually" modality has unexpected failures for specifications with next actions that do not make progress. If a specification does not explicitly assign the new values for the specification state using the prime operation, the model checker will not insert a stutter-step. The failure to introduce a stutter-step can cause the eventually checker to refute valid specifications.

Minimal Example

Considering the following specification:

type AlphabetVars = '["letter" # Char]

type AlphabetSpec = Specification AlphabetVars '["next" # 'WeakFair] '["isLetterZ" # 'Eventually]

isLetterZ :: Temporal AlphabetVars Bool
isLetterZ = do
  clock <- plain #letter
  pure (clock == 'z')

bitClockSpec :: AlphabetSpec
bitClockSpec =
  Specification
    { specInit = ConF #letter (pure 'a') NilF
    , specNext = ConF #next (ActionWF next) NilF
    , specProp = ConF #isLetterZ (PropF isLetterZ) NilF
    }

If we define the next function to be:

next :: Action AlphabetVars Bool
next = do
  letter <- plain #letter
  #letter .= pure (succ letter)
  pure (letter < 'z')

The model checker is able to find evidence that satisfies the proposition "eventually, the unprimed value of letter will be equal to the character 'z'". This is due to the final stutter-step satisfying plain #letter == 'z', which can be seen in the trace:

$ cabal v2-repl integration-tests
ghci> import Specifications.Alphabet
ghci> :set args --trace --diagram
ghci> alphabetSpecInteract
* 0x5a7b1068
│   #letter = 'z'* 0x5a7b1068
│   #letter = 'z'* 0x6a7b1068
│   #letter = 'y'
│ 
... 
│ 
* 0xdb7b1068
│   #letter = 'b'* 0xeb7b1068
    #letter = 'a'

check(pass)+trace

However, if next is reformulated such that #letter .= pure (succ letter) is only evaluated conditionally, then the resulting trace no longer contains the stutter-step satisfying plain #letter == 'z'. For example, the following definition of next:

next :: Action AlphabetVars Bool
next = do
  letter <- plain #letter
  when (letter < 'z') do
    #letter .= pure (succ letter)
  pure True

Should be equivalent to the former definition. However, wrapping(.=) with a when guard produces the following trace:

$ cabal v2-repl integration-tests
ghci> import Specifications.Alphabet
ghci> :set args --trace --diagram
ghci> alphabetSpecInteract
refuted property: eventually "isLetterZ"
  * from: 0x5a7b1068
      #letter = 'z'
  * to: 0x6a7b1068
      #letter = 'y'

* 0x5a7b1068
│   #letter = 'z'* 0x6a7b1068
│   #letter = 'y'
│ 
...
│ 
* 0xdb7b1068
│   #letter = 'b'* 0xeb7b1068
    #letter = 'a'

check(fail)+trace
@riz0id riz0id self-assigned this Jan 10, 2023
@riz0id riz0id added the bug Something isn't working label Jan 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants