state_machine_checker 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +4 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +0 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +67 -0
- data/LICENSE.txt +21 -0
- data/README.md +102 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/state_machine_checker/adapters/state_machines.rb +40 -0
- data/lib/state_machine_checker/check_result.rb +40 -0
- data/lib/state_machine_checker/ctl/a_f.rb +20 -0
- data/lib/state_machine_checker/ctl/a_g.rb +20 -0
- data/lib/state_machine_checker/ctl/a_u.rb +23 -0
- data/lib/state_machine_checker/ctl/a_x.rb +20 -0
- data/lib/state_machine_checker/ctl/and.rb +42 -0
- data/lib/state_machine_checker/ctl/api.rb +61 -0
- data/lib/state_machine_checker/ctl/atom.rb +62 -0
- data/lib/state_machine_checker/ctl/binary_formula.rb +23 -0
- data/lib/state_machine_checker/ctl/e_f.rb +34 -0
- data/lib/state_machine_checker/ctl/e_g.rb +139 -0
- data/lib/state_machine_checker/ctl/e_u.rb +42 -0
- data/lib/state_machine_checker/ctl/e_x.rb +40 -0
- data/lib/state_machine_checker/ctl/formula.rb +42 -0
- data/lib/state_machine_checker/ctl/implication.rb +19 -0
- data/lib/state_machine_checker/ctl/not.rb +36 -0
- data/lib/state_machine_checker/ctl/or.rb +40 -0
- data/lib/state_machine_checker/ctl/unary_operator.rb +22 -0
- data/lib/state_machine_checker/finite_state_machine.rb +120 -0
- data/lib/state_machine_checker/labeled_machine.rb +51 -0
- data/lib/state_machine_checker/labeling.rb +48 -0
- data/lib/state_machine_checker/rspec_matchers.rb +60 -0
- data/lib/state_machine_checker/state_result.rb +57 -0
- data/lib/state_machine_checker/transition.rb +49 -0
- data/lib/state_machine_checker/version.rb +3 -0
- data/lib/state_machine_checker.rb +43 -0
- data/state_machine_checker.gemspec +47 -0
- metadata +186 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
require "state_machine_checker"
|
|
2
|
+
|
|
3
|
+
module StateMachineChecker
|
|
4
|
+
module RspecMatchers
|
|
5
|
+
def satisfy(formula)
|
|
6
|
+
SatisfyMatcher.new(formula)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
class SatisfyMatcher
|
|
10
|
+
include StateMachineChecker
|
|
11
|
+
|
|
12
|
+
def initialize(formula)
|
|
13
|
+
@formula = formula
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def description
|
|
17
|
+
"satisfy \"#{formula}\""
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def diffable?
|
|
21
|
+
false
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def matches?(instance_generator)
|
|
25
|
+
@instance_generator = instance_generator
|
|
26
|
+
@result = check_satisfied(formula, instance_generator)
|
|
27
|
+
@result.satisfied?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def failure_message
|
|
31
|
+
<<~MESSAGE
|
|
32
|
+
Expected state machine for #{machine_name} to satisfy "#{formula}" but it does not.
|
|
33
|
+
Counterexample: #{result.counterexample}
|
|
34
|
+
MESSAGE
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def failure_message_when_negated
|
|
38
|
+
<<~MESSAGE
|
|
39
|
+
Expected state machine for #{machine_name} not to satisfy "#{formula}" but it does.
|
|
40
|
+
Witness: #{result.witness}
|
|
41
|
+
MESSAGE
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def supports_block_expectations?
|
|
45
|
+
true
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
attr_reader :instance_generator, :formula, :result
|
|
51
|
+
|
|
52
|
+
def machine_name
|
|
53
|
+
# TODO: This assumes state_machines gem
|
|
54
|
+
klass = instance_generator.call.class
|
|
55
|
+
gem_machine = klass.state_machine
|
|
56
|
+
"#{klass}##{gem_machine.name}"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module StateMachineChecker
|
|
2
|
+
# The result of checking whether this state satisfies a formula.
|
|
3
|
+
class StateResult
|
|
4
|
+
# @param [Boolean] satisfied
|
|
5
|
+
# @param [Array<Symbol>] path
|
|
6
|
+
def initialize(satisfied, path)
|
|
7
|
+
@satisfied = satisfied
|
|
8
|
+
@path = path
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Whether the formula is satisfied from this state.
|
|
12
|
+
#
|
|
13
|
+
# @return [true, false]
|
|
14
|
+
def satisfied?
|
|
15
|
+
satisfied
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# A witness that the formula is satisfied from this state.
|
|
19
|
+
#
|
|
20
|
+
# @return [Array<Symbol>] an array of the names of transitions.
|
|
21
|
+
def witness
|
|
22
|
+
if satisfied?
|
|
23
|
+
path
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# A counterexample demonstrating that the formula is not satisfied from this
|
|
28
|
+
# state.
|
|
29
|
+
#
|
|
30
|
+
# @return [Array<Symbol>] an array of the names of transitions.
|
|
31
|
+
def counterexample
|
|
32
|
+
unless satisfied?
|
|
33
|
+
path
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def or(other)
|
|
38
|
+
if satisfied?
|
|
39
|
+
self
|
|
40
|
+
else
|
|
41
|
+
other
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def and(other)
|
|
46
|
+
if !other.satisfied?
|
|
47
|
+
other
|
|
48
|
+
else
|
|
49
|
+
self
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
attr_reader :satisfied, :path
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module StateMachineChecker
|
|
2
|
+
# A transition from one state to another
|
|
3
|
+
class Transition
|
|
4
|
+
attr_reader :from, :to, :name
|
|
5
|
+
|
|
6
|
+
# @param [Symbol] from the starting state.
|
|
7
|
+
# @param [Symbol] to the ending state.
|
|
8
|
+
# @param [Symbol] name the name of the transition.
|
|
9
|
+
def initialize(from, to, name)
|
|
10
|
+
@from = from
|
|
11
|
+
@to = to
|
|
12
|
+
@name = name
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Execute the transition on an instance.
|
|
16
|
+
#
|
|
17
|
+
# This assumes that the instance has a method corresponding to the
|
|
18
|
+
# transition name, and that that will return a boolean representing whether
|
|
19
|
+
# the transition was successful.
|
|
20
|
+
#
|
|
21
|
+
# @param instance the instance to execute the transition on.
|
|
22
|
+
def execute(instance)
|
|
23
|
+
# TODO: calling the "bang" version (to raise on failure) is specific to
|
|
24
|
+
# the state_machines gem.
|
|
25
|
+
instance.public_send("#{name}!")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def ==(other)
|
|
29
|
+
hash_attributes.all? { |attr|
|
|
30
|
+
other.respond_to?(attr) &&
|
|
31
|
+
other.public_send(attr) == public_send(attr)
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def eql?(other)
|
|
36
|
+
other == self
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def hash
|
|
40
|
+
hash_attributes.map(&:hash).hash
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def hash_attributes
|
|
46
|
+
[:from, :to, :name]
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require "state_machine_checker/version"
|
|
2
|
+
require "state_machine_checker/finite_state_machine"
|
|
3
|
+
require "state_machine_checker/labeled_machine"
|
|
4
|
+
require "state_machine_checker/labeling"
|
|
5
|
+
require "state_machine_checker/adapters/state_machines"
|
|
6
|
+
require "state_machine_checker/ctl/api"
|
|
7
|
+
|
|
8
|
+
# The main entrypoint is {#check_satisfied}. The other methods are provided
|
|
9
|
+
# primarily for debugging and transparency.
|
|
10
|
+
module StateMachineChecker
|
|
11
|
+
# Check whether a formula is satisfied by the state machine of a given class.
|
|
12
|
+
#
|
|
13
|
+
# @param [CTL::Formula] formula the formula that should be satisfied.
|
|
14
|
+
# @param instance_generator a thunk (zero-argument function) that must return
|
|
15
|
+
# an instance of an object containing a state machine. The instance must be
|
|
16
|
+
# in the initial state.
|
|
17
|
+
# @return [StateResult] the result for the initial state.
|
|
18
|
+
def check_satisfied(formula, instance_generator)
|
|
19
|
+
labeled_machine = build_labeled_machine(formula, instance_generator)
|
|
20
|
+
check = formula.check(labeled_machine)
|
|
21
|
+
check.for_state(labeled_machine.initial_state)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Build a labeled machine (Kripke structure) over the atomic propositions
|
|
25
|
+
# contained in the given formula.
|
|
26
|
+
#
|
|
27
|
+
# @param [CTL::Formula] formula the formula from which to extract atomic
|
|
28
|
+
# propositions.
|
|
29
|
+
# @param instance_generator a thunk (zero-argument function) that must return
|
|
30
|
+
# an instance of an object containing a state machine. The instance must be
|
|
31
|
+
# in the initial state.
|
|
32
|
+
# @return [LabeledMachine]
|
|
33
|
+
def build_labeled_machine(formula, instance_generator)
|
|
34
|
+
# TODO: Assumes state_machines gem.
|
|
35
|
+
gem_machine = instance_generator.call.class.state_machine
|
|
36
|
+
adapter = Adapters::StateMachines.new(gem_machine)
|
|
37
|
+
fsm = FiniteStateMachine.new(adapter.initial_state, adapter.transitions)
|
|
38
|
+
LabeledMachine.new(
|
|
39
|
+
fsm,
|
|
40
|
+
Labeling.new(formula.atoms, fsm, instance_generator)
|
|
41
|
+
)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
|
+
require "state_machine_checker/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "state_machine_checker"
|
|
7
|
+
spec.version = StateMachineChecker::VERSION
|
|
8
|
+
spec.authors = ["Chris Stadler"]
|
|
9
|
+
spec.email = ["chrisstadler@gmail.com"]
|
|
10
|
+
|
|
11
|
+
spec.summary = "Model checking for state machines using CTL."
|
|
12
|
+
spec.description = <<~DESC
|
|
13
|
+
Verify that your state machines have the expected properties. Properties are
|
|
14
|
+
specified using CTL.
|
|
15
|
+
DESC
|
|
16
|
+
spec.homepage = "https://github.com/CJStadler/state_machine_checker"
|
|
17
|
+
spec.license = "MIT"
|
|
18
|
+
|
|
19
|
+
if spec.respond_to?(:metadata)
|
|
20
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
21
|
+
spec.metadata["source_code_uri"] = "https://github.com/CJStadler/state_machine_checker"
|
|
22
|
+
spec.metadata["changelog_uri"] =
|
|
23
|
+
"https://github.com/CJStadler/state_machine_checker/blob/master/CHANGELOG.md"
|
|
24
|
+
else
|
|
25
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
|
26
|
+
"public gem pushes."
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Specify which files should be added to the gem when it is released.
|
|
30
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
31
|
+
spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
|
|
32
|
+
`git ls-files -z`.split("\x0").
|
|
33
|
+
reject { |f| f.match(%r{^(test|spec|features)/}) }.
|
|
34
|
+
reject { |f| f.match('paper.pdf')}
|
|
35
|
+
end
|
|
36
|
+
spec.bindir = "exe"
|
|
37
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
38
|
+
spec.require_paths = ["lib"]
|
|
39
|
+
|
|
40
|
+
spec.add_development_dependency "bundler", "~> 1.17"
|
|
41
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
|
42
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
|
43
|
+
spec.add_development_dependency "state_machines", "~> 0.5.0"
|
|
44
|
+
spec.add_development_dependency "standard", "~> 0.0.36"
|
|
45
|
+
spec.add_development_dependency "pry"
|
|
46
|
+
spec.add_development_dependency "yard", "~> 0.9.18"
|
|
47
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: state_machine_checker
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Chris Stadler
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2019-07-05 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.17'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.17'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '10.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '10.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rspec
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '3.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '3.0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: state_machines
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 0.5.0
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: 0.5.0
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: standard
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 0.0.36
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 0.0.36
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: pry
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: yard
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: 0.9.18
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: 0.9.18
|
|
111
|
+
description: |
|
|
112
|
+
Verify that your state machines have the expected properties. Properties are
|
|
113
|
+
specified using CTL.
|
|
114
|
+
email:
|
|
115
|
+
- chrisstadler@gmail.com
|
|
116
|
+
executables: []
|
|
117
|
+
extensions: []
|
|
118
|
+
extra_rdoc_files: []
|
|
119
|
+
files:
|
|
120
|
+
- ".gitignore"
|
|
121
|
+
- ".rspec"
|
|
122
|
+
- ".travis.yml"
|
|
123
|
+
- CHANGELOG.md
|
|
124
|
+
- CODE_OF_CONDUCT.md
|
|
125
|
+
- Gemfile
|
|
126
|
+
- Gemfile.lock
|
|
127
|
+
- LICENSE.txt
|
|
128
|
+
- README.md
|
|
129
|
+
- Rakefile
|
|
130
|
+
- bin/console
|
|
131
|
+
- bin/setup
|
|
132
|
+
- lib/state_machine_checker.rb
|
|
133
|
+
- lib/state_machine_checker/adapters/state_machines.rb
|
|
134
|
+
- lib/state_machine_checker/check_result.rb
|
|
135
|
+
- lib/state_machine_checker/ctl/a_f.rb
|
|
136
|
+
- lib/state_machine_checker/ctl/a_g.rb
|
|
137
|
+
- lib/state_machine_checker/ctl/a_u.rb
|
|
138
|
+
- lib/state_machine_checker/ctl/a_x.rb
|
|
139
|
+
- lib/state_machine_checker/ctl/and.rb
|
|
140
|
+
- lib/state_machine_checker/ctl/api.rb
|
|
141
|
+
- lib/state_machine_checker/ctl/atom.rb
|
|
142
|
+
- lib/state_machine_checker/ctl/binary_formula.rb
|
|
143
|
+
- lib/state_machine_checker/ctl/e_f.rb
|
|
144
|
+
- lib/state_machine_checker/ctl/e_g.rb
|
|
145
|
+
- lib/state_machine_checker/ctl/e_u.rb
|
|
146
|
+
- lib/state_machine_checker/ctl/e_x.rb
|
|
147
|
+
- lib/state_machine_checker/ctl/formula.rb
|
|
148
|
+
- lib/state_machine_checker/ctl/implication.rb
|
|
149
|
+
- lib/state_machine_checker/ctl/not.rb
|
|
150
|
+
- lib/state_machine_checker/ctl/or.rb
|
|
151
|
+
- lib/state_machine_checker/ctl/unary_operator.rb
|
|
152
|
+
- lib/state_machine_checker/finite_state_machine.rb
|
|
153
|
+
- lib/state_machine_checker/labeled_machine.rb
|
|
154
|
+
- lib/state_machine_checker/labeling.rb
|
|
155
|
+
- lib/state_machine_checker/rspec_matchers.rb
|
|
156
|
+
- lib/state_machine_checker/state_result.rb
|
|
157
|
+
- lib/state_machine_checker/transition.rb
|
|
158
|
+
- lib/state_machine_checker/version.rb
|
|
159
|
+
- state_machine_checker.gemspec
|
|
160
|
+
homepage: https://github.com/CJStadler/state_machine_checker
|
|
161
|
+
licenses:
|
|
162
|
+
- MIT
|
|
163
|
+
metadata:
|
|
164
|
+
homepage_uri: https://github.com/CJStadler/state_machine_checker
|
|
165
|
+
source_code_uri: https://github.com/CJStadler/state_machine_checker
|
|
166
|
+
changelog_uri: https://github.com/CJStadler/state_machine_checker/blob/master/CHANGELOG.md
|
|
167
|
+
post_install_message:
|
|
168
|
+
rdoc_options: []
|
|
169
|
+
require_paths:
|
|
170
|
+
- lib
|
|
171
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
172
|
+
requirements:
|
|
173
|
+
- - ">="
|
|
174
|
+
- !ruby/object:Gem::Version
|
|
175
|
+
version: '0'
|
|
176
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
177
|
+
requirements:
|
|
178
|
+
- - ">="
|
|
179
|
+
- !ruby/object:Gem::Version
|
|
180
|
+
version: '0'
|
|
181
|
+
requirements: []
|
|
182
|
+
rubygems_version: 3.0.1
|
|
183
|
+
signing_key:
|
|
184
|
+
specification_version: 4
|
|
185
|
+
summary: Model checking for state machines using CTL.
|
|
186
|
+
test_files: []
|