Comparisons with Context
In Nettlesome, logical comparisons
between Statements and other
Factors can depend on whether
the Terms of the
Statements are considered
analagous to one another. In the example below, the two phrases can be
considered to have the same meaning because the Terms of each Statement
can be “matched” to one another.
>>> from nettlesome import Statement, Entity
>>> hades_curse = Statement(predicate="$deity cursed $target",
... terms=[Entity(name="Hades"), Entity(name="Persephone")])
>>> aphrodite_curse = Statement(predicate="$deity cursed $target",
... terms=[Entity(name="Aphrodite"), Entity(name="Narcissus")])
>>> print(aphrodite_curse)
the statement that <Aphrodite> cursed <Narcissus>
The means() method is used to determine
whether two Statements have the same meaning.
>>> hades_curse.means(aphrodite_curse)
True
The explain_same_meaning() method
generates an Explanation
explaining why the two Statements can be considered to have the
same meaning.
>>> print(hades_curse.explain_same_meaning(aphrodite_curse))
Because <Hades> is like <Aphrodite>, and <Persephone> is like <Narcissus>,
the statement that <Hades> cursed <Persephone>
MEANS
the statement that <Aphrodite> cursed <Narcissus>
Formatting Contexts for Comparison Methods
But what if the two Statements need to be
compared in a context where it
has been established that Hades is more comparable to Narcissus, not to
Aphrodite? That changes the meaning of the second Statement and
indicates that the two Statements don’t have the same meaning. To add
that context information in Nettlesome, use the context
parameter of the means() method.
Option 1: Context from Two Lists
One input format for the context
parameter is a tuple of two lists, with the first List containing Terms
from the Statement on the left, and the second List containing the
corresponding Terms from the
Statement on the right. (This means that
the two lists will need to be the same length.) In this example, there’s
a one-item List containing Hades, matched to a one-item List containing
Narcissus. The value returned by
the means() method is now False
instead of True.
>>> hades_curse.means(aphrodite_curse, context=([Entity(name="Hades")], [Entity(name="Narcissus")]))
False
Option 2: Context from a Dict
Maybe it seems more natural to use a Python dict, instead
of a tuple of
two Lists, to match pairs of corresponding Terms.
(A Python dict is a mapping of keys to values.)
A dict can be used for the context
parameter, but there’s a complication: a nettlesome.entities.Entity is not a
valid dict key in Python. Here’s the error message you’ll see
if you try to use an Entity directly
as a dict key,
and then try to retrieve the value stored under that key.
>>> myths = {Entity(name="Hades"): Entity(name="Narcissus")}
>>> myths[Entity(name="Hades")]
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-5-75ea1b988416> in <module>
1 myths = {Entity(name="Hades"): Entity(name="Narcissus")}
----> 2 myths[Entity(name="Hades")]
KeyError: Entity(name="Hades", generic=True, plural=False)
So instead of passing in the Entity itself
as a dict key, we’ll pass in the key()
property of the Entity.
>>> hades_curse.means(
... aphrodite_curse,
... context=({Entity(name="Hades").key: Entity(name="Narcissus")}))
False
Option 3: Context from One List
If neither of the options above is convenient, a third alternative is
to skip identifying any Terms from the left
Statement, and instead provide
one list with matching Terms for all of
the left Statement's
generic_terms(). To understand this, let’s see
what the Statement’s generic_terms() are. As
mentioned in the Generic Terms section of the Introduction to Nettlesome
tutorial, generic Terms are Terms used as an
example or stand-in for a broader category, so that a different generic
Term can be substituted without changing the meaning of the Statement.
>>> hades_curse.generic_terms()
[Entity(name="Hades", generic=True, plural=False),
Entity(name="Persephone", generic=True, plural=False)]
This time, we’ll provide the correct Entities that match to the Entities
of hades_curse, so the means() method
will return True.
>>> hades_curse.means(
... aphrodite_curse,
... context=([Entity(name="Aphrodite"), Entity(name="Narcissus")]))
True
Comparing FactorGroups in Context
Like Statements, FactorGroups
can be compared to one another using the
implies(), means(),
contradicts(), and
consistent_with() methods. In
this example, the nafta FactorGroup describes
three countries all making bilateral agreements with one another.
The brexit FactorGroup
describes one country making treaties with two other countries that do
not make a treaty with each other. These two FactorGroups are considered
to “contradict” one another, because if the Statements in brexit
were asserted about the parties in nafta, there would be a conflict
about whether one pair of Entities signed a treaty with each other.
>>> from nettlesome import FactorGroup
>>> 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)])
>>> nafta.contradicts(brexit)
True
The explain_contradiction() method
will generate one Explanation of how
an analogy between the generic terms of the
two FactorGroups can make them contradictory.
>>> print(nafta.explain_contradiction(brexit))
Because <Mexico> is like <Germany>, and <USA> is like <UK>,
the statement that <Mexico> signed a treaty with <USA>
CONTRADICTS
the statement it was false that <Germany> signed a treaty with <UK>
The explanations_contradiction() method
(with the plural “explanations” instead of “explain”) returns a generator
that will yield all available Explanations of
how to cause a contradiction. In this case it generates four Explanations.
>>> all_explanations = list(nafta.explanations_contradiction(brexit))
>>> len(all_explanations)
4
By adding a context parameter to the method that compares the
FactorGroups for contradiction, we can narrow
down how Nettlesome discovers analogies between
the Entity objects. The result is that
Nettlesome finds only two Explanations of
how a contradiction can exist.
>>> explanations_usa_like_uk = list(nafta.explanations_contradiction(
... brexit,
... context=([Entity(name="USA")], [Entity(name="UK")])))
>>> len(explanations_usa_like_uk)
2
Here are the two Explanations for how a contradiction
can exist if the Entity “USA” in left is considered
analagous to the Entity “UK” in right.
>>> print(explanations_usa_like_uk[0])
Because <USA> is like <UK>, and <Mexico> is like <Germany>,
the statement that <Mexico> signed a treaty with <USA>
CONTRADICTS
the statement it was false that <Germany> signed a treaty with <UK>
>>> print(explanations_usa_like_uk[1])
Because <USA> is like <UK>, and <Canada> is like <Germany>,
the statement that <USA> signed a treaty with <Canada>
CONTRADICTS
the statement it was false that <Germany> signed a treaty with <UK>