def test_parser() -> None: assert venn_from_str('1 & 2', int).is_equivalent_to( Intersection(ValueSet(1), ValueSet(2))) assert venn_from_str('1 & 2', str).is_equivalent_to( Intersection(ValueSet('1'), ValueSet('2'))) assert venn_from_str('( 1 | 2 ) & 3', int).is_equivalent_to( Intersection(ValueSet(3), Union(ValueSet(1), ValueSet(2)))) assert venn_from_str('~ 1', int).is_equivalent_to(Complement(ValueSet(1))) assert venn_from_str('~( 1 | 2 )', int).is_equivalent_to( Intersection(Complement(ValueSet(1)), Complement(ValueSet(2))))
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))
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))) ]
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
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))))
def sigma(state_target: StateTarget, level: int) -> VennSet[Target]: prod_cons_factor = Union( pi(state_target, level), Intersection(ValueSet(state_target), Complement(kappa(state_target, level)))) return Union( synthesis_factor(state_target), Intersection(degradation_factor(state_target), component_factor(state_target), prod_cons_factor))
def venn_from_effector(effector: Effector) -> VennSet[State]: if isinstance(effector, StateEffector): return ValueSet(effector.expr) elif isinstance(effector, AndEffector): return Intersection(*(venn_from_effector(x) for x in effector.exprs)) elif isinstance(effector, OrEffector): return Union(*(venn_from_effector(x) for x in effector.exprs)) elif isinstance(effector, NotEffector): return Complement(venn_from_effector(effector.expr)) else: raise AssertionError
def _effector_to_vennset(eff: Effector, con_type: Optional[ContingencyType]=None) -> VennSet: """ Preprocessing effector. Save information in leafs. Note: We need the contingency information later on in the process. Since, this information is lost during the calculation of the disjunctive normal form we have to add it beforehand. For this we say an inhibiting contingency is the complement of everything afterwards. The contingency type is only needed at the beginning of the recursion step. Args: eff: rxncon Effector. cont_type: Contingency type. Returns: Return VennSet Raises: AssertionError if the eff is not an effector. """ if isinstance(eff, StateEffector): if con_type is ContingencyType.inhibition: return Complement(ValueSet(eff.expr.to_non_structured())) return ValueSet(eff.expr.to_non_structured()) elif isinstance(eff, NotEffector): if con_type is ContingencyType.inhibition: return _effector_to_vennset(eff.expr) return Complement(_effector_to_vennset(eff.expr)) elif isinstance(eff, OrEffector): if con_type is ContingencyType.inhibition: return Complement(VennUnion(*[_effector_to_vennset(expr) for expr in eff.exprs])) return VennUnion(*[_effector_to_vennset(expr) for expr in eff.exprs]) elif isinstance(eff, AndEffector): if con_type is ContingencyType.inhibition: return Complement(Intersection(*[_effector_to_vennset(expr) for expr in eff.exprs])) return Intersection(*[_effector_to_vennset(expr) for expr in eff.exprs]) else: raise AssertionError
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)))
def update_state_rules_with_knockouts( knockout_strategy: KnockoutStrategy) -> None: if knockout_strategy == KnockoutStrategy.no_knockout: return elif knockout_strategy in (KnockoutStrategy.knockout_all_states, KnockoutStrategy.knockout_neutral_states): for state_rule in state_rules: assert isinstance(state_rule.target, StateTarget) if knockout_strategy == KnockoutStrategy.knockout_neutral_states and not state_rule.target.is_neutral: continue knockout_factor = Complement( Union(*(ValueSet(KnockoutTarget(component)) for component in state_rule.target.components))) state_rule.factor = Intersection(knockout_factor, state_rule.factor)
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()
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()
def to_venn_set(self) -> VennSet[State]: return Intersection( *(ValueSet(s) for s in self.true_states()), *(Complement(ValueSet(s)) for s in self.false_states()))
def calc_state_rules() -> None: """ Calculates the rules of state targets. Note: The factor for a state target has the from: synthesis OR (components AND NOT degradation AND ((production AND sources) OR (state AND NOT (consumption AND sources)))) Returns: A list of updating rules for states. """ def reaction_with_sources( reaction_target: ReactionTarget) -> VennSet[Target]: """ Calculates the source states of the respective reaction target Args: reaction_target: Reaction of the boolean model producing, consuming, degrading or synthesising state targets. Returns: VennSet of the reaction target and its source states """ sources = Intersection( *(ValueSet(x) for x in reaction_target.consumed_targets)) return Intersection(ValueSet(reaction_target), sources) def indirect_synth_path( state_target: StateTarget) -> VennSet[ReactionTarget]: my_brothers = [ x for x in state_targets if state_target.shares_component_with(x) and x != state_target ] return Union(*(ValueSet(rxn) for state in my_brothers for rxn in reaction_targets if rxn.synthesises(state))) def synthesis_factor( state_target: StateTarget) -> VennSet[ReactionTarget]: return Union(*(ValueSet(x) for x in reaction_targets if x.synthesises(state_target))) def component_factor( state_target: StateTarget) -> VennSet[StateTarget]: return Intersection(*(component_presence_factor[x] for x in state_target.components)) def degradation_factor( state_target: StateTarget) -> VennSet[ReactionTarget]: return Complement( Union(*(ValueSet(x) for x in reaction_targets if x.degrades(state_target)))) for state_target in state_targets: synt_fac = synthesis_factor(state_target) comp_fac = component_factor(state_target) degr_fac = degradation_factor(state_target) prod_facs = [] # type: List[VennSet] cons_facs = [] # type: List[VennSet] for reaction_target in (target for target in reaction_targets if target.produces(state_target)): if smoothing_strategy == SmoothingStrategy.no_smoothing: prod_facs.append(reaction_with_sources(reaction_target)) elif smoothing_strategy == SmoothingStrategy.smooth_production_sources: smoothed_prod_facs = [] for primary_source in reaction_target.consumed_targets: smooth_source = Union( ValueSet(primary_source), Intersection( Union(*(reaction_with_sources(rxn) for rxn in reaction_targets if rxn.produces(primary_source))), Union(degradation_factor(primary_source), indirect_synth_path(primary_source)))) smoothed_prod_facs.append(smooth_source) prod_facs.append( Intersection(ValueSet(reaction_target), *smoothed_prod_facs)) else: raise AssertionError for reaction_target in (target for target in reaction_targets if target.consumes(state_target)): cons_facs.append( Complement(reaction_with_sources(reaction_target))) tot_prod_fac = Intersection( comp_fac, Union(*prod_facs), Union(degr_fac, indirect_synth_path(state_target))) tot_cons_fac = Intersection(comp_fac, ValueSet(state_target), Intersection(*cons_facs), degr_fac) state_rules.append( UpdateRule( state_target, Union(synt_fac, tot_prod_fac, tot_cons_fac).to_simplified_set()))
def test_simplifies() -> None: x1 = Intersection(ValueSet(1), ValueSet(2)) x2 = Intersection(ValueSet(1), Complement(ValueSet(2))) assert Union(x1, x2).is_equivalent_to(ValueSet(1))
def degradation_factor( state_target: StateTarget) -> VennSet[ReactionTarget]: return Complement( Union(*(ValueSet(x) for x in reaction_targets if x.degrades(state_target))))
def test_absolute_relative_complement_identities(sets: List[Set]) -> None: for x, y in itt.product(sets, sets): assert Intersection(x, Complement(y)).is_equivalent_to(Difference(x, y)) assert Union(Complement(x), y).is_equivalent_to(Complement(Difference(x, y)))
def test_complement_squares_to_no_op(sets: List[Set]) -> None: for x in sets: assert x.is_equivalent_to(Complement(Complement(x)))
def test_de_morgan_s_identities(sets: List[Set]) -> None: for x, y in itt.product(sets, sets): assert Intersection(Complement(x), Complement(y)).is_equivalent_to(Complement(Union(x, y))) assert Union(Complement(x), Complement(y)).is_equivalent_to(Complement(Intersection(x, y)))