Example #1
0
    def explain_contradiction_some_to_all(
        self,
        other: Procedure,
        context: Optional[Union[ContextRegister, Explanation]] = None,
    ) -> Iterator[Explanation]:
        """Explain why ``other`` can't apply in all cases if ``self`` applies in some."""
        if not isinstance(context, Explanation):
            context = Explanation.from_context(context)

        # For self to contradict other, either every input of other
        # must imply some input or despite factor of self...
        implied_contexts = self._has_input_or_despite_factors_implied_by_all_inputs_of(
            other, context)

        # or every input of other must be implied by
        # some input or despite factor of self.
        implying_contexts = self._has_input_or_despite_factors_implying_all_inputs_of(
            other, context)

        # For self to contradict other, some output of other
        # must be contradicted by some output of self.
        seen_contexts = []
        for m in chain(implying_contexts, implied_contexts):
            if m.context not in seen_contexts:
                seen_contexts.append(m.context)
                yield from self.outputs_group._explanations_contradiction(
                    other.outputs_group, m)
Example #2
0
 def test_input_or_despite_factors(self):
     """Test part of the process of checking contradiction."""
     rural = Entity(name="Rural's telephone directory")
     compilation = Predicate(
         content="${rural_s_telephone_directory} was a compilation of facts"
     )
     idea = Predicate(content="${rural_s_telephone_directory} was an idea")
     copyrightable = Fact(
         predicate=Predicate(
             content="${rural_s_telephone_directory} was copyrightable"
         ),
         terms=rural,
     )
     left = Procedure(
         outputs=(copyrightable),
         inputs=(Fact(predicate=compilation, terms=rural)),
     )
     right = Procedure(
         outputs=(copyrightable),
         inputs=(Fact(predicate=idea, terms=rural)),
     )
     context = ContextRegister()
     explanation = Explanation.from_context(context)
     gen = left._has_input_or_despite_factors_implied_by_all_inputs_of(
         right, explanation
     )
     with pytest.raises(StopIteration):
         next(gen)
Example #3
0
    def triggers_next_procedure(
        self,
        other: Procedure,
        context: Optional[Union[ContextRegister, Explanation]] = None,
    ) -> Iterator[Explanation]:
        r"""
        Test if :class:`.Factor`\s from firing ``self`` would trigger ``other``.

        .. Note::
            To be confident that ``self`` actually can trigger ``other``,
            we would have to assume that self or other has ``universal: True``
            since otherwise there could be a mismatch between what is provided
            and what is needed to trigger ``other``.

        :param other:
            another :class:`Procedure` to test to see whether it can
            be triggered by triggering ``self``

        :returns:
            whether the set of :class:`Factor`\s that exist after ``self``
            is fired could trigger ``other``
        """
        self_despite_or_input = FactorGroup((*self.despite, *self.inputs))
        self_output_or_input = FactorGroup((*self.outputs, *self.inputs))

        if not isinstance(context, Explanation):
            context = Explanation.from_context(context)

        for explanation_1 in self_output_or_input.explanations_implication(
                other.inputs_group, context=context):
            yield from self_despite_or_input.explanations_implication(
                other.despite_group, context=explanation_1)
Example #4
0
 def explanations_implication(
     self,
     other: Comparable,
     context: Optional[Union[ContextRegister, Explanation]] = None,
 ) -> Iterator[ContextRegister]:
     """Yield contexts that would cause self and other to have same meaning."""
     if not self.comparable_with(other):
         raise TypeError(f"Type Holding cannot be compared with type {type(other)}.")
     if not isinstance(context, Explanation):
         context = Explanation.from_context(context)
     if isinstance(other, Procedure):
         other = Rule(procedure=other)
     if isinstance(other, Rule):
         other = Holding(rule=other)
     if not isinstance(other, self.__class__):
         if context:
             context = context.reversed_context()
         if other.implied_by(self, context=context):
             yield context
     elif self.exclusive is other.exclusive is False:
         yield from self._explanations_implies_if_not_exclusive(
             other, context=context
         )
     else:
         yield from self.nonexclusive_holdings.explanations_implication(
             other.nonexclusive_holdings, context=context
         )
Example #5
0
 def test_contradicts_if_present_both_present(self, make_statement):
     """
     Test a helper function that checks whether there would
     be a contradiction if neither Factor was "absent".
     """
     assert make_statement["crime"]._contradicts_if_present(
         make_statement["absent_no_crime"],
         explanation=Explanation.from_context())
Example #6
0
 def explanations_implication(
     self,
     other: Comparable,
     context: Optional[Union[ContextRegister, Explanation]] = None,
 ) -> Iterator[Explanation]:
     """Find contexts that would cause ``self`` to imply ``other``."""
     context = Explanation.from_context(context=context,
                                        current=self,
                                        incoming=other)
     yield from self._explanations_implication(other, context)
Example #7
0
 def explanations_implied_by(
     self,
     other: Comparable,
     context: Optional[Union[ContextRegister, Explanation]] = None,
 ) -> Iterator[Explanation]:
     """Generate explanations for how other may imply self."""
     context = context = Explanation.from_context(context=context,
                                                  current=self,
                                                  incoming=other)
     yield from self._explanations_implied_by(other=other,
                                              explanation=context)
Example #8
0
    def explanations_contradiction(
        self,
        other,
        context: Optional[Union[ContextRegister, Explanation]] = None
    ) -> Iterator[ContextRegister]:
        """Find context matches that would result in a contradiction with other."""
        if not isinstance(context, Explanation):
            context = Explanation.from_context(context)

        yield from self._explanations_contradiction(other=other,
                                                    context=context)
Example #9
0
 def explain_implication_all_to_some(
     self,
     other: Factor,
     context: Optional[Union[ContextRegister, Explanation]] = None,
 ) -> Iterator[Explanation]:
     """Yield contexts establishing that if self is always valid, other is sometimes valid."""
     if not isinstance(context, Explanation):
         context = Explanation.from_context(context)
     if isinstance(other, self.__class__):
         yield from self._explain_implication_of_procedure_all_to_some(
             other=other, context=context)
Example #10
0
    def explanations_same_meaning(
        self,
        other: Comparable,
        context: Optional[Union[ContextRegister, Explanation]] = None,
    ) -> Iterator[Explanation]:
        """Yield contexts that could cause self to have the same meaning as other."""

        if not isinstance(context, Explanation):
            context = Explanation.from_context(context)

        if isinstance(other, self.__class__):
            yield from self._explanations_same_meaning_as_procedure(
                other, context)
Example #11
0
 def implied_by(
     self,
     other: Union[OpinionReading, Holding, Rule],
     context: Optional[Union[ContextRegister, Explanation]] = None,
 ) -> bool:
     """Determine if other implies all the Holdings of self."""
     if not isinstance(context, Explanation):
         context = Explanation.from_context(context)
     if isinstance(other, Holding):
         return self._implied_by_holding(other, context=context)
     elif isinstance(other, Rule):
         return self._implied_by_rule(other, context=context)
     return other.implies(self, context=context.reversed_context())
Example #12
0
 def union(
     self,
     other: Comparable,
     context: Optional[Union[ContextRegister, Explanation]] = None,
 ) -> Optional[Comparable]:
     """Get a procedure with all the inputs and outputs of self and other."""
     if not isinstance(context, Explanation):
         context = Explanation.from_context(context)
     explanations = self.explanations_union(other, context)
     try:
         explanation = next(explanations)
     except StopIteration:
         return None
     return self._union_from_explanation(other, explanation)
Example #13
0
 def explanations_union(
     self,
     other: Procedure,
     context: Optional[Union[ContextRegister, Explanation]] = None,
 ) -> Iterator[ContextRegister]:
     """Yield explanations of contexts that allow combining these Procedures."""
     if not isinstance(context, Explanation):
         context = Explanation.from_context(context)
     for partial in self._explanations_union_partial(
             other, context.context):
         for guess in self.possible_contexts(other, partial):
             answer = self._union_from_explanation(other, guess)
             if answer:
                 yield guess
Example #14
0
 def explanations_same_meaning(
     self,
     other: Comparable,
     context: Optional[Union[ContextRegister, Explanation]] = None,
 ) -> Iterator[Explanation]:
     """Yield explanations for how ``self`` can have the same meaning as ``other``."""
     context = context = Explanation.from_context(context=context,
                                                  current=self,
                                                  incoming=other)
     context.operation = means
     to_match = self.from_comparable(other)
     if to_match is not None:
         for new_context in self._contexts_shares_all_factors_with(
                 to_match, context.context):
             yield from self._verbose_comparison(
                 still_need_matches=list(to_match.sequence),
                 explanation=context.with_context(new_context),
             )
Example #15
0
    def explanations_contradiction(
        self, other: Factor, context: ContextRegister = None
    ) -> Iterator[Explanation]:
        r"""
        Find context matches that would result in a contradiction with other.

        Works by testing whether ``self`` would imply ``other`` if
        ``other`` had an opposite value for ``rule_valid``.

        This method takes three main paths depending on
        whether the holdings ``self`` and ``other`` assert that
        rules are decided or undecided.

        A ``decided`` :class:`Rule` can never contradict
        a previous statement that any :class:`Rule` was undecided.

        If rule A implies rule B, then a holding that B is undecided
        contradicts a prior :class:`Rule` deciding that
        rule A is valid or invalid.

        :param other:
            The :class:`.Factor` to be compared to self. Unlike with
            :meth:`~Holding.contradicts`\, this method cannot be called
            with an :class:`.Opinion` for `other`.

        :returns:
            a generator yielding :class:`.ContextRegister`\s that cause a
            contradiction.
        """
        if not self.comparable_with(other):
            raise TypeError(f"Type Holding cannot be compared with type {type(other)}.")
        if not isinstance(context, Explanation):
            context = Explanation.from_context(context)
        if isinstance(other, Procedure):
            other = Rule(procedure=other)
        if isinstance(other, Rule):
            other = Holding(rule=other)
        if isinstance(other, self.__class__):
            yield from self._explanations_contradiction_of_holding(other, context)
        else:
            yield from other.explanations_contradiction(self)
Example #16
0
 def explanations_implication(
     self,
     other: Comparable,
     context: Optional[Union[ContextRegister, Explanation]] = None,
 ) -> Iterator[Explanation]:
     """Generate contexts in which all Holdings in other are implied by self."""
     if isinstance(other, Rule):
         other = Holding(rule=other)
     explanation = Explanation.from_context(
         context=context, current=self, incoming=other
     )
     if isinstance(other, Holding):
         yield from self._explanations_implication_of_holding(
             other=other, context=context
         )
     elif isinstance(other, self.__class__):
         yield from self.verbose_comparison(
             operation=operator.ge,
             still_need_matches=list(other),
             explanation=explanation,
         )
Example #17
0
    def explanations_contradiction(
        self,
        other: Comparable,
        context: Optional[Union[ContextMemo, Explanation]] = None,
    ) -> Iterator[Explanation]:
        """
        Find contexts that would cause ``self`` to contradict ``other``.

        In this example, by adding a context parameter to this method's comparison
        of two FactorGroups for contradiction, we can narrow down how nettlesome
        discovers analogies between the Entity objects. The result is that
        nettlesome finds only two Explanations for how a contradiction can exist.

            >>> from nettlesome import Statement, Entity
            >>> nafta = FactorGroup([
            ... Statement(predicate="$country1 signed a treaty with $country2",
            ...     terms=[Entity(name="Mexico"), Entity(name="USA")]),
            ... Statement(predicate="$country2 signed a treaty with $country3",
            ...     terms=[Entity(name="USA"), Entity(name="Canada")]),
            ... Statement(predicate="$country3 signed a treaty with $country1",
            ...    terms=[Entity(name="USA"), Entity(name="Canada")])])
            >>> brexit = FactorGroup([
            ... Statement(predicate="$country1 signed a treaty with $country2",
            ...     terms=[Entity(name="UK"), Entity(name="European Union")]),
            ... Statement(predicate="$country2 signed a treaty with $country3",
            ...     terms=[Entity(name="European Union"), Entity(name="Germany")]),
            ... Statement(predicate="$country3 signed a treaty with $country1",
            ...     terms=[Entity(name="Germany"), Entity(name="UK")], truth=False)])
            >>> explanations_usa_like_uk = nafta.explanations_contradiction(
            ...     brexit,
            ...     context=([Entity(name="USA")], [Entity(name="UK")]))
            >>> len(list(explanations_usa_like_uk))
            2
        """

        context = Explanation.from_context(context=context,
                                           current=self,
                                           incoming=other)
        yield from self._explanations_contradiction(other=other,
                                                    explanation=context)
Example #18
0
 def test_contradicts_if_present_one_absent(self, make_statement):
     assert make_statement["crime"]._contradicts_if_present(
         make_statement["no_crime"], explanation=Explanation.from_context())