示例#1
0
def test_dnf_form() -> None:
    assert venn_from_str('1 & 2', int).to_dnf_set().is_equivalent_to(
        venn_from_str('1 & 2', int))
    assert venn_from_str('1 | 2', int).to_dnf_set().is_equivalent_to(
        venn_from_str('1 | 2', int))
    assert UniversalSet().to_dnf_set().is_equivalent_to(UniversalSet())
    assert EmptySet().to_dnf_set().is_equivalent_to(EmptySet())
示例#2
0
def test_superset_subset_for_unary_sets() -> None:
    # UniversalSet == UniversalSet
    assert UniversalSet().is_superset_of(UniversalSet())
    assert UniversalSet().is_subset_of(UniversalSet())

    # UniversalSet contains all other sets
    assert UniversalSet().is_superset_of(EmptySet())
    assert UniversalSet().is_superset_of(ValueSet(1))

    # EmptySet is contained in all sets
    assert EmptySet().is_subset_of(EmptySet())
    assert EmptySet().is_superset_of(EmptySet())
    assert EmptySet().is_subset_of(ValueSet(2))

    # PropertySets <-> PropertySets
    assert ValueSet(2).is_superset_of(ValueSet(2))
    assert ValueSet(2).is_subset_of(ValueSet(2))
    assert not ValueSet(2).is_subset_of(ValueSet(3))
    assert not ValueSet(2).is_superset_of(ValueSet(3))

    # PropertySet <-> UniversalSet
    assert ValueSet(1).is_subset_of(UniversalSet())
    assert not UniversalSet().is_subset_of(ValueSet(1))
    assert UniversalSet().is_superset_of(ValueSet(1))
    assert not ValueSet(1).is_superset_of(UniversalSet())

    # PropertySet <-> EmptySet
    assert ValueSet(2).is_superset_of(EmptySet())
    assert not EmptySet().is_superset_of(ValueSet(2))
    assert EmptySet().is_subset_of(ValueSet(1))
    assert not ValueSet(1).is_subset_of(EmptySet())
示例#3
0
def with_connectivity_constraints(cont_set: VennSet[State]) -> VennSet:
    complexes = calc_connected_complexes(cont_set.values)
    complex_constraints = []

    for complex in complexes:  # pylint: disable=redefined-builtin
        state_paths = calc_state_paths(complex)
        constraint = UniversalSet()  # type:  VennSet[State]

        for state in complex:
            assert not state.is_global, 'Global state {} appearing in connectivity constraints.'.format(state)

            if any(path == [] for path in state_paths[state]):
                continue

            state_constraints = [Complement(ValueSet(state))]  # type: List[VennSet[State]]
            for path in state_paths[state]:
                state_constraints.append(Intersection(*(ValueSet(x) for x in path)))

            constraint = Intersection(constraint, Union(*state_constraints))  # pylint: disable=redefined-variable-type

        complex_constraints.append(constraint.to_simplified_set())

    if complex_constraints:
        LOGGER.debug('{} : Complex constraints {}'.format(current_function_name(), ' XOR '.join(str(x) for x in complex_constraints)))
        return Intersection(cont_set, DisjunctiveUnion(*complex_constraints))
    else:
        return cont_set
示例#4
0
def test_is_equivalent_to() -> None:
    assert UniversalSet().is_equivalent_to(UniversalSet())
    assert EmptySet().is_equivalent_to(EmptySet())

    assert not UniversalSet().is_equivalent_to(ValueSet(1))
    assert not ValueSet(1).is_equivalent_to(UniversalSet())

    assert UniversalSet().is_equivalent_to(Union(ValueSet(1), Complement(ValueSet(1))))
示例#5
0
def test_intersection_properties(sets: List[Set]) -> None:
    for x in sets:
        assert EmptySet().is_equivalent_to(Intersection(x, Complement(x)))
        assert EmptySet().is_equivalent_to(Intersection(Complement(x), x))

        assert EmptySet().is_equivalent_to(Intersection(EmptySet(), x))
        assert EmptySet().is_equivalent_to(Intersection(x, EmptySet()))

        assert x.is_equivalent_to(Intersection(UniversalSet(), x))
        assert x.is_equivalent_to(Intersection(x, UniversalSet()))

        assert x.is_equivalent_to(Intersection(x, x))
示例#6
0
def test_nested_list_form() -> None:
    assert venn_from_str('1', int).to_dnf_nested_list() == [[venn_from_str('1', int)]]

    x = venn_from_str('1 & ( 2 | 3 )', int)
    assert [ValueSet(1), ValueSet(2)] in x.to_dnf_nested_list()
    assert [ValueSet(1), ValueSet(3)] in x.to_dnf_nested_list()

    assert venn_from_str('1 & 2', int).to_dnf_nested_list() == [[ValueSet(1), ValueSet(2)]]
    assert venn_from_str('1 | 2', int).to_dnf_nested_list() == [[ValueSet(1)], [ValueSet(2)]]

    assert UniversalSet().to_dnf_nested_list() == [[UniversalSet()]]
    assert EmptySet().to_dnf_nested_list() == [[EmptySet()]]
示例#7
0
def test_list_form() -> None:
    assert venn_from_str('1', int).to_dnf_list() == [venn_from_str('1', int)]

    assert venn_from_str('1 & 2', int).to_dnf_list() == [venn_from_str('1 & 2', int)]
    assert set(venn_from_str('1 | 2', int).to_dnf_list()) == {ValueSet(1), ValueSet(2)}

    x = venn_from_str('1 & ( 2 | 3 )', int)
    assert any(elem.is_equivalent_to(venn_from_str('1 & 2', int)) for elem in x.to_dnf_list())
    assert any(elem.is_equivalent_to(venn_from_str('1 & 3', int)) for elem in x.to_dnf_list())

    assert UniversalSet().to_dnf_list() == [UniversalSet()]
    assert EmptySet().to_dnf_list() == [EmptySet()]
示例#8
0
    def __init__(self, q_contingencies: List[Contingency]) -> None:
        self.q_contingencies = deepcopy(q_contingencies)

        combis = [[]]  # type: List[List[Contingency]]
        for contingency in self.q_contingencies:
            new_combis = []
            for combi in combis:
                new_combis.append(combi + [
                    Contingency(contingency.reaction, ContingencyType.
                                inhibition, contingency.effector)
                ])
                combi.append(
                    Contingency(contingency.reaction,
                                ContingencyType.requirement,
                                contingency.effector))
            combis.extend(new_combis)

        self.combi_sets = []  # type: List[VennSet[State]]

        if combis == [[]]:
            self.combi_sets = [UniversalSet()]
        else:
            self.combi_sets = [
                Intersection(*(x.to_venn_set() for x in combi))
                for combi in combis
            ]

        self.current_combi_set = -1
示例#9
0
    def __init__(self,
                 reaction_parent: Reaction,
                 contingency_variant: Optional[int] = None,
                 interaction_variant: Optional[int] = None,
                 contingency_factor: VennSet['StateTarget'] = None) -> None:
        self.reaction_parent = reaction_parent  # type: Reaction
        self.produced_targets = [
            StateTarget(x) for x in reaction_parent.produced_states
        ]  # type: List[StateTarget]
        self.consumed_targets = [
            StateTarget(x) for x in reaction_parent.consumed_states
        ]  # type: List[StateTarget]
        self.synthesised_targets = [
            StateTarget(x) for x in reaction_parent.synthesised_states
        ]  # type: List[StateTarget]
        self.degraded_targets = [
            StateTarget(x) for x in reaction_parent.degraded_states
        ]  # type: List[StateTarget]

        self.contingency_variant_index = contingency_variant
        self.interaction_variant_index = interaction_variant

        if contingency_factor is None:
            self.contingency_factor = UniversalSet(
            )  # type: VennSet[StateTarget]
        else:
            self.contingency_factor = contingency_factor  # type: VennSet[StateTarget]
示例#10
0
def test_nary_sets_constructor() -> None:
    assert Union() == EmptySet()
    assert Intersection() == UniversalSet()
    assert DisjunctiveUnion() == EmptySet()

    assert Union(venn_from_str('1', int)).is_equivalent_to(venn_from_str('1', int))
    assert Intersection(venn_from_str('1', int)).is_equivalent_to(venn_from_str('1', int))
    assert DisjunctiveUnion(venn_from_str('1', int)).is_equivalent_to(venn_from_str('1', int))
示例#11
0
def sets() -> List[Set]:
    return [
        EmptySet(),
        ValueSet(1),
        UniversalSet(),
        Union(ValueSet(1), ValueSet(2)),
        Intersection(ValueSet(1), ValueSet(2)),
        Intersection(ValueSet(1), Complement(ValueSet(2))),
        Union(Intersection(ValueSet(1), ValueSet(2)), ValueSet(3)),
        Union(Intersection(ValueSet(1), ValueSet(2)), Intersection(ValueSet(3), ValueSet(4))),
        Union(Complement(Union(ValueSet(1), Complement(ValueSet(2)))), Intersection(ValueSet(3), ValueSet(4)))
    ]
示例#12
0
    def _unsatisfiable_contingencies(self) -> List[Tuple[Reaction, str]]:
        unsatisfiable = []

        for reaction in self.reactions:
            contingencies = self.s_contingencies_for_reaction(reaction)

            total_set = UniversalSet()  # type: Set[State]
            for contingency in contingencies:
                total_set = Intersection(total_set, contingency.to_venn_set())  # pylint: disable=redefined-variable-type

            solutions = total_set.calc_solutions()
            if len(solutions) == 0:
                unsatisfiable.append(
                    (reaction, 'Zero consistent solutions found.'))

            local_unsatisfiables = []
            at_least_one_consistent_soln = False

            for solution in solutions:
                trues = [state for state, val in solution.items() if val]
                if any(
                        state.is_mutually_exclusive_with(other)
                        for state, other in product(trues, trues)):
                    state, other = next(
                        (state, other)
                        for state, other in product(trues, trues)
                        if state.is_mutually_exclusive_with(other))
                    local_unsatisfiables.append(
                        (reaction,
                         'State {} mutually exclusive with {}.'.format(
                             str(state), str(other))))
                else:
                    at_least_one_consistent_soln = True

            if not at_least_one_consistent_soln:
                unsatisfiable += local_unsatisfiables

        return unsatisfiable
示例#13
0
def with_connectivity_constraints(cont_set: VennSet[State],
                                  rxncon_system: RxnConSystem) -> VennSet:
    """Intersect the contingencies with the connectivity constraints."""
    if cont_set.is_equivalent_to(UniversalSet()):
        return cont_set

    LOGGER.debug(
        'with_connectivity_constraints : calculating molecular microstates')
    components = components_microstate(cont_set, rxncon_system)
    LOGGER.debug('with_connectivity_constraints : calculating complexes')
    complexes = bond_complexes(cont_set)

    constraints = []

    for cx in complexes:
        constraints.append(
            Intersection(cx.to_venn_set(),
                         *(components[cp] for cp in cx.components)))

    return Intersection(cont_set, Union(*constraints))
示例#14
0
    def to_venn_set(
            self,
            k_plus_strict: bool = False,
            k_minus_strict: bool = False,
            structured: bool = True,
            state_wrapper: Callable[[State],
                                    Any] = lambda x: x) -> VennSet[Any]:
        def parse_effector(eff: Effector) -> VennSet:
            if isinstance(eff, StateEffector):
                if structured:
                    return ValueSet(state_wrapper(eff.expr))
                else:
                    return ValueSet(state_wrapper(
                        eff.expr.to_non_structured()))
            elif isinstance(eff, NotEffector):
                return Complement(parse_effector(eff.expr))
            elif isinstance(eff, OrEffector):
                return Union(*(parse_effector(x) for x in eff.exprs))
            elif isinstance(eff, AndEffector):
                return Intersection(*(parse_effector(x) for x in eff.exprs))
            else:
                raise AssertionError

        if k_plus_strict:
            positive = (ContingencyType.requirement, ContingencyType.positive)
        else:
            positive = (ContingencyType.requirement, )  # type: ignore

        if k_minus_strict:
            negative = (ContingencyType.inhibition, ContingencyType.negative)
        else:
            negative = (ContingencyType.inhibition, )  # type: ignore

        if self.contingency_type in positive:
            return parse_effector(self.effector)
        elif self.contingency_type in negative:
            return Complement(parse_effector(self.effector))
        else:
            return UniversalSet()
示例#15
0
    def to_venn_set(self, k_plus_strict: bool=False, k_minus_strict: bool=False, structured: bool=True,
                    state_wrapper: Callable[[State], Any]=lambda x: x) -> VennSet[Any]:
        """Returns a Venntastic Set object corresponding to the Contingency: requirements are put in a ValueSet,
        inhibitions in a ValueSet within a Complement. If `k_plus_strict` / `k_minus_strict`, then positive and
        negative Contingencies are translated into strict requirements resp. strict inhibitions. If `structured`
        is False, the structure information is discarded. Optionally all States can be wrapped in some other
        class by providing a `state_wrapper`."""
        def parse_effector(eff: Effector) -> VennSet:
            if isinstance(eff, StateEffector):
                if structured:
                    return ValueSet(state_wrapper(eff.expr))
                else:
                    return ValueSet(state_wrapper(eff.expr.to_non_structured()))
            elif isinstance(eff, NotEffector):
                return Complement(parse_effector(eff.expr))
            elif isinstance(eff, OrEffector):
                return Union(*(parse_effector(x) for x in eff.exprs))
            elif isinstance(eff, AndEffector):
                return Intersection(*(parse_effector(x) for x in eff.exprs))
            else:
                raise AssertionError('Unknown Effector {}'.format(str(eff)))

        if k_plus_strict:
            positive = (ContingencyType.requirement, ContingencyType.positive)
        else:
            positive = (ContingencyType.requirement,)  # type: ignore

        if k_minus_strict:
            negative = (ContingencyType.inhibition, ContingencyType.negative)
        else:
            negative = (ContingencyType.inhibition,)  # type: ignore

        if self.contingency_type in positive:
            return parse_effector(self.effector)
        elif self.contingency_type in negative:
            return Complement(parse_effector(self.effector))
        else:
            return UniversalSet()
示例#16
0
    def _unsatisfiable_contingencies(self) -> List[Tuple[Reaction, str]]:
        """Determines the contingencies that are not satisfiable, returns a list of (Reaction, str) where
        the str contains the human-readable reason for the contingency not being satisfiable."""
        unsatisfiable = []

        for reaction in self.reactions:
            contingencies = self.s_contingencies_for_reaction(reaction)

            # Make sure the contingency does not contain the states produced / consumed by the reaction.
            states = (state for contingency in contingencies
                      for state in contingency.effector.states)

            for state in states:
                # We need to be talking about the states mentioning the reactants.
                if not all(spec.struct_index in (0, 1)
                           for spec in state.specs):
                    continue

                if any(count > 1
                       for count in Counter(reaction.components_rhs).values()):
                    continue

                # States appear non-structured in the '.produced_states' etc. properties.
                state = state.to_non_structured()

                if state in reaction.produced_states and state not in reaction.synthesised_states:
                    unsatisfiable.append(
                        (reaction,
                         'Produced state {} appears in contingencies'.format(
                             str(state))))
                if state in reaction.consumed_states and state not in reaction.degraded_states:
                    unsatisfiable.append(
                        (reaction,
                         'Consumed state {} appears in contingencies'.format(
                             str(state))))

            # Make sure at least one solution is there (this might still contain mutually exclusive states)
            total_set = UniversalSet()  # type: Set[State]
            for contingency in contingencies:
                total_set = Intersection(total_set, contingency.to_venn_set())  # pylint: disable=redefined-variable-type

            solutions = total_set.calc_solutions()
            if len(solutions) == 0:
                unsatisfiable.append(
                    (reaction, 'Zero consistent solutions found.'))

            # Make sure that at least one solution doesn't contain mutually exclusive states.
            local_unsatisfiables = []
            at_least_one_consistent_soln = False

            for solution in solutions:
                trues = [state for state, val in solution.items() if val]
                if any(
                        state.is_mutually_exclusive_with(other)
                        for state, other in product(trues, trues)):
                    state, other = next(
                        (state, other)
                        for state, other in product(trues, trues)
                        if state.is_mutually_exclusive_with(other))
                    local_unsatisfiables.append(
                        (reaction,
                         'State {} mutually exclusive with {}.'.format(
                             str(state), str(other))))
                else:
                    at_least_one_consistent_soln = True

            if not at_least_one_consistent_soln:
                unsatisfiable += local_unsatisfiables

        return unsatisfiable