Пример #1
0
    def __init__(self,
                 atom: Union[Atom, str] = None,
                 kind: FormulaKind = None):

        if kind is None:
            self.__kind = FormulaKind.UNDEFINED
        self.__kind = kind

        if self.__kind == FormulaKind.REFINEMENT_RULES or \
                self.__kind == FormulaKind.ADJACENCY_RULES or \
                self.__kind == FormulaKind.MUTEX_RULES:
            self.__spec_kind = SpecKind.RULE
        else:
            self.__spec_kind = SpecKind.UNDEFINED

        if isinstance(atom, str) and atom == "TRUE":
            from specification.atom import Atom
            new_atom = Atom("TRUE")
            self.__cnf: List[Set[Atom]] = [{new_atom}]
            self.__dnf: List[Set[Atom]] = [{new_atom}]

        elif isinstance(atom, str) and atom == "FALSE":
            from specification.atom import Atom
            new_atom = Atom("FALSE")
            self.__cnf: List[Set[Atom]] = [{new_atom}]
            self.__dnf: List[Set[Atom]] = [{new_atom}]

        elif atom is not None:
            self.__cnf: List[Set[Atom]] = [{atom}]
            self.__dnf: List[Set[Atom]] = [{atom}]

        else:
            raise Exception("Wrong parameters LTL_forced construction")
Пример #2
0
    def __iand__(self, other: Union[Formula, Atom]) -> Formula:
        """self &= other
        Modifies self with the conjunction with other"""
        from specification.atom import Atom
        if isinstance(other, Atom):
            other = Formula(other)

        if other.is_false():
            new_atom = Atom("FALSE")
            self.__cnf: List[Set[Atom]] = [{new_atom}]
            self.__dnf: List[Set[Atom]] = [{new_atom}]
            return self

        if other.is_true():
            return self

        if other.is_true():
            self.__cnf = other.cnf
            self.__dnf = other.dnf
            return self

        if self.is_true():
            new_other = deepcopy(other)
            self.__cnf: List[Set[Atom]] = new_other.cnf
            self.__dnf: List[Set[Atom]] = new_other.dnf
            return self

        new_other = deepcopy(other)
        """Mutex Rules necessary for Satisfiability Check"""
        mutex_rules = Atom.extract_mutex_rules(self.typeset | other.typeset)
        """Cartesian product between the two dnf"""
        temp_dnf = []
        for a, b in itertools.product(self.dnf, new_other.dnf):

            new_set = a | b

            check_formula = LogicTuple.and_([f.formula() for f in new_set])
            """Adding Rules"""
            if mutex_rules is not None:
                check_formula = LogicTuple.and_(
                    [check_formula, mutex_rules.formula()])

            if Nuxmv.check_satisfiability(check_formula):
                temp_dnf.append(new_set)

        if len(temp_dnf) == 0:
            raise NotSatisfiableException(self, other, mutex_rules)
        else:
            self.__dnf = temp_dnf
        """Append to list if not already there"""
        for other_elem in new_other.cnf:
            if other_elem not in self.cnf:
                self.__cnf.append(other_elem)

        return self
Пример #3
0
    def __init__(self, supertypes: Dict[AllTypes, Set[AllTypes]]):
        super().__init__(atom=Atom("TRUE"), kind=FormulaKind.REFINEMENT_RULES)

        for key_type, set_super_types in supertypes.items():
            if isinstance(key_type, Boolean):
                for super_type in set_super_types:
                    f = Logic.g_(Logic.implies_(key_type.name,
                                                super_type.name))
                    t = Typeset({key_type, super_type})
                    new_atom = Atom(formula=(f, t),
                                    kind=AtomKind.REFINEMENT_RULE)
                    self.__iand__(new_atom)
Пример #4
0
    def __ior__(self, other: Union[Formula, Atom]) -> Formula:
        """self |= other
        Modifies self with the disjunction with other"""
        from specification.atom import Atom
        if isinstance(other, Atom):
            other = Formula(other)

        if self.is_true():
            return self

        if other.is_true():
            new_atom = Atom("TRUE")
            self.__cnf: List[Set[Atom]] = [{new_atom}]
            self.__dnf: List[Set[Atom]] = [{new_atom}]
            return self

        if other.is_false():
            return self

        new_other = deepcopy(other)
        """Cartesian product between the two cnf"""
        temp_cnf = []
        for a, b in itertools.product(self.cnf, new_other.cnf):

            new_set = a | b

            check_formula = LogicTuple.or_([f.formula() for f in new_set])
            if not Nuxmv.check_validity(check_formula):
                temp_cnf.append(new_set)
            else:
                pass

        if len(temp_cnf) == 0:
            """Result is TRUE"""
            new_atom = Atom("TRUE")
            self.__cnf: List[Set[Atom]] = [{new_atom}]
            self.__dnf: List[Set[Atom]] = [{new_atom}]
            return self
        else:
            self.__cnf = temp_cnf
        """Append to list if not already there"""
        for other_elem in new_other.dnf:
            if other_elem not in self.dnf:
                self.__dnf.append(other_elem)

        return self
Пример #5
0
    def is_satisfiable(self) -> bool:

        sat_check_formula = self.formula()
        """If does not contain Mutex Rules already, extract them and check the satisfiability"""
        from specification.atom import Atom
        mutex_rules = Atom.extract_mutex_rules(self.typeset)
        if mutex_rules is not None:
            sat_check_formula = LogicTuple.and_(
                [self.formula(), mutex_rules.formula()])

        return Nuxmv.check_satisfiability(sat_check_formula)
Пример #6
0
 def __le__(self: Specification, other: Specification):
     """self <= other. True if self is a refinement of other"""
     if other.is_true():
         return True
     """Check if self -> other is valid, considering the refinement rules r"""
     """((r & s1) -> s2) === r -> (s1 -> s2)"""
     from specification.atom import Atom
     refinement_rules = Atom.extract_refinement_rules(self.typeset
                                                      | other.typeset)
     if refinement_rules is not None:
         # ref_check_formula = (self & refinement_rules) >> other
         ref_check_formula = LogicTuple.implies_(
             LogicTuple.and_([self.formula(),
                              refinement_rules.formula()]), other.formula())
     else:
         # ref_check_formula = self >> other
         ref_check_formula = LogicTuple.implies_(self.formula(),
                                                 other.formula())
     return Nuxmv.check_validity(ref_check_formula)
Пример #7
0
    def create_transition_controller(self, start: Types, finish: Types, t_trans: int) -> Controller:

        t_controller_name = f"TRANS_{start.name}->{finish.name}"

        if self.session_name is None:
            folder_name = f"{self.t_controllers_folder_name}/{t_controller_name}"
        else:
            folder_name = f"{self.session_name}/{self.t_controllers_folder_name}/{t_controller_name}"

        typeset = Typeset({start, finish})
        realizable = False
        for n_steps in range(1, t_trans):
            trans_spec_str = Logic.and_([start.name, Logic.xn_(finish.name, n_steps)])
            trans_spec = Atom(formula=(trans_spec_str, typeset))
            trans_contract = Contract(guarantees=trans_spec)
            try:
                controller_info = trans_contract.get_controller_info(world_ts=self.world.typeset)
                a, g, i, o = controller_info.get_strix_inputs()
                controller_synthesis_input = StringMng.get_controller_synthesis_str(controller_info)
                Store.save_to_file(controller_synthesis_input,
                                   f"t_controller_{start.name}_{finish.name}_specs.txt", folder_name)
                realized, kiss_mealy, time = Strix.generate_controller(a, g, i, o)
                if realized:
                    realizable = True
                    break
            except ControllerException as e:
                raise TransSynthesisFail(self, e)
        if not realizable:
            raise Exception(
                f"Controller [{start.name}, {finish.name}] cannot be synthetized in {t_trans} steps")
        else:
            Store.save_to_file(kiss_mealy, f"{start.name}_{finish.name}_mealy",
                               folder_name)
            # Store.generate_eps_from_dot(dot_mealy, f"{start.name}_{finish.name}_dot",
            #                             folder_name)

            t_controller = Controller(mealy_machine=kiss_mealy, world=self.world, name=t_controller_name,
                                      synth_time=time)
            Store.save_to_file(str(t_controller), f"{start.name}_{finish.name}_table", folder_name)

            return t_controller
Пример #8
0
    def _remove_atoms(self, atoms_to_remove: Set[Atom]):
        """Remove Atoms from Formula"""

        if len(atoms_to_remove) == 1 and list(atoms_to_remove)[0].is_true():
            return
        """Remove from CNF"""
        for clause in self.__dnf:
            clause -= atoms_to_remove
        """Remove from CNF"""
        clause_cnf_to_remove = set()
        for clause in self.__cnf:
            """Remove clause if contains atoms to be removed"""
            if clause & atoms_to_remove:
                clause_cnf_to_remove |= clause
        """Filter out clauses"""
        for clause in list(self.cnf):
            if len(clause & clause_cnf_to_remove) > 0:
                self.__cnf.remove(clause)

        if len(self.atoms) == 0:
            new_atom = Atom("TRUE")
            self.__cnf: List[Set[Atom]] = [{new_atom}]
            self.__dnf: List[Set[Atom]] = [{new_atom}]
Пример #9
0
    def get_controller_info(self, world_ts: Typeset = None) -> SynthesisInfo:
        """Extract All Info Needed to Build a Controller from the Contract"""

        if world_ts is None:
            world_ts = Typeset()
        """Assumptions"""
        a_initial: List[str] = []
        a_fairness: List[str] = []
        a_safety: List[str] = []
        a_mutex: List[str] = []
        """Guarantees"""
        g_initial: List[str] = []
        g_safety: List[str] = []
        g_mutex: List[str] = []
        g_goal: List[str] = []

        a_typeset = Typeset()
        g_typeset = Typeset()

        list, typeset = self.assumptions.formula(FormulaOutput.ListCNF)
        a_initial.extend(list)
        a_typeset |= typeset

        list, typeset = self.guarantees.formula(FormulaOutput.ListCNF)
        g_goal.extend(list)
        g_typeset |= typeset

        all_typeset = a_typeset | g_typeset | world_ts
        """Inputs typeset"""
        i_typeset = Typeset(all_typeset.extract_inputs())
        """Output typeset"""
        o_typeset = Typeset(all_typeset.extract_outputs())

        actions_typeset = Typeset(all_typeset.ext())
        """Mutex"""
        ret = Atom.extract_mutex_rules(i_typeset, output=FormulaOutput.ListCNF)
        if ret is not None:
            rules, typeset = ret
            a_mutex.extend(rules)
        ret = Atom.extract_mutex_rules(o_typeset, output=FormulaOutput.ListCNF)
        if ret is not None:
            rules, typeset = ret
            g_mutex.extend(rules)
        """For the rules we extracts rules from the variables based on assumptions and inputs"""
        a_typeset = a_typeset | i_typeset
        """We remove the inputs typeset from the guarantees and we incorporate the variables ts"""
        g_typeset = g_typeset - i_typeset
        """Adding Mutex Rules"""
        ret = Atom.extract_mutex_rules(a_typeset, output=FormulaOutput.ListCNF)
        if ret is not None:
            rules, typeset = ret
            a_mutex.extend(rules)
            a_typeset |= typeset

        ret = Atom.extract_mutex_rules(g_typeset, output=FormulaOutput.ListCNF)
        if ret is not None:
            rules, typeset = ret
            g_mutex.extend(rules)
            g_typeset |= typeset
        """Adjacecy rules can include things that are in the world_ts"""
        if world_ts is not None:
            adjacency_ts = g_typeset | world_ts
        else:
            adjacency_ts = g_typeset

        ret = Atom.extract_adjacency_rules(adjacency_ts,
                                           output=FormulaOutput.ListCNF)
        if ret is not None:
            rules, typeset = ret
            g_adjacency.extend(rules)
            g_typeset |= typeset
        """Adding Liveness To Sensors (input)"""
        ret = Atom.extract_liveness_rules(i_typeset,
                                          output=FormulaOutput.ListCNF)
        if ret is not None:
            rules, typeset = ret
            a_liveness.extend(rules)
        """Extract Inputs and Outputs"""
        inputs = [t.name for t in (a_typeset | g_typeset).extract_inputs()]
        outputs = [t.name for t in (a_typeset | g_typeset).extract_outputs()]

        return SynthesisInfo(a_initial=assumptions,
                             a_fairness=a_liveness,
                             a_mutex=a_mutex,
                             guarantees=guarantees,
                             g_mutex=g_mutex,
                             g_safety=g_adjacency,
                             inputs=inputs,
                             outputs=outputs)
Пример #10
0
 def to_atom(self):
     from specification.atom import Atom, AtomKind
     from typeset import Typeset
     return Atom(formula=(self.name, Typeset({self})),
                 check=False,
                 kind=AtomKind.LOCATION)
Пример #11
0
    def __init__(self, name: str = "c"):
        super().__init__(name)


class GoD(ReachLocation):

    def __init__(self, name: str = "d"):
        super().__init__(name)


a = GoA()
b = GoB()
c = GoC()
d = GoD()

a = Atom((a.name, Typeset({a})))
b = Atom((b.name, Typeset({b})))

c = Atom((c.name, Typeset({c})))
d = Atom((d.name, Typeset({d})))

test = a >> ~ a

print(test.formula(FormulaOutput.CNF)[0])
print(test.formula(FormulaOutput.DNF)[0])

one = a & b

print("\none")
print(one.formula(FormulaOutput.CNF)[0])
print(one.formula(FormulaOutput.DNF)[0])
Пример #12
0
 def to_atom(self):
     from specification.atom import Atom
     from typeset import Typeset
     return Atom(formula=(self.name, Typeset({self})), check=False)
Пример #13
0
                K1(),
                # K2(),
                K3(),
                # R1(),
                # R2(),
            },
            sensors={
                ObjectRecognized(),
                Alexa(),
                GroceriesRecognized()
            },
            contexts={
                Housekeeping(),
                Party(),
                Cleanup(),
                Groceries(),
                Garbage()
            })


if __name__ == '__main__':
    w = RobocupHome()
    a_rules, a_ts = Atom.extract_mutex_rules(w.typeset, output=FormulaOutput.ListCNF)
    m_rules, m_ts = Atom.extract_adjacency_rules(w.typeset, output=FormulaOutput.ListCNF)

    print("\n".join(m_rules))
    print(", ".join(m_ts.keys()))
    print("\n\n")
    print("\n".join(a_rules))
    print(", ".join(a_ts.keys()))
Пример #14
0
    def get_controller_info(self, world_ts: Typeset = None) -> SynthesisInfo:
        """Extract All Info Needed to Build a Controller from the Contract"""

        """Assumptions"""
        assumptions = []
        a_mutex = []
        a_liveness = []

        """Guarantees"""
        guarantees = []
        g_mutex = []
        g_adjacency = []

        a_typeset = Typeset()
        g_typeset = Typeset()

        list, typeset = self.assumptions.formula(FormulaOutput.ListCNF)
        assumptions.extend(list)
        a_typeset |= typeset

        list, typeset = self.guarantees.formula(FormulaOutput.ListCNF)
        guarantees.extend(list)
        g_typeset |= typeset

        if world_ts is not None:
            instance_ts = Typeset.get_instance_ts((a_typeset | g_typeset), world_ts)
        else:
            instance_ts = (a_typeset | g_typeset)

        """Extracting Inputs and Outputs Including the variables"""
        i_set, o_set = instance_ts.extract_inputs_outputs()

        i_typeset = Typeset(i_set)
        o_typeset = Typeset(o_set)

        """Mutex Rules"""
        ret = Atom.extract_mutex_rules(i_typeset, output=FormulaOutput.ListCNF)
        if ret is not None:
            rules, typeset = ret
            a_mutex.extend(rules)

        ret = Atom.extract_mutex_rules(o_typeset, output=FormulaOutput.ListCNF)
        if ret is not None:
            rules, typeset = ret
            g_mutex.extend(rules)

        """Adjacecy Rules"""
        ret = Atom.extract_adjacency_rules(o_typeset, output=FormulaOutput.ListCNF)
        if ret is not None:
            rules, typeset = ret
            g_adjacency.extend(rules)

        """Adding Liveness To Sensors (input)"""
        ret = Atom.extract_liveness_rules(i_typeset, output=FormulaOutput.ListCNF)
        if ret is not None:
            rules, typeset = ret
            a_liveness.extend(rules)

        """Adding context and active signal rules"""
        ret = Atom.context_active_rules(i_typeset, output=FormulaOutput.ListCNF)
        if ret is not None:
            rules, typeset = ret
            assumptions.extend(rules)

        """Extract Inputs and Outputs"""
        inputs = [t.name for t in i_set]
        outputs = [t.name for t in o_set]

        return SynthesisInfo(assumptions=assumptions,
                             a_liveness=a_liveness,
                             a_mutex=a_mutex,
                             guarantees=guarantees,
                             g_mutex=g_mutex,
                             g_adjacency=g_adjacency,
                             inputs=inputs,
                             outputs=outputs)