def get_ltl_assumptions(self) -> LTL: a_list = [] vars = Variables() for c in self.contracts: a_list.append(c.assumptions.formula.formula) vars.extend(c.assumptions.formula.variables) new_formula = Or(a_list) return LTL(new_formula, vars)
def get_ltl_guarantees(self) -> LTL: g_list = [] vars = Variables() for c in self.contracts: g_list.append(c.guarantees.formula.formula) vars.extend(c.guarantees.formula.variables) new_formula = And(g_list) return LTL(new_formula, vars)
def extract_ltl_rules(context_rules: Dict) -> List[LTL]: """Dict: ltl_formula -> list_of_variables_involved""" ltl_list: List[LTL] = [] if "mutex" in context_rules: for cvars in context_rules["mutex"]: if len(cvars) > 0: variables: Variables = Variables() ltl = "G(" for vs in cvars: variables.extend(vs.variables) cvars_str = [n.formula for n in cvars] clauses = [] for vs_a in cvars_str: clause = [] clause.append(deepcopy(vs_a)) for vs_b in cvars_str: if vs_a is not vs_b: clause.append(Not(deepcopy(vs_b))) clauses.append(And(clause)) ltl += Or(clauses) ltl += ")" ltl_list.append(LTL(formula=ltl, variables=variables)) if "inclusion" in context_rules: for cvars in context_rules["inclusion"]: if len(cvars) > 0: variables: Variables = Variables() ltl = "G(" for i, vs in enumerate(cvars): variables.extend(vs.variables) ltl += str(vs) if i < (len(cvars) - 1): ltl += " -> " ltl += ")" ltl_list.append(LTL(formula=ltl, variables=variables)) if "liveness" in context_rules: for cvars in context_rules["liveness"]: variables: Variables = Variables() ltl = "G( F(" variables.extend(cvars.variables) ltl += str(cvars) ltl += "))" ltl_list.append(LTL(formula=ltl, variables=variables)) return ltl_list
def __init__(self, patterns: List[LTL]): self.patterns = patterns variables = Variables() guarantees = [] for p in patterns: variables.extend(p.variables) guarantees.append(Guarantee(p.formula, p.variables)) guarantees = Guarantees(guarantees) super().__init__(guarantees=guarantees)
def generate_general_controller_inputs_from_goal( ap: dict, rules: dict, goal: CGTGoal, complete=True) -> Tuple[List[str], List[str], List[str], List[str]]: variables = Variables() assumptions = [] guarantees = [] """Adding A/G from the goal""" a = goal.get_ltl_assumptions().formula if a != "TRUE": assumptions.append(a) g = goal.get_ltl_guarantees().formula if g != "TRUE": guarantees.append(g) variables.extend(goal.get_variables()) """Adding liveness rules of the environemnt as assumptions""" liveness_rules = extract_ltl_rules(rules["environment"]) for r in liveness_rules: variables.extend(r.variables) assumptions.append(r.formula) """Adding domain rules of the robot as guarantees""" domain_rules = extract_ltl_rules(rules["domain"]) for r in domain_rules: variables.extend(r.variables) guarantees.append(r.formula) """Adding context rules as assumptions if not already included (cgt includes them)""" if complete: context_rules = extract_ltl_rules(rules["context"]) for r in context_rules: variables.extend(r.variables) assumptions.append(r.formula) # """Replacing TRUE with true, for strix""" # for a in assumptions: # a.replace("TRUE", "true") # for g in guarantees: # g.replace("TRUE", "true") uncontrollable = [] controllable = [] """Splitting the variables between uncontrollable and controllable""" for v in variables.list: if v.name in ap["s"]: uncontrollable.append(v.name) else: controllable.append(v.name) return assumptions, guarantees, uncontrollable, controllable
def __init__(self, locations: List[LTL] = None): variables = Variables() pattern_formula = [] formula = "G(" for i, location in enumerate(locations): variables |= location.variables formula += "F(" + location.formula if i < len(locations) - 1: formula += " & " for i in range(0, len(locations)): formula += ")" formula += ")" pattern_formula.append(formula) for n, location in enumerate(locations): if n < len(locations) - 1: pattern_formula.append("(!" + locations[n + 1].formula + " U " + locations[n].formula + ")") for n, location in enumerate(locations): if n < len(locations): pattern_formula.append( "G(" + locations[(n + 1) % len(locations)].formula + " -> " + "X((!" + locations[(n + 1) % len(locations)].formula + ") U " + locations[n].formula + "))") pattern_formula = And(pattern_formula) super().__init__(pattern_formula, locations, variables)
def __init__(self, locations: List[LTL]): variables = Variables() pattern_formula = [] guarantee = "F(" for n, location in enumerate(locations): variables |= location.variables guarantee += location.formula if n == len(locations) - 1: for _ in range(len(locations)): guarantee += ")" else: guarantee += " & F(" pattern_formula.append(guarantee) for n, location in enumerate(locations): if n < len(locations) - 1: pattern_formula.append("(!" + locations[n + 1].formula + " U " + locations[n].formula + ")") pattern_formula = And(pattern_formula) super().__init__(pattern_formula, locations, variables)
def __rshift__(self, other: 'LTL') -> 'LTL': """>> self Returns a new LTL that is the result of self -> other (implies)""" return LTL( formula=Implies(self.formula, other.formula), variables=Variables(self.variables | other.variables) )
def __init__(self, assumptions_str: List[str], guarantees_str: List[str]): assumptions = [] guarantees = [] for a in assumptions_str: assumptions.append(Assumption(a, Variables(Boolean(a)))) for g in guarantees_str: guarantees.append(Guarantee(g, Variables(Boolean(g)))) assumptions = Assumptions(assumptions) guarantees = Guarantees(guarantees) guarantees.saturate_with(assumptions) super().__init__(assumptions=assumptions, guarantees=guarantees)
def remove(self, element): self.cnf.remove(element) if len(self.cnf) == 0: self.__formula: str = "TRUE" self.__cnf: Set['LTL'] = {self} self.__variables: Variables = Variables() return cnf_str = [x.formula for x in self.cnf] self.__formula: str = And(cnf_str) self.__variables: Variables = Variables() variables = set() for x in self.cnf: variables.add(x.variables) self.__variables &= variables
def __or__(self, other): """self | other Returns a new LTL with the disjunction with other""" if not isinstance(other, LTL): return AttributeError formula = Or([self.formula, other.formula]) variables = Variables(self.variables | other.variables) return LTL(formula=formula, variables=variables)
def __init__(self, assumptions_str: List[str], guarantees_str: List[str]): assumptions = set() guarantees = set() for a in assumptions_str: assumptions.add(LTL(a, Variables({Boolean(a)}))) for g in guarantees_str: guarantees.add(LTL(g, Variables({Boolean(g)}))) assumptions = LTL(cnf=assumptions) guarantees = LTL(cnf=guarantees) guarantees.saturate_with(assumptions) super().__init__(assumptions=assumptions, guarantees=guarantees)
def __init__(self, locations: List[LTL] = None): variables = Variables() pattern_formula = [] for location in locations: variables |= location.variables pattern_formula.append("G(F(" + location.formula + "))") pattern_formula = And(pattern_formula) super().__init__(pattern_formula, locations, variables)
def get_ltl_assumptions(self) -> LTL: if len(self.contracts) > 1: """conjunction""" a_list = [] vars = Variables() for c in self.contracts: a_list.append(c.assumptions.formula) vars |= c.assumptions.variables new_formula = Or(a_list) return LTL(new_formula, vars, skip_checks=True) else: """composition""" return self.contracts[0].assumptions
def __init__(self, formulae: List['LTL'], simplify=True): "formulae: list of formula to conjoin" "LTL formula" self.__formula: LTL = None "List of LTL formulae in conjunction that it is formed of" self.__list: List[LTL] = None if len(formulae) == 0: self.__formula: LTL = LTL("TRUE") self.__list: List[LTL] = [] else: if simplify: self.__formula: LTL = LTL(formulae[0].formula, formulae[0].variables) self.__list: List[LTL] = [formulae[0]] if len(formulae) > 1: try: added_formulae = self.__formula.conjoin_with(formulae[1:]) self.list.extend(added_formulae) except InconsistentException as e: raise e else: variables = Variables() formulae_str = [] for formula in formulae: variables.extend(formula.variables) formulae_str.append(formula.formula) try: self.__formula: LTL = LTL(And(formulae_str), variables) except InconsistentException as e: raise e self.__list: List[LTL] = formulae
def __init__(self, patterns: List[LTL]): self.patterns = patterns variables = Variables() guarantees = set() for p in patterns: guarantees.add(p) # variables |= p.variables # guarantees.add(LTL(p.formula, p.variables)) guarantees = LTL(cnf=guarantees) super().__init__(guarantees=guarantees)
def __init__(self, locations: List[LTL]): variables = Variables() pattern_formula = "F(" for n, location in enumerate(locations): variables |= location.variables pattern_formula += location.formula if n == len(locations) - 1: for _ in range(len(locations)): pattern_formula += ")" else: pattern_formula += " & F(" super().__init__(pattern_formula, locations, variables)
def __init__(self, formula: str, variables: Variables = None): if (formula == "TRUE" or formula == "FALSE") and variables is None: self.__formula: str = formula self.__variables: Variables = Variables() return if formula is not None: if variables is None: variables = extract_variable(str(formula)) self.__formula: str = formula self.__variables: Variables = variables if not self.is_satisfiable(): raise InconsistentException(self, self)
def add_constraints_to_all_contexts(comb_contexts: List[List[LTL]], rules: List[LTL], add_to_all=False): if add_to_all: """Add all rules to all the combinations""" for comb in comb_contexts: for rule in rules: comb.append(rule) else: """Add rules only to the combinations that predicate on the rule""" for comb in comb_contexts: comb_variables = Variables() for c in comb: comb_variables |= c.variables for rule in rules: if len(comb_variables & rule.variables) > 0: comb.append(rule)
def get_ltl_saturated_guarantees(self) -> LTL: assumptions_guarantee_pairs = [] vars = Variables() for c in self.contracts: assumptions_guarantee_pairs.append( (c.assumptions.formula.formula, c.guarantees.formula.formula)) vars.extend(c.assumptions.formula.variables) vars.extend(c.guarantees.formula.variables) new_formula = [] for ag_pairs in assumptions_guarantee_pairs: new_formula.append(Implies(ag_pairs[0], ag_pairs[1])) new_formula = And(new_formula) return LTL(new_formula, vars)
def __ior__(self, other): """self |= other Modifies self with the disjunction with other""" if not isinstance(other, LTL): return AttributeError if self.__formula == "TRUE": return self if other.formula == "FALSE": return self if other.formula == "TRUE": self.__formula = "TRUE" self.__cnf |= other.cnf return self self.__formula = Or([self.formula, other.formula]) self.__variables = Variables(self.variables | other.variables) # """TODO: maybe not needed""" # if not self.is_satisfiable(): # raise InconsistentException(self, other) return self
def get_variables(self) -> Variables: vars = Variables() for c in self.contracts: vars.extend(c.guarantees.formula.variables) vars.extend(c.assumptions.formula.variables) return vars
def extract_rules(rules: Dict) -> Dict: """Translates the rules in LTL formulae and returnes a dictionary of 5 cathegories""" """Dictionary to return""" rules_ltl = {} if "gridworld" in rules: rules_ltl["gridworld"] = [] for elem, adjacent in rules["gridworld"].items(): ltl = "G(" ltl += elem.formula + " -> X (" ltl += " | ".join([a.formula for a in adjacent]) ltl += "))" variables = Variables() variables |= elem.variables for a in adjacent: variables |= a.variables rules_ltl["gridworld"].append( LTL(formula=ltl, variables=variables, kind="gridworld")) if "context" in rules: rules_ltl["context"] = [] if "mutex" in rules["context"]: for mtx_elements in rules["context"]["mutex"]: if len(mtx_elements) > 0: variables: Variables = Variables() ltl = "G(" for vs in mtx_elements: variables |= vs.variables mtx_elements_str = [n.formula for n in mtx_elements] clauses = [] for vs_a in mtx_elements_str: clause = [deepcopy(vs_a)] for vs_b in mtx_elements_str: if vs_a is not vs_b: clause.append(Not(deepcopy(vs_b))) clauses.append(And(clause)) ltl += Or(clauses) ltl += ")" rules_ltl["context"].append( LTL(formula=ltl, variables=variables, kind="context")) if "inclusion" in rules["context"]: for pre, post in rules["context"]["inclusion"].items(): variables = Variables() variables |= pre.variables | post.variables ltl = "G((" + pre.formula + ") -> (" + post.formula + "))" rules_ltl["context"].append( LTL(formula=ltl, variables=variables, kind="context")) if "context_gridworld" in rules: rules_ltl["context_gridworld"] = [] for pre, post in rules["context_gridworld"].items(): variables = Variables() variables |= pre.variables | post.variables ltl = "G((" + pre.formula + ") -> (" + post.formula + "))" rules_ltl["context_gridworld"].append( LTL(formula=ltl, variables=variables, kind="context_gridworld")) if "constraints" in rules: rules_ltl["constraints"] = [] if "mutex" in rules["constraints"]: for mtx_elements in rules["constraints"]["mutex"]: if len(mtx_elements) > 0: variables: Variables = Variables() ltl = "G(" for vs in mtx_elements: variables |= vs.variables mtx_elements_str = [n.formula for n in mtx_elements] clauses = [] for vs_a in mtx_elements_str: clause = [deepcopy(vs_a)] for vs_b in mtx_elements_str: if vs_a is not vs_b: clause.append(Not(deepcopy(vs_b))) clauses.append(And(clause)) ltl += Or(clauses) ltl += ")" rules_ltl["constraints"].append( LTL(formula=ltl, variables=variables, kind="constraints")) if "inclusion" in rules["constraints"]: for pre, post in rules["constraints"]["inclusion"].items(): variables = Variables() variables |= pre.variables | post.variables ltl = "G((" + pre.formula + ") -> (" + post.formula + "))" rules_ltl["constraints"].append( LTL(formula=ltl, variables=variables, kind="constraints")) return rules_ltl
def get_variables(self) -> Variables: vars = Variables() for c in self.contracts: vars |= c.guarantees.variables vars |= c.assumptions.variables return vars
def __init__(self, trigger: LTL, reaction: LTL): pattern_formula = "G( (({t}) -> X({r})) & (X({r}) -> ({t})))".format( t=trigger.formula, r=reaction.formula) super().__init__(pattern_formula, Variables(trigger.variables | reaction.variables))
def __init__(self, formula: str = None, variables: Variables = None, cnf: Set['LTL'] = None, kind: str = None, context: 'LTL' = None, skip_checks: bool = False): """Basic LTL formula. It can be build by a single formula (str) or by a conjunction of other LTL formulae (CNF form)""" self.__saturation = None if formula is not None and cnf is None: if variables is None: variables = extract_variable(str(formula)) """String representing the LTL""" self.__formula: str = formula """Variables present in the formula""" self.__variables: Variables = variables """Set of LTL that conjoined result in the formula""" self.__cnf: Set['LTL'] = {self} """Adding context""" self.__context = context if not skip_checks: if not self.is_satisfiable(): raise InconsistentException(self, self) elif cnf is not None and formula is None: cnf_str = [x.formula for x in cnf] self.__formula: str = And(cnf_str) self.__variables: Variables = Variables() for x in cnf: self.__variables |= x.variables self.__cnf: Set[Union['LTL']] = cnf """Adding context""" self.__context = context if not skip_checks and len(cnf) > 1: if not self.is_satisfiable(): raise InconsistentException(self, self) elif cnf is None and formula is None: self.__formula: str = "TRUE" self.__cnf: Set['LTL'] = {self} self.__variables: Variables = Variables() self.__context = None else: raise Exception("Wrong parameters LTL construction") if kind is not None: self.__kind: str = kind else: self.__kind: str = ""