def minimize_counterexample_normal(hypothesis, system, ctx): reset = [] current_state = hypothesis.init_state current_clock = 0 LTWs = [] for tw in ctx: current_clock = current_clock + tw.time LTWs.append(TimedWord(tw.action, current_clock)) for tran in hypothesis.trans: if current_state == tran.source and tran.is_passing_tran(TimedWord(tw.action, current_clock)): reset.append(tran.reset) current_state = tran.target if tran.reset: current_clock = 0 break for i in range(len(LTWs)): while True: if i == 0 or reset[i - 1]: can_reduce = (LTWs[i].time > 0) else: can_reduce = (LTWs[i].time > LTWs[i - 1].time) if not can_reduce: break LTWs_temp = copy.deepcopy(LTWs) LTWs_temp[i] = TimedWord(LTWs[i].action, one_lower(LTWs[i].time)) flag, ctx = is_counterexample_normal(hypothesis, system, LTW_to_DTW(LTWs_temp, reset)) if not flag: break LTWs = LTWs_temp return LTW_to_DTW(LTWs, reset)
def is_consistent(self): flag = True consistent_add = [] table_element = [s for s in self.S] + [r for r in self.R] for i in range(0, len(table_element) - 1): for j in range(i + 1, len(table_element)): if table_element[i].values == table_element[j].values and table_element[i].suffixes_resets == table_element[j].suffixes_resets: temp_elements1 = [] temp_elements2 = [] for element in table_element: if is_prefix(element.LRTWs, table_element[i].LRTWs): temp_elements1.append(element) if is_prefix(element.LRTWs, table_element[j].LRTWs): temp_elements2.append(element) for e1 in temp_elements1: for e2 in temp_elements2: newLRTWs1 = delete_prefix(e1.LRTWs, table_element[i].LRTWs) newLRTWs2 = delete_prefix(e2.LRTWs, table_element[j].LRTWs) if len(newLRTWs1) == len(newLRTWs2) == 1: if newLRTWs1[0].action == newLRTWs2[0].action and newLRTWs1[0].time == newLRTWs2[0].time: if newLRTWs1[0].reset != newLRTWs2[0].reset: flag = False consistent_add = [TimedWord(newLRTWs1[0].action, newLRTWs1[0].time)] return flag, consistent_add if e1.values != e2.values or e1.suffixes_resets != e2.suffixes_resets: flag = False for k in range(0, len(e1.values)): if e1.values[k] != e2.values[k] or e1.suffixes_resets[k] != e2.suffixes_resets[k]: new_index = k consistent_add = [TimedWord(newLRTWs1[0].action, newLRTWs1[0].time)] + self.E[new_index] return flag, consistent_add return flag, consistent_add
def LTW_to_DTW(LTWs, reset): DTWs = [] for j in range(len(LTWs)): if j == 0 or reset[j - 1]: DTWs.append(TimedWord(LTWs[j].action, LTWs[j].time)) else: DTWs.append(TimedWord(LTWs[j].action, LTWs[j].time - LTWs[j - 1].time)) return DTWs
def test_DTWs_normal(self, DTWs): outputs = [] now_time = 0 cur_state = self.init_state for dtw in DTWs: if cur_state == self.sink_state: outputs.append(-1) else: time = dtw.time + now_time new_LTW = TimedWord(dtw.action, time) for tran in self.trans: if tran.source == cur_state and tran.is_passing_tran( new_LTW): cur_state = tran.target if tran.reset: now_time = 0 else: now_time = time break if cur_state in self.accept_states: outputs.append(1) elif cur_state == self.sink_state: outputs.append(-1) else: outputs.append(0) return outputs
def minimize_counterexample(hypothesis, system, ctx): # Find sequence of reset information reset = [] DRTWs, outputs = system.test_DTWs(ctx) for drtw in DRTWs: reset.append(drtw.reset) # ctx to LTWs LTWs = LRTW_to_LTW(DRTW_to_LRTW(DRTWs)) # start minimize for i in range(len(LTWs)): while True: if i == 0 or reset[i - 1]: can_reduce = (LTWs[i].time > 0) else: can_reduce = (LTWs[i].time > LTWs[i - 1].time) if not can_reduce: break LTWs_temp = copy.deepcopy(LTWs) LTWs_temp[i] = TimedWord(LTWs[i].action, one_lower(LTWs[i].time)) flag, ctx = is_counterexample(hypothesis, system, LTW_to_DTW(LTWs_temp, reset)) if not flag: break LTWs = copy.deepcopy(LTWs_temp) return LTW_to_DTW(LTWs, reset)
def find_DTWs(letterword): path = find_path(letterword) DTWs = [] current_clock_valuation = 0 delay_time = 0 for letterword in path: if len(letterword.lw) == 1: letter1, letter2 = list(letterword.lw[0]) elif len(letterword.lw) == 2: letter1, letter2 = list(letterword.lw[0])[0], list( letterword.lw[1])[0] else: raise NotImplementedError() if letter1.flag == 'A': # "A" or "B"? temp_region = letter1.guard else: temp_region = letter2.guard if letterword.action == "DELAY": delay_time = minimum_in_region( temp_region) - current_clock_valuation current_clock_valuation = minimum_in_region(temp_region) elif letterword.action == 'INIT': pass else: new_timedword = TimedWord(letterword.action, delay_time) DTWs.append(new_timedword) current_clock_valuation = minimum_in_region(temp_region) return DTWs
def test_DTW_normal(self, DTW, now_time, cur_state): value = None reset = False tran_flag = False # tranFlag为true表示有这样的迁移 if DTW is None: if cur_state in self.accept_states: value = 1 else: value = 0 else: LTW = TimedWord(DTW.action, DTW.time + now_time) for tran in self.trans: if tran.source == cur_state and tran.is_passing_tran(LTW): tran_flag = True cur_state = tran.target if tran.reset: reset = True break if not tran_flag: value = -1 cur_state = 'sink' reset = True if cur_state in self.accept_states: value = 1 elif cur_state != 'sink': value = 0 return cur_state, value, reset
def test_DTWs(self, DTWs): DRTWs = [] now_time = 0 cur_state = self.init_state for dtw in DTWs: if cur_state == self.sink_state: DRTWs.append(ResetTimedWord(dtw.action, dtw.time, True)) else: time = dtw.time + now_time new_LTW = TimedWord(dtw.action, time) for tran in self.trans: if tran.source == cur_state and tran.is_passing_tran( new_LTW): cur_state = tran.target if tran.reset: now_time = 0 reset = True else: now_time = time reset = False DRTWs.append( ResetTimedWord(dtw.action, dtw.time, reset)) break if cur_state in self.accept_states: value = 1 elif cur_state == self.sink_state: value = -1 else: value = 0 return DRTWs, value
def test_DTWs_normal(self, DTWs, is_mq=False): if is_mq: self.mq_num += 1 else: self.test_num += 1 value = 0 now_time = 0 cur_state = self.init_state for dtw in DTWs: time = dtw.time + now_time new_LTW = TimedWord(dtw.action, time) flag = False for tran in self.trans: if tran.source == cur_state and tran.is_passing_tran(new_LTW): flag = True cur_state = tran.target if tran.reset: now_time = 0 else: now_time = time break if not flag: value = -1 break if value != -1: if cur_state in self.accept_states: value = 1 else: value = 0 return value
def init_table_normal(actions, system): if system.init_state in system.accept_states: init_value = 1 else: init_value = 0 S = [Element([], [init_value], [[]])] R = [] E = [[]] tables = [ObsTable(S, R, E, parent=-1, reason="init")] for i in range(0, len(actions)): temp_tables = [] for table in tables: new_DTWs = [TimedWord(actions[i], 0)] # 同样也是LTWs outputs = system.test_DTWs_normal(new_DTWs, True) if outputs[-1] == -1: # now at sink guesses = [True] else: guesses = [True, False] for guess in guesses: new_LRTWs = [ ResetTimedWord(new_DTWs[0].action, new_DTWs[0].time, guess) ] new_element = Element(new_LRTWs, [outputs[-1]], [[]]) temp_R = table.R + [new_element] new_table = ObsTable(deepcopy(S), deepcopy(temp_R), deepcopy(E), parent=-1, reason="init") temp_tables.append(new_table) tables = temp_tables return tables
def sample_generation_main_old_1(actions, upperGuard, stateNum): sample = [] length = random.randint(1, stateNum * 2) for i in range(length): action = actions[random.randint(0, len(actions) - 1)] time = random.randint(0, upperGuard * 2 + 1) if time % 2 == 0: time = time // 2 else: time = time // 2 + 0.5 temp = TimedWord(action, time) sample.append(temp) return sample
def extend_R(s, actions, table, system): table_LRTWS = [s.LRTWs for s in table.S] + [r.LRTWs for r in table.R] for action in actions: LTWs = LRTW_to_LTW(s.LRTWs) + [TimedWord(action, 0)] LRTWs, value = TQs(LTWs, system) system.mq_num -= 1 if value == -1: element = fill_table_row(LRTWs, table, True, system) else: element = fill_table_row(LRTWs, table, False, system) if element.LRTWs not in table_LRTWS: table.R.append(element) return table
def sample_generation_custom(upper_guard, length, system): # 注意,通用采样情况下测试集可能是无效的,也就是可能会到达sink状态 sample = None while sample is None: sample = sample_generation_valid(upper_guard, length, system) action = random.choice(system.actions) time = random.randint(0, upper_guard * 3 + 1) if time % 2 == 0: time = time // 2 else: time = time // 2 + 0.5 index = random.randint(0, len(sample) - 1) sample[index] = TimedWord(action, time) # 随机替换其中一个 return sample
def test_DTWs(self, DTWs): self.test_num += 1 tuple_DTWs = tuple(DTWs) if tuple_DTWs in self.cache: return self.cache[tuple_DTWs][0], self.cache[tuple_DTWs][1] self.test_num_cache += 1 DRTWs = [] outputs = [] now_time = 0 cur_state = self.init_state for dtw in DTWs: self.action_num += 1 time = dtw.time + now_time new_LTW = TimedWord(dtw.action, time) flag = False for tran in self.trans: if tran.source == cur_state and tran.is_passing_tran(new_LTW): flag = True cur_state = tran.target if tran.reset: now_time = 0 reset = True else: now_time = time reset = False DRTWs.append(ResetTimedWord(dtw.action, dtw.time, reset)) if cur_state in self.accept_states: outputs.append(1) else: outputs.append(0) break if not flag: DRTWs.append(ResetTimedWord(dtw.action, dtw.time, True)) outputs.append(-1) break # 补全 len_diff = len(DTWs) - len(DRTWs) if len_diff != 0: temp = DTWs[len(DRTWs):] for i in temp: DRTWs.append(ResetTimedWord(i.action, i.time, True)) outputs.append(-1) self.cache[tuple_DTWs] = [DRTWs, outputs] return DRTWs, outputs
def test_DTWs_normal(self, DTWs): now_time = 0 cur_state = self.init_state for dtw in DTWs: time = dtw.time + now_time new_LTW = TimedWord(dtw.action, time) for tran in self.trans: if tran.source == cur_state and tran.is_passing_tran(new_LTW): cur_state = tran.target if tran.reset: now_time = 0 else: now_time = time if cur_state == self.sink_state: return -1 break if cur_state in self.accept_states: value = 1 else: value = 0 return value
def test_LTWs(self, LTWs): self.mq_num += 1 if not LTWs: if self.init_state in self.accept_states: value = 1 else: value = 0 return [], value else: LRTWs = [] value = None now_time = 0 cur_state = self.init_state for ltw in LTWs: if ltw.time < now_time: value = -1 LRTWs.append(ResetTimedWord(ltw.action, ltw.time, True)) break else: DTW = TimedWord(ltw.action, ltw.time - now_time) cur_state, value, reset = self.test_DTW( DTW, now_time, cur_state) if reset: LRTWs.append(ResetTimedWord(ltw.action, ltw.time, True)) now_time = 0 else: LRTWs.append( ResetTimedWord(ltw.action, ltw.time, False)) now_time = ltw.time if value == -1: break # 补全 len_diff = len(LTWs) - len(LRTWs) if len_diff != 0: temp = LTWs[len(LRTWs):] for i in temp: LRTWs.append(ResetTimedWord(i.action, i.time, True)) return LRTWs, value
def test_DTWs_normal(self, DTWs, is_mq=False): tuple_DTWs = tuple(DTWs) if is_mq: self.mq_num += 1 else: self.test_num += 1 if tuple_DTWs in self.cache: return self.cache[tuple_DTWs][0] self.test_num_cache += 1 outputs = [] now_time = 0 cur_state = self.init_state for dtw in DTWs: self.action_num += 1 time = dtw.time + now_time new_LTW = TimedWord(dtw.action, time) flag = False for tran in self.trans: if tran.source == cur_state and tran.is_passing_tran(new_LTW): flag = True cur_state = tran.target if tran.reset: now_time = 0 else: now_time = time break if not flag: outputs.append(-1) break if cur_state in self.accept_states: outputs.append(1) else: outputs.append(0) # 补全 len_diff = len(DTWs) - len(outputs) if len_diff != 0: outputs.extend([-1] * len_diff) self.cache[tuple_DTWs] = [outputs] return outputs
def test_DTWs(self, DTWs): self.test_num += 1 DRTWs = [] value = None now_time = 0 cur_state = self.init_state for dtw in DTWs: time = dtw.time + now_time new_LTW = TimedWord(dtw.action, time) flag = False for tran in self.trans: if tran.source == cur_state and tran.is_passing_tran(new_LTW): flag = True cur_state = tran.target if tran.reset: now_time = 0 reset = True else: now_time = time reset = False DRTWs.append(ResetTimedWord(dtw.action, dtw.time, reset)) break if not flag: DRTWs.append(ResetTimedWord(dtw.action, dtw.time, True)) value = -1 break # 补全 len_diff = len(DTWs) - len(DRTWs) if len_diff != 0: temp = DTWs[len(DRTWs):] for i in temp: DRTWs.append(ResetTimedWord(i.action, i.time, True)) if value != -1: if cur_state in self.accept_states: value = 1 else: value = 0 return DRTWs, value
def is_consistent(self): flag = True e_index = 0 prefix_LTWs = [] reset_i = [] reset_j = [] index_i = 0 index_j = 0 table_element = [s for s in self.S] + [r for r in self.R] for i in range(0, len(table_element) - 1): for j in range(i + 1, len(table_element)): if table_element[i].values == table_element[ j].values and table_element[ i].suffixes_resets == table_element[ j].suffixes_resets: temp_elements1 = [] temp_elements2 = [] for element in table_element: if is_prefix(element.LRTWs, table_element[i].LRTWs): temp_elements1.append(element) if is_prefix(element.LRTWs, table_element[j].LRTWs): temp_elements2.append(element) for e1 in temp_elements1: for e2 in temp_elements2: newLRTWs1 = delete_prefix(e1.LRTWs, table_element[i].LRTWs) newLRTWs2 = delete_prefix(e2.LRTWs, table_element[j].LRTWs) if len(newLRTWs1) == len(newLRTWs2) == 1: if newLRTWs1[0].action == newLRTWs2[ 0].action and newLRTWs1[ 0].time == newLRTWs2[0].time: if newLRTWs1[0].reset != newLRTWs2[0].reset: flag = False e_index = 0 prefix_LTWs = [ TimedWord(newLRTWs1[0].action, newLRTWs1[0].time) ] reset_i = [newLRTWs1[0].reset] reset_j = [newLRTWs2[0].reset] index_i = i index_j = j return flag, prefix_LTWs, e_index, reset_i, reset_j, index_i, index_j if e1.values != e2.values or e1.suffixes_resets != e2.suffixes_resets: flag = False prefix_LTWs = [ TimedWord(newLRTWs1[0].action, newLRTWs1[0].time) ] for k in range(0, len(e1.values)): if e1.values[k] != e2.values[ k] or e1.suffixes_resets != e2.suffixes_resets: e_index = k reset_i = [ newLRTWs1[0].reset ] + table_element[ i].suffixes_resets[k] reset_j = [ newLRTWs2[0].reset ] + table_element[ j].suffixes_resets[k] index_i = i index_j = j return flag, prefix_LTWs, e_index, reset_i, reset_j, index_i, index_j return flag, prefix_LTWs, e_index, reset_i, reset_j, index_i, index_j
def sample_generation_valid(upper_guard, length, system): # First produce a path (as a list of transitions) in the OTA path = [] cur_state = system.init_state for i in range(length): edges = [] for tran in system.trans: if cur_state == tran.source: edges.append(tran) edge = random.choice(edges) path.append(edge) cur_state = edge.target # Next, figure out (double of) the minimum and maximum logical time of each edge in path. min_time, max_time = [], [] for tran in path: min_time.append(min_constraint_double(tran.guards[0])) max_time.append(max_constraint_double(tran.guards[0], upper_guard)) # For each transition, maintain a mapping from logical time to the number of choices. weight = dict() for i in reversed(range(length)): tran = path[i] min_value, max_value = min_time[i], max_time[i] weight[i] = dict() if i == length - 1 or tran.reset: for j in range(min_value, max_value + 1): weight[i][j] = 1 else: for j in range(min_value, max_value + 1): weight[i][j] = 0 for k, w in weight[i + 1].items(): if k >= j: weight[i][j] += w # Now sample according to the weights double_times = [] cur_time = 0 for i in range(length): start_time = max(min_time[i], cur_time) distr = [] for j in range(start_time, max_time[i] + 1): distr.append(weight[i][j]) if sum(distr) == 0: return None # sampling failed cur_time = sample_distribution(distr) + start_time double_times.append(cur_time) if path[i].reset: cur_time = 0 # Finally, change doubled time to fractions. ltw = [] for i in range(length): if double_times[i] % 2 == 0: time = double_times[i] // 2 else: time = double_times[i] // 2 + 0.5 ltw.append(TimedWord(path[i].action, time)) # Convert logical-timed word to delayed-timed word. dtw = [] for i in range(length): if i == 0 or path[i - 1].reset: dtw.append(TimedWord(path[i].action, ltw[i].time)) else: dtw.append(TimedWord(path[i].action, ltw[i].time - ltw[i - 1].time)) return dtw