@@ -33,7 +33,7 @@ def i_star(alphabet, max_seq_len):
3333 return chain (* (product_with_possible_empty_iterable (alphabet , repeat = i ) for i in range (max_seq_len )))
3434
3535
36- def second_phase_it (hyp , alphabet , difference , middle ):
36+ def second_phase_test_case_generator (hyp , alphabet , difference , middle ):
3737 """
3838 Return an iterator that generates all possible sequences for the second phase of the Wp-method.
3939 Args:
@@ -50,7 +50,7 @@ def second_phase_it(hyp, alphabet, difference, middle):
5050 state_mapping [state ] = state_characterization_set (hyp , alphabet , state )
5151
5252 for sm in state_mapping [state ]:
53- yield ( t ,) + ( mid ,) + ( sm ,)
53+ yield t + mid + sm
5454
5555
5656class WpMethodEqOracle (Oracle ):
@@ -63,6 +63,21 @@ def __init__(self, alphabet: list, sul: SUL, max_number_of_states=4):
6363 self .m = max_number_of_states
6464 self .cache = set ()
6565
66+ def test_sequance (self , hypothesis , seq_under_test ):
67+ self .reset_hyp_and_sul (hypothesis )
68+
69+ for ind , letter in enumerate (seq_under_test ):
70+ out_hyp = hypothesis .step (letter )
71+ out_sul = self .sul .step (letter )
72+ self .num_steps += 1
73+
74+ if out_hyp != out_sul :
75+ self .sul .post ()
76+ return seq_under_test [: ind + 1 ]
77+ self .cache .add (seq_under_test )
78+
79+ return None
80+
6681 def find_cex (self , hypothesis ):
6782 if not hypothesis .characterization_set :
6883 hypothesis .characterization_set = hypothesis .compute_characterization_set ()
@@ -80,27 +95,26 @@ def find_cex(self, hypothesis):
8095 middle_1 , middle_2 = tee (i_star (self .alphabet , self .m - hypothesis .size + 1 ), 2 )
8196
8297 # first phase State Cover * Middle * Characterization Set
83- first_phase = product_with_possible_empty_iterable (state_cover , middle_1 , hypothesis .characterization_set )
98+ state_cover = state_cover or [()]
99+ char_set = hypothesis .characterization_set or [()]
100+
101+ for sc in state_cover :
102+ for m in middle_1 :
103+ for cs in char_set :
104+ test_seq = sc + m + cs
105+ if test_seq not in self .cache :
106+ counterexample = self .test_sequance (hypothesis , test_seq )
107+ if counterexample :
108+ return counterexample
84109
85110 # second phase (Transition Cover - State Cover) * Middle * Characterization Set
86111 # of the state that the prefix leads to
87- second_phase = second_phase_it (hypothesis , self .alphabet , difference , middle_2 )
88- test_suite = chain (first_phase , second_phase )
89-
90- for seq in test_suite :
91- seq = tuple ([i for sub in seq for i in sub ])
92-
93- if seq not in self .cache :
94- self .reset_hyp_and_sul (hypothesis )
95-
96- for ind , letter in enumerate (seq ):
97- out_hyp = hypothesis .step (letter )
98- out_sul = self .sul .step (letter )
99- self .num_steps += 1
112+ second_phase = second_phase_test_case_generator (hypothesis , self .alphabet , difference , middle_2 )
100113
101- if out_hyp != out_sul :
102- self .sul .post ()
103- return seq [: ind + 1 ]
104- self .cache .add (seq )
114+ for test_seq in second_phase :
115+ if test_seq not in self .cache :
116+ counterexample = self .test_sequance (hypothesis , test_seq )
117+ if counterexample :
118+ return counterexample
105119
106120 return None
0 commit comments