lernen 0.2.0 → 0.3.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 +4 -4
- data/.rubocop.yml +15 -0
- data/README.md +534 -48
- data/Rakefile +26 -7
- data/Steepfile +14 -0
- data/examples/ripper_prism.rb +63 -0
- data/examples/uri_parse_regexp.rb +73 -0
- data/lib/lernen/algorithm/cex_processor/acex.rb +43 -0
- data/lib/lernen/algorithm/cex_processor/prefix_transformer_acex.rb +43 -0
- data/lib/lernen/algorithm/cex_processor.rb +115 -0
- data/lib/lernen/algorithm/kearns_vazirani/discrimination_tree.rb +207 -0
- data/lib/lernen/algorithm/kearns_vazirani/kearns_vazirani_learner.rb +100 -0
- data/lib/lernen/algorithm/kearns_vazirani.rb +44 -0
- data/lib/lernen/algorithm/kearns_vazirani_vpa/discrimination_tree_vpa.rb +246 -0
- data/lib/lernen/algorithm/kearns_vazirani_vpa/kearns_vazirani_vpa_learner.rb +89 -0
- data/lib/lernen/algorithm/kearns_vazirani_vpa.rb +35 -0
- data/lib/lernen/algorithm/learner.rb +82 -0
- data/lib/lernen/algorithm/lsharp/lsharp_learner.rb +367 -0
- data/lib/lernen/algorithm/lsharp/observation_tree.rb +115 -0
- data/lib/lernen/algorithm/lsharp.rb +43 -0
- data/lib/lernen/algorithm/lstar/lstar_learner.rb +49 -0
- data/lib/lernen/algorithm/lstar/observation_table.rb +214 -0
- data/lib/lernen/algorithm/lstar.rb +49 -0
- data/lib/lernen/algorithm/procedural/atr_manager.rb +200 -0
- data/lib/lernen/algorithm/procedural/procedural_learner.rb +223 -0
- data/lib/lernen/algorithm/procedural/procedural_sul.rb +47 -0
- data/lib/lernen/algorithm/procedural/return_indices_acex.rb +58 -0
- data/lib/lernen/algorithm/procedural.rb +57 -0
- data/lib/lernen/algorithm.rb +19 -0
- data/lib/lernen/automaton/dfa.rb +204 -0
- data/lib/lernen/automaton/mealy.rb +108 -0
- data/lib/lernen/automaton/moore.rb +122 -0
- data/lib/lernen/automaton/moore_like.rb +83 -0
- data/lib/lernen/automaton/proc_util.rb +93 -0
- data/lib/lernen/automaton/spa.rb +368 -0
- data/lib/lernen/automaton/transition_system.rb +209 -0
- data/lib/lernen/automaton/vpa.rb +300 -0
- data/lib/lernen/automaton.rb +19 -493
- data/lib/lernen/equiv/combined_oracle.rb +57 -0
- data/lib/lernen/equiv/exhaustive_search_oracle.rb +60 -0
- data/lib/lernen/equiv/moore_like_simulator_oracle.rb +36 -0
- data/lib/lernen/equiv/oracle.rb +109 -0
- data/lib/lernen/equiv/random_walk_oracle.rb +69 -0
- data/lib/lernen/equiv/random_well_matched_word_oracle.rb +139 -0
- data/lib/lernen/equiv/random_word_oracle.rb +71 -0
- data/lib/lernen/equiv/spa_simulator_oracle.rb +39 -0
- data/lib/lernen/equiv/test_words_oracle.rb +42 -0
- data/lib/lernen/equiv/transition_system_simulator_oracle.rb +36 -0
- data/lib/lernen/equiv/vpa_simulator_oracle.rb +48 -0
- data/lib/lernen/equiv.rb +25 -0
- data/lib/lernen/graph.rb +215 -0
- data/lib/lernen/system/block_sul.rb +41 -0
- data/lib/lernen/system/moore_like_simulator.rb +45 -0
- data/lib/lernen/system/moore_like_sul.rb +33 -0
- data/lib/lernen/system/sul.rb +126 -0
- data/lib/lernen/system/transition_system_simulator.rb +40 -0
- data/lib/lernen/system.rb +72 -0
- data/lib/lernen/version.rb +2 -1
- data/lib/lernen.rb +284 -34
- data/rbs_collection.lock.yaml +16 -0
- data/rbs_collection.yaml +14 -0
- data/renovate.json +6 -0
- data/sig/generated/lernen/algorithm/cex_processor/acex.rbs +30 -0
- data/sig/generated/lernen/algorithm/cex_processor/prefix_transformer_acex.rbs +27 -0
- data/sig/generated/lernen/algorithm/cex_processor.rbs +59 -0
- data/sig/generated/lernen/algorithm/kearns_vazirani/discrimination_tree.rbs +68 -0
- data/sig/generated/lernen/algorithm/kearns_vazirani/kearns_vazirani_learner.rbs +51 -0
- data/sig/generated/lernen/algorithm/kearns_vazirani.rbs +32 -0
- data/sig/generated/lernen/algorithm/kearns_vazirani_vpa/discrimination_tree_vpa.rbs +73 -0
- data/sig/generated/lernen/algorithm/kearns_vazirani_vpa/kearns_vazirani_vpa_learner.rbs +51 -0
- data/sig/generated/lernen/algorithm/kearns_vazirani_vpa.rbs +20 -0
- data/sig/generated/lernen/algorithm/learner.rbs +53 -0
- data/sig/generated/lernen/algorithm/lsharp/lsharp_learner.rbs +103 -0
- data/sig/generated/lernen/algorithm/lsharp/observation_tree.rbs +53 -0
- data/sig/generated/lernen/algorithm/lsharp.rbs +38 -0
- data/sig/generated/lernen/algorithm/lstar/lstar_learner.rbs +38 -0
- data/sig/generated/lernen/algorithm/lstar/observation_table.rbs +79 -0
- data/sig/generated/lernen/algorithm/lstar.rbs +37 -0
- data/sig/generated/lernen/algorithm/procedural/atr_manager.rbs +80 -0
- data/sig/generated/lernen/algorithm/procedural/procedural_learner.rbs +79 -0
- data/sig/generated/lernen/algorithm/procedural/procedural_sul.rbs +36 -0
- data/sig/generated/lernen/algorithm/procedural/return_indices_acex.rbs +33 -0
- data/sig/generated/lernen/algorithm/procedural.rbs +27 -0
- data/sig/generated/lernen/algorithm.rbs +10 -0
- data/sig/generated/lernen/automaton/dfa.rbs +93 -0
- data/sig/generated/lernen/automaton/mealy.rbs +61 -0
- data/sig/generated/lernen/automaton/moore.rbs +69 -0
- data/sig/generated/lernen/automaton/moore_like.rbs +63 -0
- data/sig/generated/lernen/automaton/proc_util.rbs +38 -0
- data/sig/generated/lernen/automaton/spa.rbs +125 -0
- data/sig/generated/lernen/automaton/transition_system.rbs +108 -0
- data/sig/generated/lernen/automaton/vpa.rbs +109 -0
- data/sig/generated/lernen/automaton.rbs +15 -0
- data/sig/generated/lernen/equiv/combined_oracle.rbs +27 -0
- data/sig/generated/lernen/equiv/exhaustive_search_oracle.rbs +38 -0
- data/sig/generated/lernen/equiv/moore_like_simulator_oracle.rbs +27 -0
- data/sig/generated/lernen/equiv/oracle.rbs +75 -0
- data/sig/generated/lernen/equiv/random_walk_oracle.rbs +41 -0
- data/sig/generated/lernen/equiv/random_well_matched_word_oracle.rbs +70 -0
- data/sig/generated/lernen/equiv/random_word_oracle.rbs +45 -0
- data/sig/generated/lernen/equiv/spa_simulator_oracle.rbs +30 -0
- data/sig/generated/lernen/equiv/test_words_oracle.rbs +20 -0
- data/sig/generated/lernen/equiv/transition_system_simulator_oracle.rbs +27 -0
- data/sig/generated/lernen/equiv/vpa_simulator_oracle.rbs +33 -0
- data/sig/generated/lernen/equiv.rbs +11 -0
- data/sig/generated/lernen/graph.rbs +80 -0
- data/sig/generated/lernen/system/block_sul.rbs +29 -0
- data/sig/generated/lernen/system/moore_like_simulator.rbs +31 -0
- data/sig/generated/lernen/system/moore_like_sul.rbs +28 -0
- data/sig/generated/lernen/system/sul.rbs +87 -0
- data/sig/generated/lernen/system/transition_system_simulator.rbs +28 -0
- data/sig/generated/lernen/system.rbs +62 -0
- data/sig/generated/lernen/version.rbs +6 -0
- data/sig/generated/lernen.rbs +214 -0
- data/sig-test/generated/test/example_test.rbs +14 -0
- data/sig-test/generated/test/lernen/algorithm/kearns_vazirani_test.rbs +16 -0
- data/sig-test/generated/test/lernen/algorithm/kearns_vazirani_vpa_test.rbs +10 -0
- data/sig-test/generated/test/lernen/algorithm/lsharp_test.rbs +16 -0
- data/sig-test/generated/test/lernen/algorithm/lstar_test.rbs +16 -0
- data/sig-test/generated/test/lernen/algorithm/procedural_test.rbs +10 -0
- data/sig-test/generated/test/lernen/automaton/dfa_test.rbs +19 -0
- data/sig-test/generated/test/lernen/automaton/mealy_test.rbs +19 -0
- data/sig-test/generated/test/lernen/automaton/moore_test.rbs +19 -0
- data/sig-test/generated/test/lernen/automaton/proc_util_test.rbs +19 -0
- data/sig-test/generated/test/lernen/automaton/spa_test.rbs +19 -0
- data/sig-test/generated/test/lernen/automaton/vpa_test.rbs +19 -0
- data/sig-test/generated/test/lernen/equiv/exhaustive_search_oracle_test.rbs +10 -0
- data/sig-test/generated/test/lernen/equiv/random_walk_oracle_test.rbs +10 -0
- data/sig-test/generated/test/lernen/equiv/random_word_oracle_test.rbs +10 -0
- data/sig-test/generated/test/lernen/system/block_sul_test.rbs +16 -0
- data/sig-test/generated/test/lernen/system/moore_like_simulator_test.rbs +16 -0
- data/sig-test/generated/test/lernen/system/transition_system_simulator_test.rbs +13 -0
- data/sig-test/generated/test/lernen/system_test.rbs +11 -0
- data/sig-test/generated/test/lernen_test.rbs +13 -0
- metadata +131 -11
- data/.yardopts +0 -3
- data/lib/lernen/cex_processor.rb +0 -92
- data/lib/lernen/kearns_vazirani.rb +0 -310
- data/lib/lernen/lsharp.rb +0 -344
- data/lib/lernen/lstar.rb +0 -170
- data/lib/lernen/oracle.rb +0 -119
- data/lib/lernen/sul.rb +0 -210
@@ -0,0 +1,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# rbs_inline: enabled
|
3
|
+
|
4
|
+
module Lernen
|
5
|
+
module Equiv
|
6
|
+
# Oracle is an oracle for answering a equivalence query.
|
7
|
+
#
|
8
|
+
# On running equivalence queries, this records the statistics information.
|
9
|
+
# We can obtain this information by `Oracle#stats`.
|
10
|
+
#
|
11
|
+
# Note that this class is *abstract*. You should implement the following method:
|
12
|
+
#
|
13
|
+
# - `#find_cex(hypothesis)`
|
14
|
+
#
|
15
|
+
# @rbs generic In -- Type for input alphabet
|
16
|
+
# @rbs generic Out -- Type for output values
|
17
|
+
class Oracle
|
18
|
+
# @rbs @sul: System::SUL[In, Out]
|
19
|
+
# @rbs @num_calls: Integer
|
20
|
+
# @rbs @num_queries: Integer
|
21
|
+
# @rbs @num_steps: Integer
|
22
|
+
# @rbs @current_conf: untyped
|
23
|
+
|
24
|
+
#: (System::SUL[In, Out] sul) -> void
|
25
|
+
def initialize(sul)
|
26
|
+
@sul = sul
|
27
|
+
|
28
|
+
@num_calls = 0
|
29
|
+
@num_queries = 0
|
30
|
+
@num_steps = 0
|
31
|
+
@current_conf = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_reader :sul #: System::SUL[In, Out]
|
35
|
+
|
36
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
37
|
+
|
38
|
+
# Finds a conterexample against the given `hypothesis` automaton.
|
39
|
+
# If it is found, it returns the counterexample word, or it returns `nil` otherwise.
|
40
|
+
#
|
41
|
+
# A counterexample means that it separates a sul and a hypothesis automaton on an output
|
42
|
+
# value, i.e., `hypothesis.run(cex)[0].last != sul.query_last(cex)`. We also assume
|
43
|
+
# a counterexample is minimal; that is, there is no `n` (where `0 <= n < cex.size`)
|
44
|
+
# such that `hypothesis.run(cex[0...n])[0].last != sul.query_last(cex[0...n])`.
|
45
|
+
#
|
46
|
+
#: [Conf] (Automaton::TransitionSystem[Conf, In, Out] hypothesis) -> (Array[In] | nil)
|
47
|
+
def find_cex(hypothesis)
|
48
|
+
@num_calls += 1
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
|
52
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
53
|
+
|
54
|
+
# Returns the statistics information as a `Hash` object.
|
55
|
+
#
|
56
|
+
# The result hash contains the following values.
|
57
|
+
#
|
58
|
+
# - `num_calls`: The number of calls of `find_cex`.
|
59
|
+
# - `num_queries`: The number of queries.
|
60
|
+
# - `num_steps`: The total number of steps.
|
61
|
+
#
|
62
|
+
#: () -> Hash[Symbol, Integer]
|
63
|
+
def stats
|
64
|
+
{ num_calls: @num_calls, num_queries: @num_queries, num_steps: @num_steps }
|
65
|
+
end
|
66
|
+
|
67
|
+
# Combines two oracles.
|
68
|
+
#
|
69
|
+
#: (Oracle[In, Out] other) -> CombinedOracle[In, Out]
|
70
|
+
def +(other)
|
71
|
+
oracles = []
|
72
|
+
|
73
|
+
is_a?(CombinedOracle) ? oracles.concat(oracles) : oracles << self
|
74
|
+
other.is_a?(CombinedOracle) ? oracles.concat(other.oracles) : oracles << other
|
75
|
+
|
76
|
+
CombinedOracle.new(oracles)
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# Resets the internal states of this oracle.
|
82
|
+
#
|
83
|
+
#: [Conf] (Automaton::TransitionSystem[Conf, In, Out] hypothesis) -> void
|
84
|
+
def reset_internal(hypothesis)
|
85
|
+
@num_queries += 1
|
86
|
+
|
87
|
+
@current_conf = hypothesis.initial_conf
|
88
|
+
|
89
|
+
@sul.shutdown
|
90
|
+
@sul.setup
|
91
|
+
end
|
92
|
+
|
93
|
+
# Runs a transition of both a hypothesis and a SUL.
|
94
|
+
#
|
95
|
+
#: [Conf] (
|
96
|
+
# Automaton::TransitionSystem[Conf, In, Out] hypothesis,
|
97
|
+
# In input
|
98
|
+
# ) -> [Out, Out]
|
99
|
+
def step_internal(hypothesis, input)
|
100
|
+
@num_steps += 1
|
101
|
+
|
102
|
+
hypothesis_output, @current_conf = hypothesis.step(@current_conf, input)
|
103
|
+
sul_output = @sul.step(input)
|
104
|
+
|
105
|
+
[hypothesis_output, sul_output]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# rbs_inline: enabled
|
3
|
+
|
4
|
+
module Lernen
|
5
|
+
module Equiv
|
6
|
+
# RandomWalkOracle provides an implementation of equivalence query
|
7
|
+
# that finds a counterexample by using random walk.
|
8
|
+
#
|
9
|
+
# This takes two important parameters:
|
10
|
+
#
|
11
|
+
# - `max_steps` (default: `1500`): It is a limit of steps of a random walk.
|
12
|
+
# If a random walk is tried up to this value and no counterexample is found,
|
13
|
+
# it returns `nil` finally.
|
14
|
+
# - `reset_prob` (default: `0.09`): It is a probability to reset a random walk.
|
15
|
+
# On resetting a random walk, it resets a word, but it does not reset
|
16
|
+
# a step counter.
|
17
|
+
#
|
18
|
+
# @rbs generic In -- Type for input alphabet
|
19
|
+
# @rbs generic Out -- Type for output values
|
20
|
+
class RandomWalkOracle < Oracle #[In, Out]
|
21
|
+
# @rbs @alphabet: Array[In]
|
22
|
+
# @rbs @max_steps: Integer
|
23
|
+
# @rbs @reset_prob: Float
|
24
|
+
# @rbs @random: Random
|
25
|
+
|
26
|
+
#: (
|
27
|
+
# Array[In] alphabet,
|
28
|
+
# System::SUL[In, Out] sul,
|
29
|
+
# ?max_steps: Integer,
|
30
|
+
# ?reset_prob: Float,
|
31
|
+
# ?random: Random
|
32
|
+
# ) -> void
|
33
|
+
def initialize(alphabet, sul, max_steps: 3000, reset_prob: 0.09, random: Random)
|
34
|
+
super(sul)
|
35
|
+
|
36
|
+
@alphabet = alphabet
|
37
|
+
@max_steps = max_steps
|
38
|
+
@reset_prob = reset_prob
|
39
|
+
@random = random
|
40
|
+
end
|
41
|
+
|
42
|
+
# @rbs override
|
43
|
+
def find_cex(hypothesis)
|
44
|
+
super
|
45
|
+
|
46
|
+
reset_internal(hypothesis)
|
47
|
+
word = []
|
48
|
+
|
49
|
+
@max_steps.times do
|
50
|
+
if @random.rand < @reset_prob
|
51
|
+
reset_internal(hypothesis)
|
52
|
+
word = []
|
53
|
+
end
|
54
|
+
|
55
|
+
word << @alphabet.sample(random: @random)
|
56
|
+
|
57
|
+
hypothesis_output, sul_output = step_internal(hypothesis, word.last)
|
58
|
+
|
59
|
+
if hypothesis_output != sul_output # steep:ignore
|
60
|
+
@sul.shutdown
|
61
|
+
return word
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# rbs_inline: enabled
|
3
|
+
|
4
|
+
module Lernen
|
5
|
+
module Equiv
|
6
|
+
# RandomWellMatchedWordOracle provides an implementation of equivalence query
|
7
|
+
# that finds a counterexample by using random well-matched word generation.
|
8
|
+
#
|
9
|
+
# This takes three important parameters:
|
10
|
+
#
|
11
|
+
# - `max_words` (default: `100`): It is a limit of number of random words.
|
12
|
+
# If random words is generated and tried up to this value and no counterexample
|
13
|
+
# is found, it returns `nil` finally.
|
14
|
+
# - `min_word_size` (default: `2`): It is the minimal size of randomly generated word.
|
15
|
+
# It should be greater than `0`.
|
16
|
+
# - `max_word_size` (default: `30`): It is the maximal size of randomly generated word.
|
17
|
+
# It should be greater than or equal to `min_word_size`.
|
18
|
+
# - `call_prob` (default: `0.1`): It is a probability to generate call and return subwords.
|
19
|
+
# - `initial_proc` (default `nil`): It is the initial proc character.
|
20
|
+
# If it is specified, the generated words must be started with it.
|
21
|
+
#
|
22
|
+
# @rbs generic In -- Type for input alphabet
|
23
|
+
# @rbs generic Call -- Type for call alphabet
|
24
|
+
# @rbs generic Return -- Type for return alphabet
|
25
|
+
# @rbs generic Out -- Type for output values
|
26
|
+
class RandomWellMatchedWordOracle < Oracle #[In | Call | Return, Out]
|
27
|
+
# @rbs @alphabet: Array[In]
|
28
|
+
# @rbs @call_alphabet: Array[Call]
|
29
|
+
# @rbs @return_alphabet: Array[Return]
|
30
|
+
# @rbs @max_words: Integer
|
31
|
+
# @rbs @min_word_size: Integer
|
32
|
+
# @rbs @max_word_size: Integer
|
33
|
+
# @rbs @call_prob: Float
|
34
|
+
# @rbs @initial_proc: Call | nil
|
35
|
+
# @rbs @random: Random
|
36
|
+
|
37
|
+
#: (
|
38
|
+
# Array[In] alphabet,
|
39
|
+
# Array[Call] call_alphabet,
|
40
|
+
# Array[Return] return_alphabet,
|
41
|
+
# System::SUL[In | Call | Return, Out] sul,
|
42
|
+
# ?max_words: Integer,
|
43
|
+
# ?min_word_size: Integer,
|
44
|
+
# ?max_word_size: Integer,
|
45
|
+
# ?call_prob: Float,
|
46
|
+
# ?initial_proc: Call | nil,
|
47
|
+
# ?random: Random
|
48
|
+
# ) -> void
|
49
|
+
def initialize(
|
50
|
+
alphabet,
|
51
|
+
call_alphabet,
|
52
|
+
return_alphabet,
|
53
|
+
sul,
|
54
|
+
max_words: 100,
|
55
|
+
min_word_size: 2,
|
56
|
+
max_word_size: 30,
|
57
|
+
call_prob: 0.5,
|
58
|
+
initial_proc: nil,
|
59
|
+
random: Random
|
60
|
+
)
|
61
|
+
super(sul)
|
62
|
+
|
63
|
+
@alphabet = alphabet
|
64
|
+
@call_alphabet = call_alphabet
|
65
|
+
@return_alphabet = return_alphabet
|
66
|
+
@max_words = max_words
|
67
|
+
@min_word_size = min_word_size
|
68
|
+
@max_word_size = max_word_size
|
69
|
+
@call_prob = call_prob
|
70
|
+
@initial_proc = initial_proc
|
71
|
+
@random = random
|
72
|
+
end
|
73
|
+
|
74
|
+
# @rbs override
|
75
|
+
def find_cex(hypothesis)
|
76
|
+
super
|
77
|
+
|
78
|
+
@max_words.times do
|
79
|
+
reset_internal(hypothesis)
|
80
|
+
|
81
|
+
word = generate_word
|
82
|
+
word.each_with_index do |input, index|
|
83
|
+
hypothesis_output, sul_output = step_internal(hypothesis, input)
|
84
|
+
|
85
|
+
if hypothesis_output != sul_output # steep:ignore
|
86
|
+
@sul.shutdown
|
87
|
+
return word[0..index]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
#: () -> Array[In | Call | Return]
|
98
|
+
def generate_word
|
99
|
+
word_size = @random.rand(@min_word_size..@max_word_size)
|
100
|
+
|
101
|
+
word = []
|
102
|
+
initial_proc = @initial_proc
|
103
|
+
if initial_proc
|
104
|
+
word << initial_proc
|
105
|
+
generate_word_internal(word, word_size - 2)
|
106
|
+
word << @return_alphabet.sample(random: @random)
|
107
|
+
return word
|
108
|
+
end
|
109
|
+
|
110
|
+
generate_word_internal(word, word_size)
|
111
|
+
word
|
112
|
+
end
|
113
|
+
|
114
|
+
#: (Array[In | Call | Return] word, Integer word_size) -> void
|
115
|
+
def generate_word_internal(word, word_size)
|
116
|
+
return if word_size <= 0
|
117
|
+
|
118
|
+
if word_size == 1
|
119
|
+
word << @alphabet.sample(random: @random) # steep:ignore
|
120
|
+
return
|
121
|
+
end
|
122
|
+
|
123
|
+
if @random.rand < @call_prob
|
124
|
+
call_index = @random.rand(0...word_size - 1)
|
125
|
+
generate_word_internal(word, call_index)
|
126
|
+
word << @call_alphabet.sample(random: @random) # steep:ignore
|
127
|
+
return_index = call_index + 1 + @random.rand(0...word_size - call_index - 1)
|
128
|
+
generate_word_internal(word, return_index - call_index - 1)
|
129
|
+
word << @return_alphabet.sample(random: @random) # steep:ignore
|
130
|
+
generate_word_internal(word, word_size - return_index - 1)
|
131
|
+
else
|
132
|
+
split_size = @random.rand(1...word_size)
|
133
|
+
generate_word_internal(word, split_size)
|
134
|
+
generate_word_internal(word, word_size - split_size)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# rbs_inline: enabled
|
3
|
+
|
4
|
+
module Lernen
|
5
|
+
module Equiv
|
6
|
+
# RandomWordOracle provides an implementation of equivalence query
|
7
|
+
# that finds a counterexample by using random word generation.
|
8
|
+
#
|
9
|
+
# This takes three important parameters:
|
10
|
+
#
|
11
|
+
# - `max_words` (default: `100`): It is a limit of number of random words.
|
12
|
+
# If random words is generated and tried up to this value and no counterexample
|
13
|
+
# is found, it returns `nil` finally.
|
14
|
+
# - `min_word_size` (default: `1`): It is the minimal size of randomly generated word.
|
15
|
+
# It should be greater than `0`.
|
16
|
+
# - `max_word_size` (default: `30`): It is the maximal size of randomly generated word.
|
17
|
+
# It should be greater than or equal to `min_word_size`.
|
18
|
+
#
|
19
|
+
# @rbs generic In -- Type for input alphabet
|
20
|
+
# @rbs generic Out -- Type for output values
|
21
|
+
class RandomWordOracle < Oracle #[In, Out]
|
22
|
+
# @rbs @alphabet: Array[In]
|
23
|
+
# @rbs @max_word: Integer
|
24
|
+
# @rbs @min_word_size: Integer
|
25
|
+
# @rbs @max_word_size: Integer
|
26
|
+
# @rbs @random: Random
|
27
|
+
|
28
|
+
#: (
|
29
|
+
# Array[In] alphabet,
|
30
|
+
# System::SUL[In, Out] sul,
|
31
|
+
# ?max_words: Integer,
|
32
|
+
# ?min_word_size: Integer,
|
33
|
+
# ?max_word_size: Integer,
|
34
|
+
# ?random: Random,
|
35
|
+
# ) -> void
|
36
|
+
def initialize(alphabet, sul, max_words: 100, min_word_size: 1, max_word_size: 30, random: Random)
|
37
|
+
super(sul)
|
38
|
+
|
39
|
+
@alphabet = alphabet
|
40
|
+
@max_words = max_words
|
41
|
+
@min_word_size = min_word_size
|
42
|
+
@max_word_size = max_word_size
|
43
|
+
@random = random
|
44
|
+
end
|
45
|
+
|
46
|
+
# @rbs override
|
47
|
+
def find_cex(hypothesis)
|
48
|
+
super
|
49
|
+
|
50
|
+
@max_words.times do
|
51
|
+
reset_internal(hypothesis)
|
52
|
+
word = []
|
53
|
+
|
54
|
+
word_size = @random.rand(@min_word_size..@max_word_size)
|
55
|
+
word_size.times do
|
56
|
+
word << @alphabet.sample(random: @random)
|
57
|
+
|
58
|
+
hypothesis_output, sul_output = step_internal(hypothesis, word.last)
|
59
|
+
|
60
|
+
if hypothesis_output != sul_output # steep:ignore
|
61
|
+
@sul.shutdown
|
62
|
+
return word
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# rbs_inline: enabled
|
3
|
+
|
4
|
+
module Lernen
|
5
|
+
module Equiv
|
6
|
+
# SPASimulatorOracle provides an implementation of equivalence query
|
7
|
+
# that finds a counterexample by simulating the SPA.
|
8
|
+
#
|
9
|
+
# @rbs generic In -- Type for input alphabet
|
10
|
+
# @rbs generic Call -- Type for call alphabet
|
11
|
+
# @rbs generic Return -- Type for return alphabet
|
12
|
+
class SPASimulatorOracle < Oracle #[In | Call | Return, bool]
|
13
|
+
# @rbs @alphabet: Array[In]
|
14
|
+
# @rbs @call_alphabet: Array[Call]
|
15
|
+
# @rbs @spa: Automaton::SPA[In, Call, Return]
|
16
|
+
|
17
|
+
#: (
|
18
|
+
# Array[In] alphabet,
|
19
|
+
# Array[Call] call_alphabet,
|
20
|
+
# Automaton::SPA[In, Call, Return] spa,
|
21
|
+
# System::SUL[In | Call | Return, bool] sul
|
22
|
+
# ) -> void
|
23
|
+
def initialize(alphabet, call_alphabet, spa, sul)
|
24
|
+
super(sul)
|
25
|
+
|
26
|
+
@alphabet = alphabet
|
27
|
+
@call_alphabet = call_alphabet
|
28
|
+
@spa = spa
|
29
|
+
end
|
30
|
+
|
31
|
+
# @rbs override
|
32
|
+
def find_cex(hypothesis)
|
33
|
+
super
|
34
|
+
|
35
|
+
Automaton::SPA.find_separating_word(@alphabet, @call_alphabet, @spa, hypothesis) # steep:ignore
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# rbs_inline: enabled
|
3
|
+
|
4
|
+
module Lernen
|
5
|
+
module Equiv
|
6
|
+
# TestWordsOracle provides an implementation of equivalence query
|
7
|
+
# that find a counterexample from the given words.
|
8
|
+
#
|
9
|
+
# @rbs generic In -- Type for input alphabet
|
10
|
+
# @rbs generic Out -- Type for output values
|
11
|
+
class TestWordsOracle < Oracle #[In, Out]
|
12
|
+
# @rbs @words: Array[Array[In]]
|
13
|
+
|
14
|
+
#: (Array[Array[In]] words, System::SUL[In, Out] sul) -> void
|
15
|
+
def initialize(words, sul)
|
16
|
+
super(sul)
|
17
|
+
|
18
|
+
@words = words
|
19
|
+
end
|
20
|
+
|
21
|
+
# @rbs override
|
22
|
+
def find_cex(hypothesis)
|
23
|
+
super
|
24
|
+
|
25
|
+
@words.each do |word|
|
26
|
+
reset_internal(hypothesis)
|
27
|
+
|
28
|
+
word.each_with_index do |input, index|
|
29
|
+
hypothesis_output, sul_output = step_internal(hypothesis, input)
|
30
|
+
|
31
|
+
if hypothesis_output != sul_output # steep:ignore
|
32
|
+
@sul.shutdown
|
33
|
+
return word[0..index]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# rbs_inline: enabled
|
3
|
+
|
4
|
+
module Lernen
|
5
|
+
module Equiv
|
6
|
+
# TransitionSystemSimulatorOracle provides an implementation of equivalence query
|
7
|
+
# that finds a counterexample by simulating the transition system.
|
8
|
+
#
|
9
|
+
# @rbs generic Conf -- Type for a configuration of this automaton
|
10
|
+
# @rbs generic In -- Type for input alphabet
|
11
|
+
# @rbs generic Out -- Type for output values
|
12
|
+
class TransitionSystemSimulatorOracle < Oracle #[In, Out]
|
13
|
+
# @rbs @alphabet: Array[In]
|
14
|
+
# @rbs @automaton: Automaton::TransitionSystem[Conf, In, Out]
|
15
|
+
|
16
|
+
#: (
|
17
|
+
# Array[In] alphabet,
|
18
|
+
# Automaton::TransitionSystem[Conf, In, Out] spa,
|
19
|
+
# System::SUL[In, Out] sul
|
20
|
+
# ) -> void
|
21
|
+
def initialize(alphabet, automaton, sul)
|
22
|
+
super(sul)
|
23
|
+
|
24
|
+
@alphabet = alphabet
|
25
|
+
@automaton = automaton
|
26
|
+
end
|
27
|
+
|
28
|
+
# @rbs override
|
29
|
+
def find_cex(hypothesis)
|
30
|
+
super
|
31
|
+
|
32
|
+
Automaton::TransitionSystem.find_separating_word(@alphabet, @automaton, hypothesis)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# rbs_inline: enabled
|
3
|
+
|
4
|
+
module Lernen
|
5
|
+
module Equiv
|
6
|
+
# VPASimulatorOracle provides an implementation of equivalence query
|
7
|
+
# that finds a counterexample by simulating the VPA.
|
8
|
+
#
|
9
|
+
# @rbs generic In -- Type for input alphabet
|
10
|
+
# @rbs generic Call -- Type for call alphabet
|
11
|
+
# @rbs generic Return -- Type for return alphabet
|
12
|
+
class VPASimulatorOracle < Oracle #[In | Call | Return, bool]
|
13
|
+
# @rbs @alphabet: Array[In]
|
14
|
+
# @rbs @call_alphabet: Array[Call]
|
15
|
+
# @rbs @return_alphabet: Array[Return]
|
16
|
+
# @rbs @spa: Automaton::VPA[In, Call, Return]
|
17
|
+
|
18
|
+
#: (
|
19
|
+
# Array[In] alphabet,
|
20
|
+
# Array[Call] call_alphabet,
|
21
|
+
# Array[Return] return_alphabet,
|
22
|
+
# Automaton::VPA[In, Call, Return] vpa,
|
23
|
+
# System::SUL[In | Call | Return, bool] sul
|
24
|
+
# ) -> void
|
25
|
+
def initialize(alphabet, call_alphabet, return_alphabet, vpa, sul)
|
26
|
+
super(sul)
|
27
|
+
|
28
|
+
@alphabet = alphabet
|
29
|
+
@call_alphabet = call_alphabet
|
30
|
+
@return_alphabet = return_alphabet
|
31
|
+
@vpa = vpa
|
32
|
+
end
|
33
|
+
|
34
|
+
# @rbs override
|
35
|
+
def find_cex(hypothesis)
|
36
|
+
super
|
37
|
+
|
38
|
+
Automaton::VPA.find_separating_word(
|
39
|
+
@alphabet,
|
40
|
+
@call_alphabet,
|
41
|
+
@return_alphabet,
|
42
|
+
@vpa,
|
43
|
+
hypothesis # steep:ignore
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/lernen/equiv.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# rbs_inline: enabled
|
3
|
+
|
4
|
+
module Lernen
|
5
|
+
# This is a namespace for equivalence query oracles.
|
6
|
+
#
|
7
|
+
# A equivalence query check the given hypothesis automaton is equivalence
|
8
|
+
# to a SUL. If that is not, it returns a counterexample, which leads
|
9
|
+
# different output values between the hypothesis and the SUL.
|
10
|
+
module Equiv
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
require "lernen/equiv/oracle"
|
15
|
+
|
16
|
+
require "lernen/equiv/combined_oracle"
|
17
|
+
require "lernen/equiv/exhaustive_search_oracle"
|
18
|
+
require "lernen/equiv/test_words_oracle"
|
19
|
+
require "lernen/equiv/random_walk_oracle"
|
20
|
+
require "lernen/equiv/random_word_oracle"
|
21
|
+
require "lernen/equiv/random_well_matched_word_oracle"
|
22
|
+
require "lernen/equiv/transition_system_simulator_oracle"
|
23
|
+
require "lernen/equiv/moore_like_simulator_oracle"
|
24
|
+
require "lernen/equiv/vpa_simulator_oracle"
|
25
|
+
require "lernen/equiv/spa_simulator_oracle"
|