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.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +15 -0
  3. data/README.md +534 -48
  4. data/Rakefile +26 -7
  5. data/Steepfile +14 -0
  6. data/examples/ripper_prism.rb +63 -0
  7. data/examples/uri_parse_regexp.rb +73 -0
  8. data/lib/lernen/algorithm/cex_processor/acex.rb +43 -0
  9. data/lib/lernen/algorithm/cex_processor/prefix_transformer_acex.rb +43 -0
  10. data/lib/lernen/algorithm/cex_processor.rb +115 -0
  11. data/lib/lernen/algorithm/kearns_vazirani/discrimination_tree.rb +207 -0
  12. data/lib/lernen/algorithm/kearns_vazirani/kearns_vazirani_learner.rb +100 -0
  13. data/lib/lernen/algorithm/kearns_vazirani.rb +44 -0
  14. data/lib/lernen/algorithm/kearns_vazirani_vpa/discrimination_tree_vpa.rb +246 -0
  15. data/lib/lernen/algorithm/kearns_vazirani_vpa/kearns_vazirani_vpa_learner.rb +89 -0
  16. data/lib/lernen/algorithm/kearns_vazirani_vpa.rb +35 -0
  17. data/lib/lernen/algorithm/learner.rb +82 -0
  18. data/lib/lernen/algorithm/lsharp/lsharp_learner.rb +367 -0
  19. data/lib/lernen/algorithm/lsharp/observation_tree.rb +115 -0
  20. data/lib/lernen/algorithm/lsharp.rb +43 -0
  21. data/lib/lernen/algorithm/lstar/lstar_learner.rb +49 -0
  22. data/lib/lernen/algorithm/lstar/observation_table.rb +214 -0
  23. data/lib/lernen/algorithm/lstar.rb +49 -0
  24. data/lib/lernen/algorithm/procedural/atr_manager.rb +200 -0
  25. data/lib/lernen/algorithm/procedural/procedural_learner.rb +223 -0
  26. data/lib/lernen/algorithm/procedural/procedural_sul.rb +47 -0
  27. data/lib/lernen/algorithm/procedural/return_indices_acex.rb +58 -0
  28. data/lib/lernen/algorithm/procedural.rb +57 -0
  29. data/lib/lernen/algorithm.rb +19 -0
  30. data/lib/lernen/automaton/dfa.rb +204 -0
  31. data/lib/lernen/automaton/mealy.rb +108 -0
  32. data/lib/lernen/automaton/moore.rb +122 -0
  33. data/lib/lernen/automaton/moore_like.rb +83 -0
  34. data/lib/lernen/automaton/proc_util.rb +93 -0
  35. data/lib/lernen/automaton/spa.rb +368 -0
  36. data/lib/lernen/automaton/transition_system.rb +209 -0
  37. data/lib/lernen/automaton/vpa.rb +300 -0
  38. data/lib/lernen/automaton.rb +19 -493
  39. data/lib/lernen/equiv/combined_oracle.rb +57 -0
  40. data/lib/lernen/equiv/exhaustive_search_oracle.rb +60 -0
  41. data/lib/lernen/equiv/moore_like_simulator_oracle.rb +36 -0
  42. data/lib/lernen/equiv/oracle.rb +109 -0
  43. data/lib/lernen/equiv/random_walk_oracle.rb +69 -0
  44. data/lib/lernen/equiv/random_well_matched_word_oracle.rb +139 -0
  45. data/lib/lernen/equiv/random_word_oracle.rb +71 -0
  46. data/lib/lernen/equiv/spa_simulator_oracle.rb +39 -0
  47. data/lib/lernen/equiv/test_words_oracle.rb +42 -0
  48. data/lib/lernen/equiv/transition_system_simulator_oracle.rb +36 -0
  49. data/lib/lernen/equiv/vpa_simulator_oracle.rb +48 -0
  50. data/lib/lernen/equiv.rb +25 -0
  51. data/lib/lernen/graph.rb +215 -0
  52. data/lib/lernen/system/block_sul.rb +41 -0
  53. data/lib/lernen/system/moore_like_simulator.rb +45 -0
  54. data/lib/lernen/system/moore_like_sul.rb +33 -0
  55. data/lib/lernen/system/sul.rb +126 -0
  56. data/lib/lernen/system/transition_system_simulator.rb +40 -0
  57. data/lib/lernen/system.rb +72 -0
  58. data/lib/lernen/version.rb +2 -1
  59. data/lib/lernen.rb +284 -34
  60. data/rbs_collection.lock.yaml +16 -0
  61. data/rbs_collection.yaml +14 -0
  62. data/renovate.json +6 -0
  63. data/sig/generated/lernen/algorithm/cex_processor/acex.rbs +30 -0
  64. data/sig/generated/lernen/algorithm/cex_processor/prefix_transformer_acex.rbs +27 -0
  65. data/sig/generated/lernen/algorithm/cex_processor.rbs +59 -0
  66. data/sig/generated/lernen/algorithm/kearns_vazirani/discrimination_tree.rbs +68 -0
  67. data/sig/generated/lernen/algorithm/kearns_vazirani/kearns_vazirani_learner.rbs +51 -0
  68. data/sig/generated/lernen/algorithm/kearns_vazirani.rbs +32 -0
  69. data/sig/generated/lernen/algorithm/kearns_vazirani_vpa/discrimination_tree_vpa.rbs +73 -0
  70. data/sig/generated/lernen/algorithm/kearns_vazirani_vpa/kearns_vazirani_vpa_learner.rbs +51 -0
  71. data/sig/generated/lernen/algorithm/kearns_vazirani_vpa.rbs +20 -0
  72. data/sig/generated/lernen/algorithm/learner.rbs +53 -0
  73. data/sig/generated/lernen/algorithm/lsharp/lsharp_learner.rbs +103 -0
  74. data/sig/generated/lernen/algorithm/lsharp/observation_tree.rbs +53 -0
  75. data/sig/generated/lernen/algorithm/lsharp.rbs +38 -0
  76. data/sig/generated/lernen/algorithm/lstar/lstar_learner.rbs +38 -0
  77. data/sig/generated/lernen/algorithm/lstar/observation_table.rbs +79 -0
  78. data/sig/generated/lernen/algorithm/lstar.rbs +37 -0
  79. data/sig/generated/lernen/algorithm/procedural/atr_manager.rbs +80 -0
  80. data/sig/generated/lernen/algorithm/procedural/procedural_learner.rbs +79 -0
  81. data/sig/generated/lernen/algorithm/procedural/procedural_sul.rbs +36 -0
  82. data/sig/generated/lernen/algorithm/procedural/return_indices_acex.rbs +33 -0
  83. data/sig/generated/lernen/algorithm/procedural.rbs +27 -0
  84. data/sig/generated/lernen/algorithm.rbs +10 -0
  85. data/sig/generated/lernen/automaton/dfa.rbs +93 -0
  86. data/sig/generated/lernen/automaton/mealy.rbs +61 -0
  87. data/sig/generated/lernen/automaton/moore.rbs +69 -0
  88. data/sig/generated/lernen/automaton/moore_like.rbs +63 -0
  89. data/sig/generated/lernen/automaton/proc_util.rbs +38 -0
  90. data/sig/generated/lernen/automaton/spa.rbs +125 -0
  91. data/sig/generated/lernen/automaton/transition_system.rbs +108 -0
  92. data/sig/generated/lernen/automaton/vpa.rbs +109 -0
  93. data/sig/generated/lernen/automaton.rbs +15 -0
  94. data/sig/generated/lernen/equiv/combined_oracle.rbs +27 -0
  95. data/sig/generated/lernen/equiv/exhaustive_search_oracle.rbs +38 -0
  96. data/sig/generated/lernen/equiv/moore_like_simulator_oracle.rbs +27 -0
  97. data/sig/generated/lernen/equiv/oracle.rbs +75 -0
  98. data/sig/generated/lernen/equiv/random_walk_oracle.rbs +41 -0
  99. data/sig/generated/lernen/equiv/random_well_matched_word_oracle.rbs +70 -0
  100. data/sig/generated/lernen/equiv/random_word_oracle.rbs +45 -0
  101. data/sig/generated/lernen/equiv/spa_simulator_oracle.rbs +30 -0
  102. data/sig/generated/lernen/equiv/test_words_oracle.rbs +20 -0
  103. data/sig/generated/lernen/equiv/transition_system_simulator_oracle.rbs +27 -0
  104. data/sig/generated/lernen/equiv/vpa_simulator_oracle.rbs +33 -0
  105. data/sig/generated/lernen/equiv.rbs +11 -0
  106. data/sig/generated/lernen/graph.rbs +80 -0
  107. data/sig/generated/lernen/system/block_sul.rbs +29 -0
  108. data/sig/generated/lernen/system/moore_like_simulator.rbs +31 -0
  109. data/sig/generated/lernen/system/moore_like_sul.rbs +28 -0
  110. data/sig/generated/lernen/system/sul.rbs +87 -0
  111. data/sig/generated/lernen/system/transition_system_simulator.rbs +28 -0
  112. data/sig/generated/lernen/system.rbs +62 -0
  113. data/sig/generated/lernen/version.rbs +6 -0
  114. data/sig/generated/lernen.rbs +214 -0
  115. data/sig-test/generated/test/example_test.rbs +14 -0
  116. data/sig-test/generated/test/lernen/algorithm/kearns_vazirani_test.rbs +16 -0
  117. data/sig-test/generated/test/lernen/algorithm/kearns_vazirani_vpa_test.rbs +10 -0
  118. data/sig-test/generated/test/lernen/algorithm/lsharp_test.rbs +16 -0
  119. data/sig-test/generated/test/lernen/algorithm/lstar_test.rbs +16 -0
  120. data/sig-test/generated/test/lernen/algorithm/procedural_test.rbs +10 -0
  121. data/sig-test/generated/test/lernen/automaton/dfa_test.rbs +19 -0
  122. data/sig-test/generated/test/lernen/automaton/mealy_test.rbs +19 -0
  123. data/sig-test/generated/test/lernen/automaton/moore_test.rbs +19 -0
  124. data/sig-test/generated/test/lernen/automaton/proc_util_test.rbs +19 -0
  125. data/sig-test/generated/test/lernen/automaton/spa_test.rbs +19 -0
  126. data/sig-test/generated/test/lernen/automaton/vpa_test.rbs +19 -0
  127. data/sig-test/generated/test/lernen/equiv/exhaustive_search_oracle_test.rbs +10 -0
  128. data/sig-test/generated/test/lernen/equiv/random_walk_oracle_test.rbs +10 -0
  129. data/sig-test/generated/test/lernen/equiv/random_word_oracle_test.rbs +10 -0
  130. data/sig-test/generated/test/lernen/system/block_sul_test.rbs +16 -0
  131. data/sig-test/generated/test/lernen/system/moore_like_simulator_test.rbs +16 -0
  132. data/sig-test/generated/test/lernen/system/transition_system_simulator_test.rbs +13 -0
  133. data/sig-test/generated/test/lernen/system_test.rbs +11 -0
  134. data/sig-test/generated/test/lernen_test.rbs +13 -0
  135. metadata +131 -11
  136. data/.yardopts +0 -3
  137. data/lib/lernen/cex_processor.rb +0 -92
  138. data/lib/lernen/kearns_vazirani.rb +0 -310
  139. data/lib/lernen/lsharp.rb +0 -344
  140. data/lib/lernen/lstar.rb +0 -170
  141. data/lib/lernen/oracle.rb +0 -119
  142. 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
@@ -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"