One of the most difficult AuthoritySpoke features for users to understand has been the ability for the Factors of legal rules to have “generic context” affecting how the rules can be compared to one another. This article will try to make that concept a little clearer, and also describe how to use contexts with comparison methods like .means(), .implies(), and .contradicts().

“Generic” in AuthoritySpoke

As mentioned before, the text of a Factor is like a phrase, and the terms of the Factor are like the nouns that function as the subject and objects of the phrase. If a Factor’s terms are labeled as “generic”, then the Factor can be considered to have the same meaning as another Factor that has different terms, as long as the other Factor’s terms are also labeled “generic”.

Here’s an example (based on the documentation for Nettlesome, which is a dependency of AuthoritySpoke). Each Entity object is “generic” by default, so all four of the “terms” in the example are considered “generic”. I’ve also given each Entity a generic-sounding name, instead of a proper noun, to emphasize that each Fact could refer to many different people. However, nothing in AuthoritySpoke will stop you from using proper nouns as the names of generic terms. All the examples in this article were tested on version 0.6.0 of AuthoritySpoke.

>>> from authorityspoke import Fact, Entity
>>> poet_payment = Fact("$payor made a payment to $payee",
...     terms=[Entity("the fierce philanthropist"), Entity("the starving poet")])
>>> henchman_payment = Statement("$payor made a payment to $payee",
...     terms=[Entity("the affable spy"), Entity("the devious henchman")])
>>> print(henchman_payment)
the statement that <the affable spy> made a payment to <the devious henchman>

The means() method can be used to determine whether two Facts have the same meaning.

>>> poet_payment.means(henchman_payment)
True

The explain_same_meaning() method generates an Explanation showing why the two Facts can be considered to have the same meaning.

>>> print(poet_payment.explain_same_meaning(henchman_payment))
"""Because <the fierce philanthropist> is like <the affable spy>, and <the starving poet> is like <the devious henchman>,
  the fact that <the fierce philanthropist> made a payment to <the starving poet>
MEANS
  the fact that <the affable spy> made a payment to <the devious henchman>"""

The illustration above shows that when AuthoritySpoke finds two Facts to be the same, it means that the relationships they describe are the same. It doesn’t at all mean that the identities of the “generic” Entities are the same.

Identifying Parallel Generic Terms

In AuthoritySpoke, the “context” of a comparison dictates which generic terms are considered parallel to one another. If no context parameter is passed in to a comparison method like .means(), then the comparison method will try every permutation of both Facts’ generic terms to find ways to match them all. Passing in a context parameter limits the ways that the generic terms can be matched.

In this example, the two Facts are compared in a context where it has been established that the philanthropist is more like the henchman, and the poet is more like the spy. (After all, to AuthoritySpoke these names are just strings, and AuthoritySpoke has no idea that they don’t sound similar.) To create this context, we pass in a tuple of two lists: a list of terms on the left that will be replaced, and a list of replacements from the right in the corresponding order. Because the context precludes the first term of poet_payment from being matched to the first term of henchman_payment, the method that checks whether these Facts have the same meaning now returns False.

>>> poet_payment.means(henchman_payment)
...     context=(
...         [Entity("the fierce philanthropist"), Entity("the starving poet")],
...         [Entity("the devious henchman"), Entity("the affable spy")])
...     )
False

Instead of using .means(), we could also have used the context parameter in the same format to test whether the first Factor .implies() or .contradicts() the other. There’s more information about using a context parameter with comparison methods in the Nettlesome documentation.

Up to now, we’ve only compared Factors outside the scope of any legal rule or judicial holding. To build on the ideas above and do a little real legal analysis, let’s see an example of how generic context works in an example Holding based on United States v. Harmon, a recent case from the District Court of the District of Columbia.

First, we use AuthoritySpoke’s legislation download client to get the statute being interpreted. If you try out this code yourself, you’ll need to follow the directions for creating an environment variable called “LEGISLICE_API_TOKEN”.

>>> import os
>>> from dotenv import load_dotenv
>>> from authorityspoke.io.downloads import Client
>>> load_dotenv()
>>> LEGISLICE_API_TOKEN = os.getenv("LEGISLICE_API_TOKEN")
>>> CLIENT = Client(api_token=LEGISLICE_API_TOKEN)
>>> offense_statute = CLIENT.read("/us/usc/t18/s1960/a")
>>> print(offense_statute)
'"Whoever knowingly conducts, controls, manages, supervises, directs, or owns all or part of an unlicensed money transmitting business, shall be fined in accordance with this title or imprisoned not more than 5 years, or both." (/us/usc/t18/s1960/a 2013-07-18)'

Next, we create the Facts that the court found to be relevant to the elements of a criminal offense, and we combine them into a Holding.

>>> from authorityspoke import Entity, Fact, Holding, Predicate
>>> no_license = Fact(
...     "$business was licensed as a money transmitting business",
...     truth=False,
...     terms=Entity("Helix"))
>>> operated = Fact(
...     "$person operated $business as a business",
...     terms=[Entity("Harmon"), Entity("Helix")])
>>> transmitting = Fact(
...     "$business was a money transmitting business",
...     terms=Entity("Helix"))
>>> offense = Fact(
...     "$person committed the offense of conducting an unlicensed money transmitting business",
...     terms=Entity("Harmon"))
>>> offense_holding = Holding.from_factors(
...     inputs=[operated, transmitting, no_license],
...     outputs=offense,
...     enactments=offense_statute,
...     universal=True)

This Holding simply says that if a person has committed the elements of the offense, the court may convict the person of the offense.

>>> print(offense_holding)
"""the Holding to ACCEPT
  the Rule that the court MAY ALWAYS impose the
    RESULT:
      the fact that <Harmon> committed the offense of conducting an
      unlicensed money transmitting business
    GIVEN:
      the fact that <Harmon> operated <Helix> as a business
      the fact that <Helix> was a money transmitting business
      the fact it was false that <Helix> was licensed as a money
      transmitting business
    GIVEN the ENACTMENT:
      "Whoever knowingly conducts, controls, manages, supervises, directs, or owns all or part of an unlicensed money transmitting business, shall be fined in accordance with this title or imprisoned not more than 5 years, or both." (/us/usc/t18/s1960/a 2013-07-18)"""

And then we can create the more important Holding of the case, in which the court found that a bitcoin transmitting business met the statutory definition of a “money transmitting” business requiring a license.

>>> definition_statute = CLIENT.read("/us/usc/t18/s1960/b/2")
>>> bitcoin = Fact(
...     "$business transferred bitcoin on behalf of the public",
...     terms=Entity("Helix"))
>>> bitcoin_holding = Holding.from_factors(
...     inputs=bitcoin,
...     outputs=transmitting,
...     enactments=definition_statute,
...     universal=True)
>>> print(bitcoin_holding)
"""the Holding to ACCEPT
  the Rule that the court MAY ALWAYS impose the
    RESULT:
      the fact that <Helix> was a money transmitting business
    GIVEN:
      the fact that <Helix> transferred bitcoin on behalf of the public
    GIVEN the ENACTMENT:
      "the term “money transmitting” includes transferring funds on behalf of the public by any and all means including but not limited to transfers within this country or to locations abroad by wire, check, draft, facsimile, or courier; and" (/us/usc/t18/s1960/b/2 2013-07-18)"""

By adding the two Holdings above, we get a new Holding indicating that if a person operated a business that transferred bitcoin on behalf of the public without a “money transmitting business” license, the person may be found guilty of the offense. To generate this Holding, AuthoritySpoke finds that the terms named “Harmon” and “Helix” in offense_holding can be matched to the terms with the same names in bitcoin_holding.

>>> result = bitcoin_holding + offense_holding
>>> print(result)
"""the Holding to ACCEPT
  the Rule that the court MAY ALWAYS impose the
    RESULT:
      the fact that <Harmon> committed the offense of conducting an
      unlicensed money transmitting business
      the fact that <Helix> was a money transmitting business
    GIVEN:
      the fact that <Harmon> operated <Helix> as a business
      the fact it was false that <Helix> was licensed as a money
      transmitting business
      the fact that <Helix> transferred bitcoin on behalf of the public
    GIVEN the ENACTMENTS:
      "Whoever knowingly conducts, controls, manages, supervises, directs, or owns all or part of an unlicensed money transmitting business, shall be fined in accordance with this title or imprisoned not more than 5 years, or both." (/us/usc/t18/s1960/a 2013-07-18)
      "the term “money transmitting” includes transferring funds on behalf of the public by any and all means including but not limited to transfers within this country or to locations abroad by wire, check, draft, facsimile, or courier; and" (/us/usc/t18/s1960/b/2 2013-07-18)"""

Finally, once that Holding is created, we can also generalize the Holding by using a new context to apply it to different generic terms.

>>> result_with_new_context = result.new_context(
...     ([Entity("Harmon"), Entity("Helix")],
...    [Entity("Schrute"), Entity("Schrute Bucks")]))
>>> print(result_with_new_context)
"""the Holding to ACCEPT
  the Rule that the court MAY ALWAYS impose the
    RESULT:
      the fact that <Schrute> committed the offense of conducting an
      unlicensed money transmitting business
      the fact that <Schrute Bucks> was a money transmitting business
    GIVEN:
      the fact that <Schrute> operated <Schrute Bucks> as a business
      the fact it was false that <Schrute Bucks> was licensed as a money
      transmitting business
      the fact that <Schrute Bucks> transferred bitcoin on behalf of the
      public
    GIVEN the ENACTMENTS:
      "Whoever knowingly conducts, controls, manages, supervises, directs, or owns all or part of an unlicensed money transmitting business, shall be fined in accordance with this title or imprisoned not more than 5 years, or both." (/us/usc/t18/s1960/a 2013-07-18)
      "the term “money transmitting” includes transferring funds on behalf of the public by any and all means including but not limited to transfers within this country or to locations abroad by wire, check, draft, facsimile, or courier; and" (/us/usc/t18/s1960/b/2 2013-07-18)"""