def generate_basic_traces(folder_name, trace_count, duration): viol_formula = 'x0 < 5' stn_viol = STL.SyntaxTreeNode() stn_viol.initialize_node(viol_formula.split(), 0) tc = 0 while tc < trace_count: f_signal_name = folder_name + "test_" + str(tc) f_label_name = f_signal_name + "_label" f_s = open(f_signal_name, 'w') f_l = open(f_label_name, 'w') time = 0 x = [ random.randint(5, 7) ] # this line is to be uncommented if initial x is wanted to be randomized. #x = [0] while time <= duration: u = [random.choice([-2, 1, 2])] f_s.write( "%s %s %s\n" % (str(time), " ".join([str(x[0])]), " ".join([str(u[0])]))) stn_viol.compute_qv(STL.DataPoint(value=x + u, time=time)) qual = 1 if stn_viol.qv < 0 else 0 f_l.write("%s %s\n" % (str(time), str(qual))) x, _ = basic_example_step_function(x, u) time += 1 f_s.close() f_l.close() print("Done with generate basic traces, trace no" + str(tc)) tc += 1
def parameter_search_for_formula(formula, parameter_domains_for_formula, folder_name, trace_count, signal_file_base, process_count, return_type, past_results=[]): parameter_list = list(parameter_domains_for_formula.keys()) parameter_domain = [parameter_domains_for_formula[pa] for pa in parameter_list] prefix_formula = STL.infix_to_prefix(formula) best_v, params, time_passed = grid_search.grid_search(formula=prefix_formula, parameter_list=parameter_list, parameter_domain=parameter_domain, folder_name=folder_name, signal_file_base=signal_file_base, trace_count=trace_count, signal_file_rest='', process_count=process_count, return_type=return_type, past_results=past_results) #result_file = folder_name + "".join(formula.split()) + ".mat" #_ = plot.convert_save_results(parameter_list, parameter_domain, all_results, result_file, formula, # time_passed, trace_count, process_count, best_v, params) formula_n = formula if params == None: print( "There are no best parameters for the formula: " + formula ) else: for p, v in zip(parameter_list, params): formula_n = formula_n.replace(p, str(v)) print("With valuation " + str(best_v) + " ,best parameters form " + formula_n + " ,with prefix form: " + STL.infix_to_prefix(formula_n) + " ,in time: " + str(time_passed)) return stl_constants.FormulaValuation(formula=formula_n, valuation=best_v)
def label_test_file(test_file_name, label_file_name, viol_formula, duration): # THIS DOES NOT WORK. I WILL FIX IT LATER! f_s = open(test_file_name, 'r') lines = f_s.readlines() f_l = open(label_file_name, 'w') time = 0 # Initialize the checker: stn_viol = STL.SyntaxTreeNode() stn_viol.initialize_node(viol_formula.split(), 0) while time <= duration: # Store the values to the file: kk = [float(f) for f in lines[time].split()[1:6] ] + [int(i) for i in lines[time].split()[6:]] stn_viol.compute_qv( STL.DataPoint(value=[float(f) for f in lines[time].split()[1:6]] + [int(i) for i in lines[time].split()[6:]], time=time)) qual = 1 if stn_viol.qv > 0 else 0 f_l.write("%s %s\n" % (str(time), str(qual))) time += 1 f_s.close() f_l.close() print("Done!")
def controller_traffic_data(viol_formula, folder_name, trace_count, duration, pc, cause_formula): """ Args: cause_formula: formula got from cause_mining_traffic_data (in prefix form) Returns: nothing """ #traffic_file = "test_data/traffic_data/l5_system" #traffic_file_no_soln = "test_data/traffic_data/l5_system_no_soln" #traffic_file_no_soln2 = "test_data/traffic_data/l5_system_no_soln2" traffic_file_no_soln3 = "test_data/traffic_data/l5_system_no_soln3" link_dict, intersection_dict = read_input.load_from_annotated_file( traffic_file_no_soln3) tn = network.Network(link_dict, intersection_dict, scale=5) uk_count = tn.get_intersection_count() xk_initialized = np.zeros(tn.get_link_count()) tn.initialize_links(xk_initialized, 0.1) viol_formula_prefix = STL.infix_to_prefix(viol_formula) sg.controller(folder_name=folder_name, name='test', trace_count=trace_count, duration=duration, viol_formula=viol_formula_prefix, cause_formula=cause_formula, step_function=tn.step, xk_initialized=xk_initialized, uk_domain=[0, 1], uk_count=uk_count, num_to_let=True)
def cause_mining_print_detailed_result(infix_formula, folder_name, signal_file_base, trace_count, signal_file_rest): """ Written as a function to see how "good" a formula is, mainly to help us debug. This function prints the false positive, false negative, true positive, true negative, precision, recall and various f scores of the infix formula given as an input. """ prefix_formula = STL.infix_to_prefix(infix_formula) fp_fn_tp_tn = evaluator.evaluate_signals(formula=prefix_formula, folder_name=folder_name, signal_file_base=signal_file_base, trace_count=trace_count, signal_file_rest=signal_file_rest, return_type=stl_constants.__DETAILED) print(infix_formula) fp = str(fp_fn_tp_tn[0]) fn = str(fp_fn_tp_tn[1]) tp = str(fp_fn_tp_tn[2]) tn = str(fp_fn_tp_tn[3]) precision = str(metrics_util.calculate_precision(fp_fn_tp_tn)) recall = str(metrics_util.calculate_recall(fp_fn_tp_tn)) f1 = str(metrics_util.calculate_f1_score(fp_fn_tp_tn)) f05 = str(metrics_util.calculate_fhalf_score(fp_fn_tp_tn)) f09 = str(metrics_util.calculate_f_Beta_score(fp_fn_tp_tn, 0.9)) f01 = str(metrics_util.calculate_f_Beta_score(fp_fn_tp_tn, 0.1)) f015 = str(metrics_util.calculate_f_Beta_score(fp_fn_tp_tn, 0.15)) f02 = str(metrics_util.calculate_f_Beta_score(fp_fn_tp_tn, 0.2)) f03 = str(metrics_util.calculate_f_Beta_score(fp_fn_tp_tn, 0.3)) f04 = str(metrics_util.calculate_f_Beta_score(fp_fn_tp_tn, 0.4)) print('fp: ' + fp + ' fn: ' + fn + ' tp: ' + tp + ' tn: ' + tn + ' precision: ' + precision + ' recall: ' + recall + ' \nf1 score: ' + f1 + ' f0.5 score: ' + f05 + ' f0.9 score: ' + f09 + ' \nf0.1 score: ' + f01 + ' f0.15 score: ' + f015 + ' f0.2 score: ' + f02 + ' f0.3 score: ' + f03 + ' \nf0.4 score: ' + f04) return fp_fn_tp_tn
def formula_val_list_into_concat_formula_list(prefix_formula_val_list, folder_name, signal_file_base, trace_count, signal_file_rest, return_type): """ Designed for debug purposes of cause mining algorithm Takes only the formula parts of a Formula_Valuation list, turns them into their infix forms, concatenates them with or and calculates the valuation of the resulting formula. Returns the resulting formula and the valuation as a FormulaValuation. Args: prefix_formula_val_list: A list of Formula Valuations where formulas are in prefix forms. Ex: [FormulaValuation(formula='A 0 4 x5 = 0', valuation=0.7824), FormulaValuation(formula='& A 0 2 x5 = 0 P 1 1 x3 > 10', valuation=0.921521)] return_type: Returns: a FormulaValuation """ infix_formula_list = [fv.formula for fv in prefix_formula_val_list] prefix_to_infix_list(infix_formula_list) concat_with_or_infix(infix_formula_list) formula = STL.infix_to_prefix(infix_formula_list[0]) valuation = optimization.evaluator.evaluate_signals( formula, folder_name, signal_file_base, trace_count, signal_file_rest, return_type) return stl_constants.FormulaValuation(formula=infix_formula_list[0], valuation=valuation)
def convert_and_evaluate(formula_list, parallel_process_count, parameter_domains, folder_name, signal_file_base, return_type, trace_count, metric_list, set_valued_metrics): nodes_list = [] for formula in formula_list: formula = inject_parameters(formula, parameter_domains, metric_list, set_valued_metrics) formula = STL.infix_to_prefix(formula) syntax_tree_node = STL.SyntaxTreeNode() syntax_tree_node.initialize_node(formula.split(), 0) nodes_list.append(syntax_tree_node) pool = Pool(processes=parallel_process_count) fitness_partial = partial(insert_fitness_value_to_individual, folder_name, signal_file_base, return_type, trace_count) results = (pool.map(fitness_partial, nodes_list)) pool.close() pool.join() return results
def return_sc_form(formula, prefix=True): """ Args: formula: formula to be written with "next" statements prefix: bool value that indicates whether the given formula is prefix or infix Returns: formula written with only X and !. For example, return_sc_form('P 1 1 ( x0 = 0 ))', False) = 'X (x0=0.0)' """ if not prefix: formula = STL.infix_to_prefix(formula) stn = STL.SyntaxTreeNode() stn.initialize_node(formula.split(), 0) next_form_str = return_next_form(stn) #print(next_form_str) return next_form_str
def break_formula(cause_formula): """ Breaks a cause formula Phi = Phi_1 | Phi_2 | ... | Phi_n into an array formula_list = [Phi_1, Phi_2, ..., Phi_n] where Phi_i = A[1,a](u_i = c_i) & P[1,1] (phi_i) Args: cause_formula: Returns: stn_list of all formula components of the given concatenated formula """ stn = STL.SyntaxTreeNode() stn.initialize_node(cause_formula.split(), 0) return break_formula_helper(stn)
def prefix_to_infix_list(prefix_list): """ Changes prefix formulas in a list to their infix forms Args: prefix_list: list of prefix formulas Returns: nothing """ length = len(prefix_list) for i in range(0, length): prefix_list.append(STL.prefix_to_infix(prefix_list[0])) prefix_list.pop(0)
def find_best_formula(folder_name, trace_count, heuristic, duration, signal_file_base, signal_file_rest, return_type, operator_count_limit, pc, upto, cause_limit, withoutS, valuation_limit=None): """ Returns: the best formula found with heuristic algorithm if heuristic == True, found with search_all_search_space if heuristic == False. """ if not heuristic: best_result = search_all_search_space_traffic_data( pc=pc, return_type=return_type, folder_name=folder_name, trace_count=trace_count, signal_file_base=signal_file_base, cause_limit=cause_limit, operator_count_limit=operator_count_limit, upto=upto, withoutS=withoutS) cause_formula_prefix = STL.infix_to_prefix(best_result.formula) else: cause_formula_prefix = cause_mining_traffic_data( pc=pc, valuation_limit=valuation_limit, folder_name=folder_name, trace_count=trace_count, signal_file_base=signal_file_base, return_type=return_type, operator_count_limit=operator_count_limit, withoutS=withoutS) # best formula in prefix form cmm.print_detailed_result(prefix=1, formula=cause_formula_prefix, folder_name=folder_name, signal_file_base=signal_file_base, signal_file_rest=signal_file_rest, trace_count=trace_count) return cause_formula_prefix
def print_past_formulas_prefix_infix_valuation(past_results, folder_name, signal_file_base, trace_count, signal_file_rest, return_type): """ Debugging tool for past formulas. Calls formula_val_list_into_concat_formula_list and calculates the resulting formula from past_results list (or any FormulaValuation list with formulas in prefix forms), returns the prefix and infix form and the valuation of the resulting formula """ forVal = formula_val_list_into_concat_formula_list( past_results, folder_name, signal_file_base, trace_count, signal_file_rest, return_type) print("Infix Formula: " + forVal.formula) print("Prefix Formula: " + STL.infix_to_prefix(forVal.formula)) print("Valuation: " + str(forVal.valuation))
def look_for_any_formula(folder_name, trace_count, heuristic, duration, signal_file_base, signal_file_rest, return_type, operator_count_limit, pc, upto, cause_limit, withoutS, valuation_limit=None): if not heuristic: best_result = search_all_search_space_traffic_data( pc=pc, return_type=return_type, folder_name=folder_name, trace_count=trace_count, signal_file_base=signal_file_base, cause_limit=cause_limit, operator_count_limit=operator_count_limit, upto=upto, withoutS=withoutS, controllable_formulas=False) cause_formula_prefix = STL.infix_to_prefix(best_result.formula) else: cause_formula_prefix = cause_mining_traffic_data( pc=pc, valuation_limit=valuation_limit, folder_name=folder_name, trace_count=trace_count, signal_file_base=signal_file_base, return_type=return_type, operator_count_limit=operator_count_limit, withoutS=withoutS, controllable_formulas=False) # best formula in prefix form cmm.print_detailed_result(prefix=1, formula=cause_formula_prefix, folder_name=folder_name, signal_file_base=signal_file_base, signal_file_rest=signal_file_rest, trace_count=trace_count) return cause_formula_prefix
def print_detailed_result(prefix, formula, folder_name, signal_file_base, signal_file_rest, trace_count): """ Args: prefix: (bool) 1 if formula given is prefix, 0 if its infix formula: STL formula Returns: nothing """ if prefix: infix_formula = STL.prefix_to_infix(formula) else: infix_formula = formula fp_fn_tp_tn = cause_mining_heuristic.cause_mining_print_detailed_result( infix_formula, folder_name, signal_file_base, trace_count, signal_file_rest) return fp_fn_tp_tn
def traffic_signal_generator(folder_name, pc): # This function uses the package "signal_generation". This is for "cause mining." # generates new traffic_signal data with given violation_formula, trace_count and duration. #viol_formula = "( ( ( ( ( x0 < 30 ) & ( x1 < 30 ) ) & ( x2 < 30 ) ) & ( x3 < 15 ) ) & ( x4 < 15 ) )" #viol_formula_no_soln = "( ( ( ( ( x0 < 32 ) & ( x1 < 32 ) ) & ( x2 < 32 ) ) & ( x3 < 16 ) ) & ( x4 < 16 ) )" #viol_formula_no_soln2 = "( ( ( ( ( x0 < 30 ) & ( x1 < 30 ) ) & ( x2 < 30 ) ) & ( x3 < 15 ) ) & ( x4 < 15 ) )" viol_formula_no_soln3 = "( ( ( ( ( x0 < 30 ) & ( x1 < 30 ) ) & ( x2 < 30 ) ) & ( x3 < 15 ) ) & ( x4 < 15 ) )" viol_formula_prefix = STL.infix_to_prefix(viol_formula_no_soln3) trace_count = 20 duration = 100 #traffic_file = "test_data/traffic_data/l5_system" #traffic_file_no_soln = "test_data/traffic_data/l5_system_no_soln" #traffic_file_no_soln2 = "test_data/traffic_data/l5_system_no_soln2" traffic_file_no_soln3 = "test_data/traffic_data/l5_system_no_soln3" generator.generate_traffic_traces(folder_name=folder_name, file_name="test", trace_count=trace_count, viol_formula=viol_formula_prefix, traffic_file=traffic_file_no_soln3, duration=duration, pc=pc)
def controller_n_iterations(n, heuristic): folder_name = 'test_data/toy_example_data/' trace_count = 20 signal_file_base = 'test' signal_file_rest = "" duration = 100 cause_limit = 1 oc_limit = 0 pc = 8 return_type = stl_constants.__F_03_SCORE withoutS = True upto = False uk_domain = [1, 2, 3, 4] uk_count = 1 violation_formula = ' ! ( x0 = 0 ) & ! ( x1 = 5 ) & ! ( x1 = 6 ) ' # violation formula of game_map2 violation_formula2 = '! ( ( x0 < 2 ) & ( x1 < 4 ) ) & ! ( ( x0 > 3 ) & ( x1 > 3 ) )' # violation formula of game_map viol_formula_prefix = STL.infix_to_prefix(violation_formula2) formula_list = [] valuation_limit = 0.1 operator_count_limit_heuristic = 100 label_cnt = hf.label_count(folder_name=folder_name, label_file_base='test_', label_file_rest='_label', trace_count=trace_count) print("label count before the controller: " + str(label_cnt)) for i in range(0, n): if heuristic: cause_formula_prefix = heuristic_toy_example( pc=pc, folder_name=folder_name, valuation_limit=valuation_limit, trace_count=trace_count, signal_file_base=signal_file_base, operator_count_limit=operator_count_limit_heuristic, return_type=return_type, withoutS=withoutS) # returns prefix formula (string) else: best_formula = search_all_search_space_toy_example( cause_limit=cause_limit, pc=pc, return_type=return_type, folder_name=folder_name, trace_count=trace_count, signal_file_base=signal_file_base, upto=upto, operator_count_limit=oc_limit, withoutS=withoutS) if best_formula == "": print("no formula with positive valuation") break cause_formula_prefix = STL.infix_to_prefix(best_formula) cma.cause_mining_main.print_detailed_result( prefix=1, formula=cause_formula_prefix, folder_name=folder_name, signal_file_base=signal_file_base, signal_file_rest=signal_file_rest, trace_count=trace_count) formula_list.append(cause_formula_prefix) cause_formula_prefix = cma.helper_funs.concat_with_or_prefix( formula_list) sg.controller(folder_name=folder_name, name='test', trace_count=trace_count, duration=duration, viol_formula=viol_formula_prefix, cause_formula=cause_formula_prefix, step_function=toy_example_step_function, xk_initialized=(3, 4), uk_domain=uk_domain, uk_count=uk_count, num_to_let=False) label_cnt = hf.label_count(folder_name=folder_name, label_file_base='test_', label_file_rest='_label', trace_count=trace_count) print("label count after controller " + str(i) + " is: " + str(label_cnt)) if label_cnt == 0: break
def traffic_signal_generator(trace_start_index, folder_name, name, traffic_file, trace_count, viol_formula, duration): """ Args: trace_start_index: folder_name: name: traffic_file: trace_count: viol_formula: duration: Returns tuple (metrics,inputs, parameter_domains) where metrics: The list of metrics inputs: A list of controllable metrics (inputs is subset of metrics) parameter_domains: A dictionary containing the domains of parameters Sample return: ([0,1,2], [2], {'p0': [0, 10], 'p1': [0, 10], 'p2': ['a', 'b']}) Note that the domain for the input metrics is always set valued. """ # First construct the traffic network. # In loop, generate trace. check it against the formula, produce the label. Save both link_dict, intersection_dict = read_input.load_from_annotated_file( traffic_file) tn = network.Network(link_dict, intersection_dict, scale=5) tc = 0 while tc < trace_count: index = trace_start_index + tc f_signal_name = folder_name + "/" + name + "_" + str(index) f_label_name = f_signal_name + "_label" f_s = open(f_signal_name, 'w') f_l = open(f_label_name, 'w') time = 0 # The states of the links xk = np.zeros(tn.get_link_count()) sm = [_ for _ in range(tn.get_intersection_count())] tn.initialize_links(xk, 0.1) tn.set_random_signal_mode(sm) # Initialize the checker: stn_viol = STL.SyntaxTreeNode() stn_viol.initialize_node(viol_formula.split(), 0) sm_numbers = [0 if x == 'a' else 1 for x in sm] while time <= duration: # Store the values to the file: stn_viol.compute_qv( STL.DataPoint(value=xk.tolist() + sm_numbers, time=time)) f_s.write("%s %s %s\n" % (str(time), " ".join( [str(x) for x in xk]), " ".join([str(x) for x in sm_numbers]))) qual = 0 if stn_viol.qv >= 0 else 1 f_l.write("%s %s\n" % (str(time), str(qual))) xk, _ = tn.step(xk, sm) tn.set_random_signal_mode(sm) sm_numbers = [0 if x == 'a' else 1 for x in sm] time += 1 f_s.close() f_l.close() print("Done %d" % index) tc += 1 if trace_count == 0: # return the set of metrics link_count = tn.get_link_count() link_metrics = list(range(0, link_count)) intersection_metrics = list(range(tn.get_intersection_count())) intersection_metrics = [ x + tn.get_link_count() for x in intersection_metrics ] # shift the indices c = tn.get_all_intersection_indices_and_modes() parameter_domains = {} for i in range(tn.get_intersection_count()): pi = 'p' + str(i + link_count) parameter_domains[pi] = next( list(x[1].keys()) for x in c if x[0] == i) capacities = tn.np_xcap for i in range(link_count): parameter_domains['p' + str(i)] = [0, capacities[i]] return link_metrics + intersection_metrics, intersection_metrics, parameter_domains # All metrics, set valued metrics, domains for set valued metrics
def basic_example(heuristic): """ finds the best formula with heuristic or search_all_search_space and applies controller refinement loop_count times. Args: heuristic: (bool) True -> search the best formula by heuristic algorithm, False -> search the best formula bu search_all_search_space Returns: nothing """ loop_count = 6 folder_name = 'test_data/basic_example_data/' trace_count = 20 duration = 100 pc = 24 return_type = stl_constants.__F_03_SCORE oc_limit = 0 cause_limit = 1 upto = False withoutS = True #for heuristic==True and print_detailed_results valuation_limit = 0.01 signal_file_base = 'test' signal_file_rest = '' operator_count_limit = 1 viol_formula = 'x0 < 5' viol_formula_prefix = STL.infix_to_prefix(viol_formula) uk_domain = [-2, 1, 2] uk_count = 1 #generate random traces and check the label count generate_basic_traces(folder_name, trace_count, duration) label_cnt = hf.label_count(folder_name=folder_name, label_file_base='test_', label_file_rest='_label', trace_count=trace_count) print("label count before the controller: " + str(label_cnt)) formula_list = [] for i in range(loop_count): if not heuristic: best_formula = search_all_search_space_for_basic_example( cause_limit=cause_limit, pc=pc, return_type=return_type, operator_count_limit=oc_limit, upto=upto, withoutS=withoutS) cause_formula_prefix = STL.infix_to_prefix(best_formula) else: cause_formula_prefix = cause_mining_for_basic_example( pc=pc, valuation_limit=valuation_limit, folder_name=folder_name, trace_count=trace_count, signal_file_base=signal_file_base, return_type=return_type, operator_count_limit=operator_count_limit, withoutS=withoutS) # best formula in prefix form cma.cause_mining_main.print_detailed_result( prefix=1, formula=cause_formula_prefix, folder_name=folder_name, signal_file_base=signal_file_base, signal_file_rest=signal_file_rest, trace_count=trace_count) formula_list.append(cause_formula_prefix) cause_formula_prefix = helper_funs.concat_with_or_prefix(formula_list) sg.controller(folder_name=folder_name, name='test', trace_count=trace_count, duration=duration, viol_formula=viol_formula_prefix, cause_formula=cause_formula_prefix, step_function=basic_example_step_function, xk_initialized=[0], uk_domain=uk_domain, uk_count=uk_count, num_to_let=False) label_cnt = hf.label_count(folder_name=folder_name, label_file_base='test_', label_file_rest='_label', trace_count=trace_count) print("label count after controller " + str(i) + " is: " + str(label_cnt)) if label_cnt == 0: break
def find_best_formula(heuristic, controllable_formulas=True): """ Args: heuristic: (bool) True -> search the best formula by heuristic algorithm, False -> search the best formula bu search_all_search_space Returns: the best formula in prefix form """ folder_name = 'test_data/basic_example_data/' trace_count = 20 duration = 100 pc = 0 return_type = stl_constants.__F_03_SCORE cause_limit = 1 upto = False withoutS = True if controllable_formulas: oc_limit_lhs = 1 oc_limit_rhs = 0 oc_limit = [oc_limit_lhs, oc_limit_rhs] else: oc_limit = 0 # for heuristic==True and print_detailed_results valuation_limit = 0.01 signal_file_base = 'test' signal_file_rest = '' operator_count_limit = 1 print("operator_count_limit = " + str(oc_limit)) print("pc = " + str(pc)) print("return type = " + str(return_type.category)) print("withoutS = " + str(withoutS)) print("heuristic = " + str(heuristic)) if heuristic: print("valuation_limit = " + str(valuation_limit)) else: print("cause_limit = " + str(cause_limit)) print("upto = " + str(upto)) # generate random traces and check the label count generate_basic_traces(folder_name, trace_count, duration) if not heuristic: best_formula = search_all_search_space_for_basic_example( cause_limit=cause_limit, pc=pc, return_type=return_type, operator_count_limit=oc_limit, upto=upto, withoutS=withoutS, controllable_formulas=controllable_formulas) cause_formula_prefix = STL.infix_to_prefix(best_formula) else: cause_formula_prefix = cause_mining_for_basic_example( pc=pc, valuation_limit=valuation_limit, folder_name=folder_name, trace_count=trace_count, signal_file_base=signal_file_base, return_type=return_type, operator_count_limit=operator_count_limit, withoutS=withoutS, controllable_formulas=controllable_formulas ) # best formula in prefix form cma.cause_mining_main.print_detailed_result( prefix=1, formula=cause_formula_prefix, folder_name=folder_name, signal_file_base=signal_file_base, signal_file_rest=signal_file_rest, trace_count=trace_count) return cause_formula_prefix
def cause_mining_traffic_data(pc, valuation_limit, folder_name, trace_count, signal_file_base, return_type, operator_count_limit, withoutS=False, controllable_formulas=True): """ Calls cause_mining_algorithm from cause_mining_algo package with traffic data. Returns: best formula in prefix form """ print( "---------------------------------------------------------------------------------------" ) print(" cause_mining_traffic_data ") print( "---------------------------------------------------------------------------------------" ) start_time = time.time() save = True metric_list = ['6', '1', '2', '3', '4', '5', '0'] control_metrics = ['5', '6'] set_valued_metrics = ['6', '5'] parameter_domains = { 'p0': range(10, 40, 5), 'p1': range(10, 40, 5), 'p2': range(10, 40, 5), 'p3': range(5, 20, 5), 'p4': range(5, 20, 5), 'p5': range(0, 2, 1), 'p6': range(0, 2, 1), 'pA': range(0, 6, 1), 'pP': range(0, 6, 1), 'pS': range(0, 6, 2), 'pT': [1, 2] } result_file = 'min_max' strictly_increasing_oc = False best_result = cause_mining_heuristic.cause_mining_algorithm( metric_list=metric_list, control_metrics=control_metrics, set_valued_metrics=set_valued_metrics, parameter_domains=parameter_domains, folder_name=folder_name, trace_count=trace_count, signal_file_base=signal_file_base, process_count=pc, save=save, result_file=result_file, return_type=return_type, strictly_increasing_oc=strictly_increasing_oc, valuation_limit=valuation_limit, operator_count_limit=operator_count_limit, withoutS=withoutS, controllable_formulas=controllable_formulas, time_shift=1) # type: FormulaValuation print('### --------end of cause mining for traffic data-------- ### ') print("Best Result in prefix form : " + best_result.formula +\ "\nBest Result in infix form: " + STL.prefix_to_infix(best_result.formula) + \ "\nWith the Valuation : " + str(best_result.valuation)) end_time = time.time() print("") print( "---------------------------------------------------------------------------------------" ) print("cause_mining_traffic_data ended in %s seconds" % str(end_time - start_time)) print( "---------------------------------------------------------------------------------------" ) print("folder name: " + folder_name) print("trace count: " + str(trace_count)) print("processor count: " + str(pc)) print("parameter domains: " + str(parameter_domains)) print("return type: " + return_type.name) print("strictly increasing: " + str(strictly_increasing_oc)) print("searched until operator count: " + str(operator_count_limit)) return best_result.formula
def evaluate(formula, signal_file_name, label_file_name, stn, return_type, past_results=[]): """ evaluates the given formulas false_positive, false_negative, true_positive, true_negative results in the given files end returns the necessary ones based on the result_type. If there are past_results, all formulas are concatenated with or and the resulting formula's results are returned. Args: formula: prefix formula signal_file_name: label_file_name: stn: return_type: one of the types in stl_constants, determines the valuation best_result will be chosen based on in evaluate_signals. past_results: a list of formula valuations (formulas inside being prefix) If past_results is not empty, formula and the formulas in past_results are concatenated using "or" and evaluation is done based on the concatenated formula. Returns: if return_type is TYPE_RATIO; true positives / # of data points is returned if return_type is TYPE_MISMATCH; # of data points - true positives is returned else; detailed_result (i.e. an array of false_positive, false_negative, true_positive, true_negative is returned """ # Construct syntax tree if stn and past_results == []: stn.clean() else: # create new formula by concatenating the formula with past formulas with or, and compute this formula on tests new_formula = formula for frml in past_results: new_formula = ' | ' + new_formula + ' ' + frml.formula stn = STL.SyntaxTreeNode() stn.initialize_node(new_formula.split(), 0) result = 0 counter = 0 # detailed result is false_positive, false_negative, true_positive, true_negative detailed_result = [0, 0, 0, 0] skip_count = 10 # skip the first 10 data points, not important in monitoring. sc = 0 with open(signal_file_name, 'r') as sf, open(label_file_name, 'r') as lf: for ts, te in zip(sf, lf): s = ts.split() t = s[0] s = s[1:] _, e = te.split() t = float(t) s = [float(x) for x in s] e = float(e) while t > stn.nt: stn.compute_qv(STL.DataPoint(value=s, time=stn.nt)) if sc > skip_count: result += (stn.qv > 0) == ep counter += 1 # label is false if (ep == 0): # if stn.qv > 0 is true then it is false positive # if stn.qv > 0 is false then it is true negative detailed_result = (detailed_result[0] + int( (stn.qv > 0) != ep), detailed_result[1], detailed_result[2], detailed_result[3] + int((stn.qv > 0) == ep)) # label is true else: # if stn.qv > 0 is false then it is false negative # if stn.qv > 0 is true then it is true positive detailed_result = (detailed_result[0], detailed_result[1] + int((stn.qv > 0) != ep), detailed_result[2] + int((stn.qv > 0) == ep), detailed_result[3]) else: sc += 1 stn.compute_qv(STL.DataPoint(time=t, value=s)) if sc > skip_count: result += (stn.qv > 0) == e counter += 1 # label is false if (e == 0): # if stn.qv > 0 is true then it is false positive # if stn.qv > 0 is false then it is true negative detailed_result = (detailed_result[0] + int( (stn.qv > 0) != e), detailed_result[1], detailed_result[2], detailed_result[3] + int((stn.qv > 0) == e)) # label is true else: # if stn.qv > 0 is false then it is false negative # if stn.qv > 0 is true then it is true positive detailed_result = (detailed_result[0], detailed_result[1] + int((stn.qv > 0) != e), detailed_result[2] + int((stn.qv > 0) == e), detailed_result[3]) else: sc += 1 sp = s ep = e if return_type.type == stl_constants.TYPE_RATIO: return float(result) / counter if return_type.type == stl_constants.TYPE_MISMATCH: # return the mismatch count return counter - result else: # return detailed results return detailed_result
def evaluate_signals(formula, folder_name, signal_file_base, trace_count, signal_file_rest, return_type, stn=None, past_results=[]): """ Checks if the formula's lower bounds & upper bounds are within the limits. Calls evaluate, returns valuation based on return_type. Args: formula: prefix formula folder_name: signal_file_base: trace_count: signal_file_rest: return_type: stn: past_results: Returns: """ # Below code piece checks if lower bounds are smaller than upper bounds in "formula", # if not, it returns the worst value. if not stn: stn = STL.SyntaxTreeNode() stn.initialize_node(formula.split(), 0) flag = helper_funs.traverse_formula_check_intervals(stn) if not flag: if return_type.category == stl_constants.CATEGORY_MAXIMIZATION: return 0.0 elif return_type.type == stl_constants.__DETAILED: return [0, 0, 0, 0] elif return_type.category == stl_constants.CATEGORY_MINIMIZATION: return stl_constants.MAX_EVAL # start evaluation count = 0 total = 0 detailed_result = [0, 0, 0, 0] for i in range(trace_count): s_file = folder_name + signal_file_base + '_' + str( i) + signal_file_rest label_file = s_file + "_label" r = evaluate(formula=formula, signal_file_name=s_file, label_file_name=label_file, stn=stn, return_type=return_type, past_results=past_results) count += 1 if return_type.type == stl_constants.TYPE_RATIO or return_type.type == stl_constants.TYPE_MISMATCH: total += r # total number of mismatches for ret_type = MISMATCH else: detailed_result = [ detailed_result[0] + r[0], detailed_result[1] + r[1], detailed_result[2] + r[2], detailed_result[3] + r[3] ] # fp, fn, tp, tn if return_type.type == stl_constants.TYPE_RATIO: return total / count elif return_type.type == stl_constants.TYPE_MISMATCH: return total elif return_type.type == stl_constants.TYPE_PRECISION: return float(metrics_util.calculate_precision(detailed_result)) elif return_type.type == stl_constants.TYPE_RECALL: return float(metrics_util.calculate_recall(detailed_result)) elif return_type.type == stl_constants.TYPE_F1_SCORE: return float(metrics_util.calculate_f1_score(detailed_result)) elif return_type.type == stl_constants.TYPE_FHALF_SCORE: return float(metrics_util.calculate_fhalf_score(detailed_result)) elif return_type.type == stl_constants.TYPE_F_015_SCORE: return float(metrics_util.calculate_f_Beta_score( detailed_result, 0.15)) elif return_type.type == stl_constants.TYPE_F_02_SCORE: return float(metrics_util.calculate_f_Beta_score(detailed_result, 0.2)) elif return_type.type == stl_constants.TYPE_F_03_SCORE: return float(metrics_util.calculate_f_Beta_score(detailed_result, 0.3)) elif return_type.type == stl_constants.TYPE_F_04_SCORE: return float(metrics_util.calculate_f_Beta_score(detailed_result, 0.4)) else: return detailed_result
import unittest import random from trace_checker import STL from trace_checker import formula_utilities as U import syntactically_cosafe_form as scf _data_points = [ STL.DataPoint(0, [0]), STL.DataPoint(2, [1]), STL.DataPoint(4, [3]), STL.DataPoint(6, [8]) ] class Test_syntactically_cosafe_form(unittest.TestCase): def test_scf(self): formula = 'P 1 1 ( x0 = 1 )' formula_X0, dict0 = 'X p0', {'x0=1.0': 'p0'} sc_formula = scf.return_sc_form(formula, prefix=False) formula_X, dict = scf.turn_inequalities_to_atomic_propositions( sc_formula) self.assertEqual(formula_X, formula_X0) self.assertEqual(dict, dict0) formula = 'P 1 2 ( x0 = 1 )' formula_X0, dict0 = '( X p0 | XX p0 )', {'x0=1.0': 'p0'} sc_formula = scf.return_sc_form(formula, prefix=False) formula_X, dict = scf.turn_inequalities_to_atomic_propositions( sc_formula) self.assertEqual(formula_X, formula_X0) self.assertEqual(dict, dict0)
def cause_mining_algorithm(metric_list, control_metrics, set_valued_metrics, parameter_domains, folder_name, trace_count, signal_file_base, process_count, save, result_file, return_type, strictly_increasing_oc, valuation_limit, operator_count_limit, withoutS=False, controllable_formulas=True, time_shift=0): """ Args: metric_list: control_metrics: set_valued_metrics: parameter_domains: folder_name: trace_count: signal_file_base: process_count: save: result_file: return_type: strictly_increasing_oc: (bool) If False, the heuristic is applied while increasing operator count, if True, operator count increases by one in each loop. valuation_limit: the predefined limit which decides how much of a value addition is enough for a best formula of an operator count to enter the past_formula list. operator_count_limit: Last operator count. The best_formulas are searched for until operator count reaches this integer value. controllable_formulas: (bool) if True, cause_mining input is given to formula_search as True, and generate_formula_tree_cause_mining is called inside formula_search_operator_count as a consequence. That is, controllable formulas are synthesized. if False, cause_mining input is given to formula_search as False, and generate_formula_tree_iterative is called inside formula_search_operator_count as a consequence. That is, all kinds of formulas are generated. By default, controllable_formulas = True, so only controllable formulas are generated. Returns: FormulaValuation(the resulting formula -small best formulas concatenated with ors- in prefix form, its valuation) """ if type(operator_count_limit) is int: oc_rhs_limit = operator_count_limit else: _, oc_rhs_limit = operator_count_limit if controllable_formulas: # we do this since if controllable_formulas == True, the code will enter generate_formula_tree_iterative and this function cannot process oc = -1 current_oc = -1 else: current_oc = 0 past_results = [] # all formulas in past_results must be in prefix form if not strictly_increasing_oc: last_used_oc = current_oc while True: results, best_formula = formula_search.formula_search(metric_list=metric_list, set_valued_metrics=set_valued_metrics, operator_counts=[current_oc], parameter_domains=parameter_domains, folder_name=folder_name, trace_count=trace_count, generate_signals="", signal_file_base=signal_file_base, process_count=process_count, save=save, cause_mining=controllable_formulas, return_type=return_type, result_file=result_file, control_metrics=control_metrics, past_results=past_results, withoutS=withoutS, time_shift=time_shift) # turn the formula into prefix form, and then append it to past_results. best_formula_prefix = stl_constants.FormulaValuation(formula=STL.infix_to_prefix(best_formula.formula), valuation=best_formula.valuation) past_results.append(best_formula_prefix) if len(past_results) > 1 and (past_results[-1].valuation - past_results[-2].valuation) < valuation_limit: past_results.pop() if last_used_oc < current_oc: print("break 1") break current_oc += 1 print("oc change to " + str(current_oc)) elif len(past_results) > 1 and (past_results[-1].valuation - past_results[-2].valuation) > valuation_limit: last_used_oc = current_oc print("last used oc : " + str(last_used_oc)) print("?????????????????? PAST RESULTS SO FAR ???????????????????????????") print(past_results) #helper_funs.print_past_formulas_prefix_infix_valuation(past_results=past_results, folder_name=folder_name, # signal_file_base=signal_file_base, # trace_count=trace_count, # signal_file_rest='', return_type=return_type) if current_oc == oc_rhs_limit+1: break else: # i.e. if strictly_increasing_oc: while True: results, best_formula = formula_search.formula_search(metric_list=metric_list, set_valued_metrics=set_valued_metrics, operator_counts=[current_oc], parameter_domains=parameter_domains, folder_name=folder_name, trace_count=trace_count, generate_signals="", signal_file_base=signal_file_base, process_count=process_count, save=save, cause_mining=controllable_formulas, return_type=return_type, result_file=result_file, control_metrics=control_metrics, past_results=past_results, time_shift=time_shift) # turn the formula into prefix form, and the append it to past_results. best_formula_prefix = stl_constants.FormulaValuation(formula=STL.infix_to_prefix(best_formula.formula), valuation=best_formula.valuation) past_results.append(best_formula_prefix) if len(past_results) > 1 and (past_results[-1].valuation - past_results[-2].valuation) < valuation_limit: past_results.pop() print("break 2") break current_oc += 1 if current_oc == operator_count_limit+1: break print("?????????????????? PAST RESULTS SO FAR ???????????????????????????") print(past_results) past_formulas = [fv.formula for fv in past_results] #for formula_valuation in past_results: #past_formulas.append(STL.prefix_to_infix(formula_valuation.formula)) # now the list is consisted of infix formulas, it can go into concat_with_or result = stl_constants.FormulaValuation(formula=helper_funs.concat_with_or_prefix(past_formulas), valuation=past_results[-1].valuation) return result
def plot_change_wrt_parameter(formula, parameter_name, parameter_domain, folder_name, signal_file_base, trace_count): """ Written as a function to see how "good" a formula is, mainly to help us debug. This function takes a formula with one parameter and parameter domain, replaces the parameter name with numbers in parameter domain and plots the change in the tp, tn, fp, tp+tn, precision, recall results """ tp_plus_tn = [] fp_plus_fn = [] index_cnt = 0 formulas = np.zeros((len(parameter_domain), 13)) # 13 corresponds to the 13 values evaluate_signals_deneme returs: fp,fn,tp,tn,precision,recall,f.5,f.4,f.3,f.2,f.15,f.1 for i in parameter_domain: new_formula = formula.replace(parameter_name, str(i)) print(new_formula) return_type = stl_constants.__DETAILED # evaluate_signals returns fp,fn,tp,tn formulas[index_cnt, :4] = evaluator.evaluate_signals(formula=new_formula, folder_name=folder_name, signal_file_base=signal_file_base, trace_count=trace_count, signal_file_rest='', return_type=return_type) formulas[index_cnt, 5] = metrics_util.calculate_precision(formulas[index_cnt, :4]) formulas[index_cnt, 6] = metrics_util.calculate_recall(formulas[index_cnt, :4]) formulas[index_cnt, 7] = metrics_util.calculate_f_Beta_score(formulas[index_cnt, :4], 0.5) # f0.5 formulas[index_cnt, 8] = metrics_util.calculate_f_Beta_score(formulas[index_cnt, :4], 0.4) # f0.4 formulas[index_cnt, 9] = metrics_util.calculate_f_Beta_score(formulas[index_cnt, :4], 0.3) # f0.3 formulas[index_cnt, 10] = metrics_util.calculate_f_Beta_score(formulas[index_cnt, :4], 0.2) # f0.2 formulas[index_cnt, 11] = metrics_util.calculate_f_Beta_score(formulas[index_cnt, :4], 0.15) # f0.15 formulas[index_cnt, 12] = metrics_util.calculate_f_Beta_score(formulas[index_cnt, :4], 0.1) # f0.1 # the code piece between two identical prints only serves the need to see the values in the console, this part is useless for the plot # print('\n#################### plot_change_wrt_parameter #####################') # tp = int(formulas[index_cnt][0]) # tn = int(formulas[index_cnt][1]) # fp = int(formulas[index_cnt][2]) # fn = int(formulas[index_cnt][3]) # prec = int(formulas[index_cnt][4]) # recall = int(formulas[index_cnt][5]) # f1score = int(formulas[index_cnt][6]) # fhalfscore = int(formulas[index_cnt][7]) # print('tp: '+ str(tp) + ' tn: '+str(tn) + ' fp: '+ str(fp) + ' fn: ' + str(fn) + ' precision: '+ str(prec) + ' recall: ' + str(recall) + ' f1 score: ' + str(f1score) + ' f0.5 score: ' + str(fhalfscore)) # print('#################### plot_change_wrt_parameter #####################\n') tp_plus_tn.append(formulas[index_cnt][2] + formulas[index_cnt][3]) fp_plus_fn.append(formulas[index_cnt][0] + formulas[index_cnt][1]) index_cnt += 1 t = [i for i in parameter_domain] # plot 1 : t vs. True Positive plt.subplot(8, 1, 1) plt.plot(t, formulas[:, 0], '-go') # above operations are done to write the formula in infix form stn = STL.SyntaxTreeNode() dummy_parameter = '999' # this parameter is solely used to get our way around the stn.initialize_node function # by giving a dummy parameter in stead of parameter name to initialize the node properly. Then we replace this # dummy variable with parameter_name again to print the formula in infix form formula = formula.replace(parameter_name, dummy_parameter) stn.initialize_node(formula.split(), 0) plt.title('Formula = ' + stn.to_formula().replace(dummy_parameter, parameter_name)) plt.ylabel('True Positive') # arranging plot 1 view [xmin, xmax, ymin, ymax] = plt.axis() y_axis_space = (ymax - ymin) / 5 plt.axis([xmin, xmax, ymin - y_axis_space, ymax + y_axis_space]) # arranging x axis labels ax = plt.gca() ax.set_xticks(t) ax.set_xticklabels(t) # plot 2 : t vs. False Positive plt.subplot(8, 1, 2) plt.plot(t, formulas[:, 0], '-co') plt.ylabel('False Positive') # arranging x axis labels ax = plt.gca() ax.set_xticks(t) ax.set_xticklabels(t) # plot 3 : t vs. F 0.5 Score plt.subplot(8, 1, 3) plt.plot(t, formulas[:, 7], '-ro', label="F 0.5") plt.ylabel('F 0.5') plt.legend() # arranging x axis labels ax = plt.gca() ax.set_xticks(t) ax.set_xticklabels(t) # plot 4 : t vs. F 0.4 Score plt.subplot(8, 1, 4) plt.plot(t, formulas[:, 8], '-ro', label="F 0.4") plt.ylabel('F 0.4') plt.legend() # arranging x axis labels ax = plt.gca() ax.set_xticks(t) ax.set_xticklabels(t) # plot 5 : t vs. F 0.3 Score plt.subplot(8, 1, 5) plt.plot(t, formulas[:, 9], '-ro', label="F 0.3") plt.ylabel('F 0.3') plt.legend() # arranging x axis labels ax = plt.gca() ax.set_xticks(t) ax.set_xticklabels(t) # plot 6 : t vs. F 0.2 Score plt.subplot(8, 1, 6) plt.plot(t, formulas[:, 10], '-ro', label="F 0.2") plt.ylabel('F 0.2') plt.legend() # plot 7 : t vs. F 0.15 Score plt.subplot(8, 1, 7) plt.plot(t, formulas[:, 11], '-ro', label="F 0.15") plt.ylabel('F 0.15') plt.legend() # arranging x axis labels ax = plt.gca() ax.set_xticks(t) ax.set_xticklabels(t) # plot 8 : t vs. F 0.1 Score plt.subplot(8, 1, 8) plt.plot(t, formulas[:, 12], '-ro', label="F 0.1") plt.ylabel("F 0.1") plt.legend() # arranging plot 3 view #[xmin, xmax, ymin, ymax] = plt.axis() #y_axis_space = (ymax - ymin) / 5 #plt.axis([xmin, xmax, ymin - y_axis_space, ymax + y_axis_space]) # arranging x axis labels ax = plt.gca() ax.set_xticks(t) ax.set_xticklabels(t) # plt.legend(bbox_to_anchor=(0.8, 1), loc=2, borderaxespad=0.) plt.show()
import sys from trace_checker import STL import evaluator import stl_constants #( XX p0 & ( p1 & p2 ) ) {'x5=0.0': 'p0', 'x3>10.0': 'p1', 'x2<20.0': 'p2'} #( p0 & XX p1 ) {'x5=0.0': 'p0', 'x3>10.0': 'p1'} #( P 1 1 ( ( x1 > 15 ) & ( x7 = 1 ) & ( x6 = 0 ) ) ) | ( P 1 1 ( ( x1 > 25 ) & ( x7 = 1 ) ) ) | ( P 1 1 ( ( x4 < 10 ) & ( x7 = 1 ) & ( x6 = 0 ) ) ) #print(sys.argv[1]) #optimized_formula=sys.argv[1] optimized_formula='( P 1 1 ( ( v1 > 15 ) & ( v7 = 1 ) & ( v6 = 0 ) ) ) | ( P 1 1 ( ( v1 > 25 ) & ( v7 = 1 ) ) ) | ( P 1 1 ( ( v4 < 10 ) & ( v7 = 1 ) & ( v6 = 0 ) ) )' folder_name = 'D:/CASE STUDY/ptSTL/stl_fs_sm-master/stl_fs_sm-master/test_data/traffic_data/traffic_data_l6/' signal_file_base = 'test' result = evaluator.evaluate_signals(STL.infix_to_prefix(optimized_formula), folder_name, signal_file_base, 20, '', stl_constants.__DETAILED, stn=None, past_results=[]) # print('for formula = ' + optimized_formula + ' result is: ' + str(result)) print(str(result)) #[22, 2, 454, 1322]
def cause_mining_for_basic_example(pc, valuation_limit, folder_name, trace_count, signal_file_base, return_type, operator_count_limit, withoutS=False, controllable_formulas=True): """ Calls cause_mining_algorithm -with heuristic- from cause_mining_algo package with basic_example data. Returns: best formula in prefix form """ print( "---------------------------------------------------------------------------------------" ) print(" cause_mining_for_basic_example ") print( "---------------------------------------------------------------------------------------" ) start_time = time.time() save = False metric_list = ['0', '1'] control_metrics = ['1'] set_valued_metrics = ['1'] parameter_domains = { 'p0': range(3, 6, 1), 'p1': [-2, 1, 2], 'pA': range(0, 3, 1), 'pP': range(0, 3, 1), 'pS': range(0, 3, 1), 'pT': [1, 2] } result_file = 'min_max' strictly_increasing_oc = False best_result = cause_mining_heuristic.cause_mining_algorithm( metric_list=metric_list, control_metrics=control_metrics, set_valued_metrics=set_valued_metrics, parameter_domains=parameter_domains, folder_name=folder_name, trace_count=trace_count, signal_file_base=signal_file_base, process_count=pc, save=save, result_file=result_file, return_type=return_type, strictly_increasing_oc=strictly_increasing_oc, valuation_limit=valuation_limit, operator_count_limit=operator_count_limit, withoutS=withoutS, controllable_formulas=controllable_formulas) # type: FormulaValuation # formula is in prefix form print('### --------end of cause mining for basic example -------- ### ') print("Best Result in prefix form : " + best_result.formula +\ "\nBest Result in infix form: " + STL.prefix_to_infix(best_result.formula) + \ "\nWith the Valuation : " + str(best_result.valuation)) end_time = time.time() print("") print( "---------------------------------------------------------------------------------------" ) print("cause_mining_for_basic_example ended in %s seconds" % str(end_time - start_time)) print( "---------------------------------------------------------------------------------------" ) print("folder name: " + folder_name) print("trace count: " + str(trace_count)) print("processor count: " + str(pc)) print("parameter domains: " + str(parameter_domains)) print("return type: " + return_type.name) print("strictly increasing: " + str(strictly_increasing_oc)) print("searched until operator count: " + str(operator_count_limit)) return best_result.formula # prefix formula
def signal_generator_for_plot(trace_start_index, folder_name, name, traffic_file, trace_count, viol_formula, duration, formula): """ Args: trace_start_index: folder_name: name: traffic_file: trace_count: viol_formula: duration: cause_formula: (prefix) This is None if we are not constructing a controller, has a value otherwise. Returns tuple (metrics,inputs, parameter_domains) where metrics: The list of metrics inputs: A list of controllable metrics (inputs is subset of metrics) parameter_domains: A dictionary containing the domains of parameters Sample return: ([0,1,2], [2], {'p0': [0, 10], 'p1': [0, 10], 'p2': ['a', 'b']}) Note that the domain for the input metrics is always set valued. """ # First construct the traffic network. # In loop, generate trace. check it against the formula, produce the label. Save both link_dict, intersection_dict = read_input.load_from_annotated_file( traffic_file) tn = network.Network(link_dict, intersection_dict, scale=5) tc = 0 while tc < trace_count: index = trace_start_index + tc f_signal_name = folder_name + "/" + name + "_" + str(index) f_label_name = f_signal_name + "_label" f_formula_label_name = f_signal_name + "_formula_label" f_s = open(f_signal_name, 'w') f_l = open(f_label_name, 'w') f_fl = open(f_formula_label_name, 'w') time = 0 # The states of the links xk = np.zeros(tn.get_link_count()) sm = [_ for _ in range(tn.get_intersection_count())] tn.initialize_links(xk, 0.1) tn.set_random_signal_mode(sm) # Initialize the checker: stn_viol = STL.SyntaxTreeNode() stn_viol.initialize_node(viol_formula.split(), 0) stn_cause = STL.SyntaxTreeNode() stn_cause.initialize_node(formula.split(), 0) sm_numbers = [0 if x == 'a' else 1 for x in sm] while time <= duration: # Store the values to the file: stn_viol.compute_qv( STL.DataPoint(value=xk.tolist() + sm_numbers, time=time)) f_s.write("%s %s %s\n" % (str(time), " ".join( [str(x) for x in xk]), " ".join([str(x) for x in sm_numbers]))) qual1 = 0 if stn_viol.qv >= 0 else 1 f_l.write("%s %s\n" % (str(time), str(qual1))) stn_cause.compute_qv( STL.DataPoint(value=xk.tolist() + sm_numbers, time=time)) qual2 = 0 if stn_cause.qv >= 0 else 1 f_fl.write("%s %s\n" % (str(time), str(qual2))) xk, _ = tn.step(xk, sm) tn.set_random_signal_mode(sm) sm_numbers = [0 if x == 'a' else 1 for x in sm] time += 1 f_s.close() f_l.close() f_fl.close() print("Done %d" % index) tc += 1
def controller(folder_name, name, trace_count, duration, viol_formula, cause_formula, step_function, xk_initialized, uk_domain, uk_count, num_to_let=False): """ IMPORTANT!: We make the assumption that an input value (control or system) is ordered in the following way: The first xk_count numbers starting from 0 are for system inputs, the following uk_count ones, starting from xk_count are control inputs. For example, if xk_count = 3 and uk_count = 2, x0,x1 and x2 are system inputs and x3,x4 are control inputs. We also make the assumption that uk_domain is the same for each control input. Args: folder_name: name: trace_count: viol_formula: duration: cause_formula: (prefix) This is None if we are not constructing a controller, has a value otherwise. step_function: a function xk, _ = step(xk,uk) that takes old xk and uk values and returns the new xk value with another unimportant value. uk_domain: (list) of domain of uk values uk_count: the number of control inputs xk_initialized: (tuple, numpy array or list) initialized xk values num_to_let:(bool) if step_function takes xk's in the form of letters a and b instead of numbers 1 and 0, this value must be given as True. This variable is set specifically for traffic network's step function's needs. """ npml = 0 # "no possible modes left" count #viol_cnt = 0 xk_count = len(xk_initialized) iter_uk_crossproduct = product(uk_domain, repeat=uk_count) uk_crossproduct = [] # set list of all possible uk combinations for prod in iter_uk_crossproduct: uk_crossproduct.append(prod) # First construct the traffic network. # In loop, generate trace. check it against the formula, produce the label. Save both tc = 0 while tc < trace_count: f_signal_name = folder_name + "/" + name + "_" + str(tc) f_label_name = f_signal_name + "_label" f_s = open(f_signal_name, 'w') f_l = open(f_label_name, 'w') time = 0 # initialize the states of system inputs xk = xk_initialized xk = xk_tolist(xk) # break the formula into its components formula_list = hf.break_formula(cause_formula) formula_components = hf.give_formula_components(formula_list) # Initialize the checker: stn_viol = STL.SyntaxTreeNode() stn_viol.initialize_node(viol_formula.split(), 0) # Initialize a number representing the last value where uk was not ck for each formula component's left side control_array = np.full((len(formula_list), 1), -1) while time <= duration: # new uk's free values are determined upon old xk and uk values uk_works = False free_control_values = copy.deepcopy(uk_crossproduct) while not uk_works: # set uk randomly from free_control_values rand_index = random.randint( 0, len(free_control_values) - 1) # very weirdly, random.randint(a,b) can give out b uk = list(free_control_values[rand_index]) j = 0 while j in range(len(formula_list)): # check if left side is satisfied by checking if A 1, b-1 (u=c) is satisfied # and if u = c at this randomly generated uk. control_input = formula_components[j][ 0].left_node.metric - xk_count control_input_val = formula_components[j][ 0].left_node.param control_input_length = formula_components[j][ 0].interval.ub + 1 # orjinal formul A 1 1 ise length = 0 if uk[control_input] == control_input_val and ( control_input_length == 0 or time - control_array[j] > control_input_length): # left side is satisfied for A 0 b-2 ( u = c ), check if right formula is satisfied right_side_satisfied = False if formula_components[j][1] == None: right_side_satisfied = True else: copy_stn = copy.deepcopy(formula_components[j][1]) copy_stn.compute_qv( STL.DataPoint(value=xk + uk, time=time)) if copy_stn.qv > 0: right_side_satisfied = True if right_side_satisfied: break j += 1 if j == len(formula_list): uk_works = True else: free_control_values = hf.safe_remove( free_control_values, tuple(uk)) if len(free_control_values) == 0: print("No possible free control combinations left") npml += 1 rand_index = random.randint(0, len(uk_crossproduct) - 1) uk = list(uk_crossproduct[rand_index]) uk_works = True # we found a working uk for the corresponding xk # update all stns and linked_list values with this uk and xk values for i in range(len(formula_list)): if formula_components[i][1] is not None: formula_components[i][1].compute_qv( STL.DataPoint(value=xk + uk, time=time)) control_input = formula_components[i][ 0].left_node.metric - xk_count control_input_val = formula_components[i][0].left_node.param if not uk[control_input] == control_input_val: control_array[ i] = time # en son bu time'da uk[control_input], control_input_val'dan degisikti # compute label, write new xk, uk and label to the file stn_viol.compute_qv(STL.DataPoint(value=xk + uk, time=time)) f_s.write("%s %s\n" % (str(time), " ".join([str(x) for x in xk + uk]))) qual = 0 if stn_viol.qv >= 0 else 1 f_l.write("%s %s\n" % (str(time), str(qual))) # new xk is calculated from this loop's xk and uk values if num_to_let: uk_letters = ['a' if x == 0 else 'b' for x in uk] xk, _ = step_function(xk, uk_letters) else: xk, _ = step_function(xk, uk) xk = xk_tolist(xk) time += 1 f_s.close() f_l.close() print("Done %d" % tc) tc += 1 print("There were no possible modes left for a controller input for " + str(npml) + " times.")
def find_best_formula(heuristic, controllable_formulas): folder_name = 'test_data/toy_example_data/' trace_count = 20 signal_file_base = 'test' signal_file_rest = "" duration = 100 if controllable_formulas: oc_limit_lhs = 1 oc_limit_rhs = 0 oc_limit = [oc_limit_lhs, oc_limit_rhs] else: oc_limit = 2 cause_limit = 1 pc = 8 return_type = stl_constants.__F_03_SCORE withoutS = True upto = False valuation_limit = 0.0001 operator_count_limit_heuristic = 100 print("operator_count_limit = " + str(oc_limit)) print("pc = " + str(pc)) print("return type = " + str(return_type.category)) print("withoutS = " + str(withoutS)) print("heuristic = " + str(heuristic)) if heuristic: print("valuation_limit = " + str(valuation_limit)) else: print("cause_limit = " + str(cause_limit)) print("upto = " + str(upto)) if heuristic: cause_formula_prefix = heuristic_toy_example( pc=pc, folder_name=folder_name, valuation_limit=valuation_limit, trace_count=trace_count, signal_file_base=signal_file_base, operator_count_limit=operator_count_limit_heuristic, return_type=return_type, withoutS=withoutS, controllable_formulas=controllable_formulas ) # returns prefix formula (string) else: best_formula = search_all_search_space_toy_example( cause_limit=cause_limit, pc=pc, return_type=return_type, folder_name=folder_name, trace_count=trace_count, signal_file_base=signal_file_base, upto=upto, operator_count_limit=oc_limit, withoutS=withoutS, controllable_formulas=controllable_formulas) cause_formula_prefix = STL.infix_to_prefix(best_formula) cma.cause_mining_main.print_detailed_result( prefix=1, formula=cause_formula_prefix, folder_name=folder_name, signal_file_base=signal_file_base, signal_file_rest=signal_file_rest, trace_count=trace_count) return cause_formula_prefix