Comparisons with Context
In Nettlesome, logical comparisons
between Statement
s and other
Factor
s can depend on whether
the Term
s of the
Statement
s 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 Statement
s 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 Statement
s 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 list
s, with the first List containing Terms
from the Statement on the left, and the second List containing the
corresponding Term
s 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 Term
s 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 Statement
s, FactorGroup
s
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 FactorGroup
s 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 Explanation
s 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
FactorGroup
s for contradiction, we can narrow
down how Nettlesome discovers analogies between
the Entity
objects. The result is that
Nettlesome finds only two Explanation
s 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 Explanation
s 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>