def generate_controller_from_cgt(cgt: CGTGoal, folder_path): assum = [] guaran = [] for elem in cgt.get_ltl_assumptions().cnf: assum.append(elem.formula) guaran.append(cgt.get_ltl_guarantees().formula) # for elem in cgt.get_ltl_guarantees().cnf: # guaran.append(elem.formula) uncontrollable = [] controllable = [] variables = cgt.get_variables() for var in variables: if var.controllable: controllable.append(var.name) else: uncontrollable.append(var.name) save_to_file(generate_controller_input_text(assum, guaran, uncontrollable, controllable), folder_path + "specification.txt") exec_time = 0.0 realizable = False mealy_machine = None realizable, mealy_machine, exec_time = create_controller_if_exists(folder_path + "specification.txt") return realizable, mealy_machine, exec_time
def generate_buchi(formula: LTL, file_path: str): # if platform.system() != "Linux": # print(platform.system() + " is not supported for buchi generation") # return try: dot_file_path = os.path.dirname(file_path) if dot_file_path == "": file_path = results_folder + file_path print(formula) b_formula, new_vars, old_vars = traslate_boolean(formula.formula) print(b_formula) result = subprocess.check_output( ["ltl2tgba", "-B", b_formula, "-d"], encoding='UTF-8', stderr=subprocess.DEVNULL).splitlines() result = [x for x in result if not ('[Büchi]' in x)] result = "".join(result) dot_file_path = os.path.dirname(file_path) dot_file_name = os.path.splitext(file_path)[0] save_to_file(result, dot_file_name + ".dot") src = Source(result, directory=dot_file_path, filename=dot_file_name, format="eps") src.render(cleanup=True) print(dot_file_name + ".eps -> buchi generated") except Exception as e: raise e
def create_general_controller_from_goals(goals: List[CGTGoal], folder_path: str, type: str): assumptions = [] guarantees = [] inputs = set() outputs = set() for goal in goals: assum, guaran, ins, outs = generate_general_controller_inputs_from_goal( ap, rules, goal, complete=True) assumptions.extend(assum) guarantees.extend(guaran) inputs.update(set(ins)) outputs.update(set(outs)) controller_file_name = folder_path + "specification.txt" if type == "AND": save_to_file( generate_controller_input_text(assumptions, guarantees, list(inputs), list(outputs)), controller_file_name) elif type == "OR": save_to_file( generate_controller_input_text([Or(assumptions)], guarantees, list(inputs), list(outputs)), controller_file_name) else: raise Exception("type error, either AND or OR") controller_generated = False trivial = False exec_time = 0.0 try: controller_generated, exec_time = create_controller_if_exists( controller_file_name) except SynthesisException as e: if e.os_not_supported: print("Os not supported for synthesis. Only linux can run strix") elif e.trivial: trivial = True controller_generated = True print( "The assumptions are not satisfiable. The controller is trivial." ) return controller_generated, trivial, exec_time
def create_controller_if_exists( controller_input_file: str) -> Tuple[bool, str, float]: """Return true if controller has been synthesized False otherwise. It also return the time needed""" if platform.system() != "Linux": print(platform.system() + " is not supported for synthesis") raise SynthesisException("os_not_supported") print("controller_input_file: " + controller_input_file) a, g, i, o = parse_controller(controller_input_file) # variables = [var.strip() + ": boolean" for var in i.split(',')] # assumptions_satisfiable = check_satisfiability(variables, a) # # if not assumptions_satisfiable: # raise SynthesisException("trivial") mealy_machine, exec_time = get_controller(a, g, i, o) if mealy_machine.startswith("UNREALIZABLE"): print("UNREALIZABLE") return False, None, exec_time print(controller_input_file + " IS REALIZABLE") dot_file_path = os.path.dirname(controller_input_file) dot_file_name = os.path.splitext(controller_input_file)[0] dot_file_name = dot_file_name.replace("specification", "controller") save_to_file(mealy_machine, dot_file_name + ".dot") print("DOT file generated") src = Source(mealy_machine, directory=dot_file_path, filename=dot_file_name, format="eps") src.render(cleanup=True) print(dot_file_name + ".eps -> mealy machine generated") return True, mealy_machine, exec_time
def generate_controller_from_cgt(cgt: CGTGoal, folder_path, complete): assum, guaran, ins, outs = generate_general_controller_inputs_from_goal( ap, rules, cgt, complete) save_to_file(generate_controller_input_text(assum, guaran, ins, outs), folder_path + "specification.txt") exec_time = 0.0 realizable = False try: controller_generated, exec_time = create_controller_if_exists( folder_path + "specification.txt") realizable = controller_generated except SynthesisException as e: if e.os_not_supported: print("Os not supported for synthesis. Only linux can run strix") elif e.trivial: print( "The assumptions are not satisfiable. The controller is trivial." ) raise Exception( "Assumptions unsatisfiable in a CGT is impossible.") return realizable, exec_time
def run(list_of_goals: List[CGTGoal], result_folder: str): """Print List of Goals""" for g in list_of_goals: print(g) rules_dict = extract_rules(rules) for k, v in rules_dict.items(): print(k) for elem in v: print(elem) """Create new mutex clusters and assign them to the goals""" context_goals = create_contextual_clusters(list_of_goals, "MUTEX", rules_dict["context"]) """Create the CGT based on the clusters""" try: cgt = create_cgt(context_goals, rules_dict) except CGTFailException as e: print(pretty_cgt_exception(e)) sys.exit() save_to_file(str(cgt), result_folder + "/CGT_clustered.txt") save_to_file(str(cgt.print_cgt_detailed()), result_folder + "/CGT_clustered_details.txt") """Try to extent every leaf of the CGT by mapping to the library""" try: extend_cgt(cgt, library, rules_dict) except CGTFailException as e: print(pretty_cgt_exception(e)) sys.exit() save_to_file(str(cgt), result_folder + "/CGT_refined.txt") save_to_file(str(cgt.print_cgt_detailed()), result_folder + "/CGT_refined_detailed.txt") save_to_file(str(cgt.print_cgt_summary()), result_folder + "/CGT_summary.txt") """Generate a controller for each node of the CGT""" generate_controllers_for_cgt(cgt, result_folder + "/all_goals/") save_to_file(str(cgt.print_cgt_summary()), result_folder + "/CGT_summary.txt") save_to_file(str(cgt.pretty_print_cgt_summary()), result_folder + "/CGT_summary_pretty.txt") print(cgt)
def run(list_of_goals: List[CGTGoal], result_folder: str, general_and=False, general_or=False, no_clusters=False, clusters_origianl=False, clusters_mutex=False, complete=True): """Print List of Goals""" for g in list_of_goals: print(g) controller_generated_and = False trivial_and = False controller_generated_or = False trivial_or = False realizable_no_clusters = False no_clusters_exec_time = 0.0 realizables_clustered = [] exec_times_clustered = [] realizables_original = [] exec_times_original = [] goals_res = "" for g in list_of_goals: """Generate controller from goals as is, where the assumptions are in AND""" controller, trivial, exec_time = create_general_controller_from_goals( [g], result_folder + "/goal_list/" + g.name + "/", "AND") if controller: goals_res += g.name + "\t" + "YES\t" + format(exec_time, '.3f') + "sec\n" else: goals_res += g.name + "\t" + "NO\t" + format(exec_time, '.3f') + "sec\n" summary_file_name = result_folder + "/SUMMARY.txt" dirname = os.path.dirname(summary_file_name) if not os.path.exists(dirname): os.makedirs(dirname) with open(summary_file_name, 'w') as f: f.write(pretty_print_goals(ap, rules, goals)) f.write("\nREALIZABILITY OF INDIVIDUAL GOALS\n" + goals_res) f.close() if general_and: """Generate controller from goals as is, where the assumptions are in AND""" controller_generated_and, trivial_and, exec_time_and = create_general_controller_from_goals( list_of_goals, result_folder + "/general_with_and/", "AND") ret = "\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" ret += "GENERAL SPECIFICATION WITH ALL GAOLS: **AND** OF ASSUMPTIONS **AND** OF GUARANTEES\n" ret += "-->\t" + str(len(list_of_goals)) + " goals: " + str( [c.name for c in list_of_goals]) + "\n" if controller_generated_and: ret += "REALIZABLE\tYES\t\t" + format(exec_time_and, '.3f') + "sec\n" else: ret += "REALIZABLE\tNO\t\t" + format(exec_time_and, '.3f') + "sec\n" if trivial_and: ret += "TRIVIAL\tYES\t\t\n" else: ret += "TRIVIAL\tNO\t\t\n" ret += "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n" f = open(summary_file_name, "a+") f.write(ret) f.close() if general_or: """Generate controller from goals as is, where the assumptions are in OR""" controller_generated_or, trivial_or, exec_time_or = create_general_controller_from_goals( list_of_goals, result_folder + "/general_with_or/", "OR") ret = "\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" ret += "GENERAL SPECIFICATION WITH ALL GAOLS: **OR** OF ASSUMPTIONS **AND** OF GUARANTEES\n" ret += "-->\t" + str(len(list_of_goals)) + " goals: " + str( [c.name for c in list_of_goals]) + "\n" if controller_generated_and: ret += "REALIZABLE\tYES\t\t" + format(exec_time_or, '.3f') + "sec\n" else: ret += "REALIZABLE\tNO\t\t" + format(exec_time_or, '.3f') + "sec\n" if trivial_and: ret += "TRIVIAL\tYES\t\t\n" else: ret += "TRIVIAL\tNO\t\t\n" ret += "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n" f = open(summary_file_name, "a+") f.write(ret) f.close() if no_clusters: """No Clustering, Conjunction of all the goals (with saturated G = A->G)""" try: cgt = conjunction(deepcopy(list_of_goals)) except CGTFailException as e: print(pretty_cgt_exception(e)) sys.exit() save_to_file(str(cgt), result_folder + "/CGT_no_clusters/CGT.txt") save_to_file(str(cgt.print_cgt_CROME()), result_folder + "/CGT_no_clusters/CGT_CROME.txt") """Generate a controller from cgt root""" realizable_no_clusters, no_clusters_exec_time = generate_controller_from_cgt( cgt, result_folder + "/CGT_no_clusters/", complete) ret = "\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" ret += "CGT WITH CONJUNCTION OF GOALS\n" ret += "-->\t" + str(len(list_of_goals)) + " goals: " + str( [c.name for c in list_of_goals]) + "\n" if realizable_no_clusters: ret += "REALIZABLE\tYES\t\t" + format(no_clusters_exec_time, '.3f') + "sec\n" else: ret += "REALIZABLE\tNO\t\t" + format(no_clusters_exec_time, '.3f') + "sec\n" ret += "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n" f = open(summary_file_name, "a+") f.write(ret) f.close() """Clustering""" """Create cgt with the goals, it will automatically compose/conjoin them based on the context""" context_goals = create_contextual_clusters(list_of_goals, "MUTEX", rules["context"]) if clusters_mutex: """Create the CGT composing the goals with the context""" try: cgt_1 = create_cgt(context_goals, compose_with_context=True) except CGTFailException as e: print(pretty_cgt_exception(e)) sys.exit() save_to_file(str(cgt_1), result_folder + "/cgt_clusters_mutex/CGT.txt") save_to_file(str(cgt_1.print_cgt_CROME()), result_folder + "/cgt_clusters_mutex/CGT_CROME.txt") """Generate a controller for each branch of the CGT""" realizables_clustered, exec_times_clustered = generate_controllers_from_cgt_clustered( cgt_1, result_folder + "/cgt_clusters_mutex/", complete) ret = "\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" ret += "CGT WITH MUTEX CLUSTERS \t " + str( sum(realizables_clustered)) + "/" + str( len(realizables_clustered)) + " REALIZABLE \n" cluster_goals = cgt_1.refined_by ret += "FEASIBLE CLUSTERS:\t " + str(len(cluster_goals)) + "/" + str( len(context_goals.keys())) for i, goal in enumerate(cluster_goals): ret += "\nCLUSTER " + str(i) + "\n" ret += "SCENARIO:\t" + str( goal.goal_context_to_show.formula) + "\n-->\t" + str( len(goal.refined_by)) + " goals: " + str( [g.name for g in goal.refined_by]) + "\n" if len(realizables_clustered) > 0: if realizables_clustered[i]: ret += "REALIZABLE\tMUTEX \tYES\t\t" + format( exec_times_clustered[i], '.3f') + "sec\n" else: ret += "REALIZABLE\tMUTEX \tNO\t\t" + format( exec_times_clustered[i], '.3f') + "sec\n" ret += "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n" f = open(summary_file_name, "a+") f.write(ret) f.close() if clusters_origianl: """Create the CGT composing the goals without the context""" try: cgt_2 = create_cgt(context_goals, compose_with_context=False) except CGTFailException as e: print(pretty_cgt_exception(e)) sys.exit() save_to_file(str(cgt_2), result_folder + "/CGT_with_clusters/CGT.txt") save_to_file(str(cgt_2.print_cgt_CROME()), result_folder + "/CGT_with_clusters/CGT_CROME.txt") realizables_original, exec_times_original = generate_controllers_from_cgt_clustered( cgt_2, result_folder + "/CGT_with_clusters/", complete) unrealizable_goals = {} ret = "\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" ret += "CGT WITH CLUSTERS \t" + str( sum(realizables_original)) + "/" + str( len(realizables_original)) + " REALIZABLE\n" original_goals = cgt_2.refined_by ret += "FEASIBLE CLUSTERS:\t " + str(len(original_goals)) + "/" + str( len(context_goals.keys())) for i, goal in enumerate(original_goals): ret += "\nCLUSTER " + str(i) + "\n" ret += "SCENARIO:\t" + str( goal.goal_context_to_show.formula) + "\n-->\t" + str( len(goal.refined_by)) + " goals: " + str( [g.name for g in goal.refined_by]) + "\n" if len(realizables_original) > 0: if realizables_original[i]: ret += "REALIZABLE \tYES\t\t" + format( exec_times_original[i], '.3f') + "sec\n" else: ret += "REALIZABLE \tNO\t\t" + format( exec_times_original[i], '.3f') + "sec\n" for g_name in [g.name for g in goal.refined_by]: if g_name in unrealizable_goals.keys(): unrealizable_goals[g_name] += 1 else: unrealizable_goals[g_name] = 1 ret += "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n" ret += "\n~~~~~~~~~~'UNSAT-CORE' - UNREALIZABLE GOALS~~~~~~~~~~~~~~~~\n" sorted_unrealizable_goals = sorted(unrealizable_goals.items(), key=lambda x: x[1], reverse=True) for (g, v) in sorted_unrealizable_goals: ret += g + "\t" + str(v) + "\n" ret += "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n" f = open(summary_file_name, "a+") f.write(ret) f.close() # save_to_file(pretty_print_summary_clustering(list_of_goals, # controller_generated_and, # trivial_and, # controller_generated_or, # trivial_or, # realizable_no_clusters, # context_goals, # realizables_clustered, # realizables_original), # result_folder + "/SUMMARY.txt") print("\nClustering process finished. Results generated.") return realizable_no_clusters, realizables_clustered, realizables_original, no_clusters_exec_time, exec_times_clustered, exec_times_original
for ctx, goals in context_goals.items(): from helper.buchi import generate_buchi g_name = "||".join(g.name for g in goals) generate_buchi(ctx, file_path + "/buchi/" + g_name) # save_to_file(pretty_print_summary_clustering(context_goals), file_path + "/context-goals") try: cgt = create_cgt(context_goals, compose_with_context=False) except CGTFailException as e: print(pretty_cgt_exception(e)) sys.exit() save_to_file(str(cgt), file_path + "/cgt_1_contexual") """Adding Domain Properties (i.e. descriptive statements about the problem world (such as physical laws) E.g. a robot cannot be in two locations at the same time. These properties are intrinsic in each pattern""" # cgt.add_domain_properties() save_to_file(str(cgt), file_path + "/cgt_2_domain") """Adding Domain Hypothesis or Expectations (i.e. prescriptive assumptions on the environment E.g. In the environment of deployment of the mission the item weight 10kg so in order to pick it up there is a new assumption where the 'weight_power' must be at least 10""" expectations = [ Contract(assumptions=Assumptions( Assumption(formula="G(weight_power > 10)", variables=Variables(BoundedNat("weight_power")), kind="expectation")), guarantees=Guarantees( Guarantee(formula="G(heavy_item_pickup)",