Skip to content

Commit 4524d53

Browse files
committed
add test-cases for Moore and DFAs in hW, rename function params
1 parent 0824487 commit 4524d53

2 files changed

Lines changed: 121 additions & 6 deletions

File tree

aalpy/learning_algs/resetless/hW.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -819,8 +819,14 @@ def main_loop(self, print_level=2):
819819
return hypothesis, info
820820

821821

822-
def run_hW(alphabet: list, sul, automaton_type='mealy', num_testing_steps=200, reset_testing_counter=True,
823-
query_for_initial_state=True, H=None, W=None, return_data=False, print_level=2):
822+
def run_hW(alphabet: list, sul, automaton_type='mealy',
823+
num_testing_steps=200,
824+
reset_testing_counter=True,
825+
query_for_initial_state=True,
826+
provided_homing_sequence=None,
827+
provided_characterization_set=None,
828+
return_data=False,
829+
print_level=2):
824830
"""
825831
Executes the hW resetless learning algorithm.
826832
Algorithm description can be found in "hW-inference: A heuristic approach to retrieve models through
@@ -845,10 +851,10 @@ def run_hW(alphabet: list, sul, automaton_type='mealy', num_testing_steps=200, r
845851
846852
query_for_initial_state: if True, query the SUL to identify the true initial state (Default value = True)
847853
848-
H: optional user-provided homing sequence. If supplied, hW starts with this sequence instead of deriving an
854+
provided_homing_sequence: optional user-provided homing sequence. If supplied, hW starts with this sequence instead of deriving an
849855
initial one from the daisy hypothesis counterexample. (Default value = None)
850856
851-
W: optional user-provided characterization set. If supplied, hW starts with these suffixes instead of an empty
857+
provided_characterization_set: optional user-provided characterization set. If supplied, hW starts with these suffixes instead of an empty
852858
characterization set. For Moore machines and DFAs, the empty suffix is added automatically.
853859
(Default value = None)
854860
@@ -873,8 +879,8 @@ def run_hW(alphabet: list, sul, automaton_type='mealy', num_testing_steps=200, r
873879
num_testing_steps=num_testing_steps,
874880
reset_testing_counter=reset_testing_counter,
875881
query_for_initial_state=query_for_initial_state,
876-
H=H,
877-
W=W,
882+
H=provided_homing_sequence,
883+
W=provided_characterization_set,
878884
)
879885

880886
hypothesis, info = hw.main_loop(print_level=print_level)

tests/test_hW_moore_dfa.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import pytest
2+
3+
from aalpy import generate_random_deterministic_automata, bisimilar, run_hW
4+
from aalpy.SULs import MealySUL
5+
6+
SEEDS = list(range(20))
7+
MODEL_SIZES = [
8+
(2, 2, 2),
9+
(2, 2, 3),
10+
(3, 2, 2),
11+
(3, 2, 3),
12+
(3, 3, 2),
13+
(4, 2, 3),
14+
(4, 3, 2),
15+
(5, 3, 3),
16+
(6, 2, 3),
17+
(6, 3, 2),
18+
(10, 2, 3),
19+
(10, 2, 4),
20+
(10, 2, 2),
21+
(10, 2, 3),
22+
(20, 5, 5),
23+
(30, 3, 4),
24+
]
25+
26+
TEST_CASES = [
27+
pytest.param(
28+
automaton_type,
29+
seed_val,
30+
num_states,
31+
input_size,
32+
output_size,
33+
id=f"states={num_states}-inputs={input_size}-outputs={output_size}-seed={seed_val}-automaton_type={automaton_type}",
34+
)
35+
for num_states, input_size, output_size in MODEL_SIZES
36+
for seed_val in SEEDS
37+
for automaton_type in ['dfa', 'moore']
38+
]
39+
40+
41+
@pytest.mark.parametrize("automaton_type,seed_val,num_states,input_size,output_size", TEST_CASES)
42+
@pytest.mark.timeout(5)
43+
def test_hw_seed(automaton_type, seed_val, num_states, input_size, output_size):
44+
from random import seed
45+
46+
seed(seed_val)
47+
48+
model = generate_random_deterministic_automata(
49+
automaton_type,
50+
num_states=num_states,
51+
input_alphabet_size=input_size,
52+
output_alphabet_size=output_size,
53+
)
54+
if not model.is_minimal():
55+
pytest.skip(f"seed {seed_val} does not produce a minimal model")
56+
if not model.is_strongly_connected():
57+
pytest.skip(
58+
f"seed {seed_val} does not produce a strongly connected model "
59+
f"for states={num_states}, inputs={input_size}, outputs={output_size}"
60+
)
61+
62+
sul = MealySUL(model)
63+
input_alphabet = model.get_input_alphabet()
64+
65+
66+
learned_model = run_hW(input_alphabet,
67+
sul,
68+
num_testing_steps=1000 * num_states,
69+
automaton_type=automaton_type,
70+
reset_testing_counter=True,
71+
query_for_initial_state=True)
72+
73+
assert learned_model.is_minimal()
74+
75+
print(learned_model)
76+
print(model)
77+
assert bisimilar(model, learned_model)
78+
79+
80+
def test_hw_uses_user_provided_h_and_w():
81+
from aalpy import bisimilar, generate_random_deterministic_automata, run_hW, AutomatonSUL
82+
from random import seed
83+
seed(1)
84+
85+
model = generate_random_deterministic_automata(
86+
'mealy',
87+
num_states=100,
88+
input_alphabet_size=4,
89+
output_alphabet_size=4,
90+
)
91+
92+
sul = AutomatonSUL(model)
93+
input_alphabet = model.get_input_alphabet()
94+
95+
char_set = model.compute_characterization_set()
96+
97+
assert model.is_minimal() and model.is_minimal()
98+
99+
learned_model = run_hW(input_alphabet,
100+
sul,
101+
automaton_type='mealy',
102+
provided_characterization_set=char_set,
103+
num_testing_steps=2000,
104+
reset_testing_counter=True,
105+
query_for_initial_state=True)
106+
107+
assert learned_model.is_minimal()
108+
assert bisimilar(model, learned_model)
109+

0 commit comments

Comments
 (0)