Example #1
0
    def __init__(self, locations: List[LTL]):

        variables = Variables()
        pattern_formula = []

        guarantee = "F("
        for n, location in enumerate(locations):
            variables.extend(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)
Example #2
0
    def __iand__(self, other):
        """self &= other
        Modifies self with the conjunction with other"""
        if not isinstance(other, LTL):
            return AttributeError

        if self.context is not None and other.context is not None:
            if self.context != other.context:
                raise DifferentContextException(self.context, other.context)

        if self.context is None and other.context is not None:
            raise DifferentContextException(self.context, other.context)

        """Contexts must be equal"""

        if self.__formula == "TRUE":
            self.__formula = deepcopy(other.formula)
            self.__variables = deepcopy(other.variables)
            self.__cnf = deepcopy(other.cnf)
            return self

        if other.formula == "TRUE":
            return self
        if other.formula == "FALSE":
            self.__formula = "FALSE"
            self.__cnf |= other.cnf
            return self

        self.__formula = And([self.__formula, other.unsaturated])
        self.__variables |= other.variables
        self.__cnf |= other.cnf

        if not self.is_satisfiable():
            raise InconsistentException(self, other)
        return self
Example #3
0
    def __init__(self, locations: List[LTL] = None):
        variables = Variables()
        pattern_formula = []

        formula = ""
        for i, location in enumerate(locations):
            variables.extend(location.variables)
            formula += "F(" + location.formula
            if i < len(locations) - 1:
                formula += " & "
        for i in range(0, len(locations)):
            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) - 1:
                pattern_formula.append("(!" + locations[n].formula + " U (" +
                                       locations[n].formula + " & X(!" +
                                       locations[n].formula + " U(" +
                                       locations[n + 1].formula + "))))")

        pattern_formula = And(pattern_formula)

        super().__init__(pattern_formula, locations, variables)
Example #4
0
def check_satisfiability(variables: List[str],
                         propositions: Union[List[str], str]) -> bool:
    if isinstance(propositions, str):
        propositions = [propositions]

    if len(propositions) == 1 and propositions[0] == "TRUE":
        return True
    if len(propositions) == 0:
        return True
    """Write the NuSMV file"""
    with open(smvfile, 'w') as ofile:

        ofile.write('MODULE main\n')

        ofile.write('VAR\n')

        for v in list(set(variables)):
            ofile.write('\t' + v + ";\n")

        ofile.write('\n')
        ofile.write('LTLSPEC ')
        ofile.write(str(Not(And(propositions))))

        ofile.write('\n')

    try:
        output = subprocess.check_output(
            ['nuXmv', smvfile], encoding='UTF-8',
            stderr=subprocess.DEVNULL).splitlines()
        output = [
            x for x in output
            if not (x[:3] == '***' or x[:7] == 'WARNING' or x == '')
        ]
        for line in output:
            if line[:16] == '-- specification':
                if 'is false' in line:
                    print("\t\t\tSAT:\t" + str(And(propositions)))
                    return True
                elif 'is true' in line:
                    return False

    except Exception as e:
        with open(smvfile, 'r') as fin:
            print(fin.read())
        raise e
Example #5
0
    def __init__(self, locations: List[LTL] = None):
        variables = Variables()
        pattern_formula = []

        for location in locations:
            variables.extend(location.variables)
            pattern_formula.append("G(F(" + location.formula + "))")

        pattern_formula = And(pattern_formula)

        super().__init__(pattern_formula, locations, variables)
Example #6
0
    def __init__(self, locations: List[LTL]):
        variables = Variables()
        pattern_formula = []

        for location in locations:
            variables |= location.variables
            pattern_formula.append("F(" + location.formula + ")")

        pattern_formula = And(pattern_formula)

        super().__init__(pattern_formula, locations, variables)
Example #7
0
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
Example #8
0
def prioritize_goal(first_priority_goal, second_priority_goal):
    pass
    """
    Makes the assumption of one goal dependent on the satisfiability of the assumptions of the second goal
    """
    variables = []
    stronger_assumptions_list = []

    for contract in first_priority_goal.contracts:
        variables |= contract.variables
        stronger_assumptions_list.append(And(contract.assumptions))

    for contract in second_priority_goal.contracts:
        contract.add_variables(variables)
        contract.add_assumptions(Not(Or(stronger_assumptions_list)))
Example #9
0
    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
Example #10
0
    def conjoin_with_formula(self, other: 'LTL') -> bool:
        """Returns True if other has been conjoined"""

        if self.formula == "FALSE":
            print(
                "The conjunction has no effects since the current formula is FALSE"
            )
            return False
        if self.formula == "TRUE":
            self.formula = deepcopy(other.formula)
            self.variables = deepcopy(other.variables)
            return True

        if other.formula == "FALSE":
            self.formula = "FALSE"
            return True
        if other.formula == "TRUE":
            print(
                "The conjunction has no effects since the other formula is FALSE"
            )
            return False

        if other <= self:
            """the other formula is a refinement of the current formula"""
            self.formula = deepcopy(other.formula)
            self.variables = deepcopy(other.variables)
            return True

        if self.is_satisfiable_with(other):

            new_formula = deepcopy(self)
            new_formula.variables.extend(other.variables)
            new_formula.formula = And([new_formula.formula, other.formula])
            """If by conjoining other, the result should be a refinement of the existing formula"""
            if new_formula <= self:
                self.formula = deepcopy(new_formula.formula)
                self.variables = deepcopy(new_formula.variables)
                return True
        else:
            raise InconsistentException(self, other)
Example #11
0
    def __init__(self, locations: List[str] = None):

        conj_list = []

        guarantee = "F("
        for n, location in enumerate(locations):

            guarantee += location
            if n == len(locations) - 1:
                for _ in range(len(locations)):
                    guarantee += ")"
            else:
                guarantee += " & F("

        conj_list.append(guarantee)

        for n, location in enumerate(locations):
            if n < len(locations) - 1:
                conj_list.append("(!" + locations[n + 1] + " U " +
                                 locations[n] + ")")

        super().__init__(locations, And(conj_list))
Example #12
0
    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
Example #13
0
def extract_saturated_guarantees_from(
        goals: Union[CGTGoal, List[CGTGoal]]) -> List[str]:
    if isinstance(goals, CGTGoal):
        goals = [goals]

    assumptions_goals = []
    guarantees_goals = []
    variables_goals = set()

    for goal in goals:
        goal_variables = set()
        goal_new_variables = set()
        goal_old_variables = set()
        assumptions_guarantee_pairs = []
        for contract in goal.contracts:
            a_boolean, a_new_vars, a_old_vars = traslate_boolean(
                str(contract.assumptions.formula))
            g_boolean, g_new_vars, g_old_vars = traslate_boolean(
                str(contract.guarantees.formula))
            vars = [v.name for v in contract.variables.list]
            goal_variables.update(vars)
            a_new_vars.extend(g_old_vars)
            a_old_vars.extend(g_old_vars)
            goal_new_variables.update(a_new_vars)
            goal_old_variables.update(a_old_vars)
            assumptions_guarantee_pairs.append((a_boolean, g_boolean))
        goal_variables = goal_variables - goal_old_variables
        goal_variables.update(goal_new_variables)

        assumptions_goal = Or([a for (a, goal) in assumptions_guarantee_pairs])
        guarantees_goal = And(
            [Implies(a, goal) for (a, goal) in assumptions_guarantee_pairs])

        guarantees_goals.append(guarantees_goal)
        variables_goals.update(goal_variables)

    return guarantees_goals
Example #14
0
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
Example #15
0
    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 = ""
Example #16
0
    def __init__(self, locations: List[str] = None):
        conj_list = []
        for location in locations:
            conj_list.append("G(F(" + location + "))")

        super().__init__(locations, And(conj_list))
Example #17
0
def parse_controller(file_path: str) -> Tuple[str, str, str, str]:
    """Returns: assumptions, guarantees, inputs, outputs"""

    assumptions = []
    guarantees = []
    inputs = []
    outputs = []

    file_header = ""

    with open(file_path, 'r') as ifile:
        for line in ifile:
            line, ntabs = _count_line(line)

            # skip empty lines
            if not line:
                continue

            # parse file header line
            elif ntabs == FILE_HEADER_INDENT:

                if ASSUMPTIONS_HEADER == line:
                    if file_header == "":
                        file_header = line
                    else:
                        Exception("File format not supported")

                elif CONSTRAINTS_HEADER == line:
                    if file_header == ASSUMPTIONS_HEADER:
                        file_header = line
                    else:
                        Exception("File format not supported")

                elif GUARANTEES_HEADER == line:
                    if file_header == CONSTRAINTS_HEADER:
                        file_header = line
                    else:
                        Exception("File format not supported")

                elif INS_HEADER == line:
                    if file_header == GUARANTEES_HEADER:
                        file_header = line
                    else:
                        Exception("File format not supported")

                elif OUTS_HEADER == line:
                    if file_header == INS_HEADER:
                        file_header = line
                    else:
                        Exception("File format not supported")

                elif END_HEADER == line:
                    if file_header == OUTS_HEADER:
                        if len(assumptions) == 0:
                            assumptions.append("true")
                        return And(assumptions), And(guarantees), ",".join(
                            inputs), ",".join(outputs)
                    else:
                        Exception("File format not supported")
                else:
                    raise Exception("Unexpected File Header: " + line)

            else:

                if ASSUMPTIONS_HEADER == file_header:
                    if ntabs == DATA_INDENT:
                        assumptions.append(line.strip())

                if CONSTRAINTS_HEADER == file_header:
                    if ntabs == DATA_INDENT:
                        guarantees.append(line.strip())

                if GUARANTEES_HEADER == file_header:
                    if ntabs == DATA_INDENT:
                        guarantees.append(line.strip())

                if INS_HEADER == file_header:
                    if ntabs == DATA_INDENT:
                        inputs.append(line.strip())

                if OUTS_HEADER == file_header:
                    if ntabs == DATA_INDENT:
                        outputs.append(line.strip())