import proveit
from proveit import a, b, c, d, e, x, A, B, C
from proveit import InstantiationFailure, ProofFailure
from proveit.logic import Equals, Forall, InSet, Not, Set, SetEquiv, SetNotEquiv
from proveit.numbers import one, two, three, four, five, Real
from proveit.logic.sets.equivalence import set_equiv_def, set_not_equiv_def
from proveit.logic.sets.equivalence import (
set_equiv_reflexivity, set_equiv_reversal, set_equiv_transitivity)
%begin demonstrations
The Set Equivalence class, SetEquiv, is intended to capture the membership equivalence of 2 structures A and B. $A \cong B$, coded in Prove-It by SetEquiv(A, B) is a claim that all elements of A are also elements of B and vice-versa, and uses the congruence symbol $\cong$ to distinguish the SetEquiv claim from the stronger claim that $A = B$.</font>
Set Equivalence expressions are easy to construct …
Let's look at some simple examples of set equivalence expressions and their common attributes.
SetEquiv(A, B)
The axiomatic basis for set equivalence currently consists of two axioms, one defining set equivalence in terms of membership and one defining set non-equivlance (these can be found in the [set equivalence theorems Jupyter Python notebook](axioms.ipynb) ):
set_equiv_def
set_not_equiv_def
The `logic.sets/equivalence` theory already has a number of related theorems and conjectures established, many of which are related to set equivalence being an equivalence relation. Some illustrative examples of the theorems are shown below, and the remainder can be found in the [set equivalence theorems Jupyter Python notebook](theorems.ipynb).
set_equiv_reflexivity
set_equiv_reversal
set_equiv_transitivity
The material below was developed to test various SetEquiv-related methods. Some of this material could be integrated into the `_demonstrations_` page eventually and/or deleted as development continues.
Sets
For Testing¶# some standard enumerated sets
from proveit import e
set_12345, set_abcde, set_1a2b3c, power_set_of_ab, empty_set = (
Set(one, two, three, four, five),
Set(a, b, c, d, e),
Set(one, a, two, b, three, c),
Set(Set(), Set(a), Set(b), Set(a,b)),
Set())
# some non-standard enumerated sets pretending to be multi-sets (but not!)
set_12131, set_1a1b2a = (
Set(one, two, one, three, one),
Set(one, a, one, b, two, a))
SetEquiv.conclude()
methodThe conclude()
method is a general method with the following format:
and attempts to conclude the equivalence in various ways: (1) using simple reflexivity (A equiv A); (2) via an evaluation (if one side is an irreducible); or (3) via transitivity.
SetEquiv(C, C).conclude()
# As one would expect, we cannot conclude a set-equivalence between
# two arbitrary sets
try:
SetEquiv(Set(one, two, three), Set(a, b, c)).conclude()
assert False, "Should not get this far!"
except ProofFailure as the_error:
print("ProofFailure: {}".format(the_error))
# This also doesn't work even with these proper assumptions because
# these substitutions are not made automatically.
try:
SetEquiv(Set(one, d, three), Set(a, b, c)).conclude(
assumptions=[Equals(a, one), Equals(b, d), Equals(c, three)])
assert False, "Should not get this far!"
except ProofFailure as the_error:
print("ProofFailure: {}".format(the_error))
# But evaluations to irreducible values are special in this regard and we can prove the following.
SetEquiv(Set(one, two, three), Set(a, b, c)).conclude(
assumptions=[Equals(a, one), Equals(b, two), Equals(c, three)])
SetEquiv.conclude_via_reflexivity()
methodThe conclude_via_reflexivity()
method has the following format:
and attempts to prove and return self of the form A equiv A.
# Notice that reflexivity of set equivalence should generally
# not require any assumptions
SetEquiv(A, A).conclude_via_reflexivity()
SetEquiv(Set(a, two, c), Set(a, two, c)).conclude_via_reflexivity()
# We can use standard pre-defined sets as well
SetEquiv(Real, Real).conclude_via_reflexivity()
# in fact, reflexivity is captured generally in the conclude()
# method, allowing Prove-It to prove() reflexive set equivalence claims
SetEquiv(Set(a, b, three), Set(a, b, three)).prove()
# If the 'self' object on which we call the conclude_via_reflexivity() method
# is not actually reflexive (i.e. the lhs and rhs are not literally the same),
# we get an error:
try:
SetEquiv(A, B).conclude_via_reflexivity()
assert False, "Should not make it this far!"
except ProofFailure as the_error:
print("AssertionError: {}".format(the_error))
SetEquiv(A, B).conclude_via_reflexivity(assumptions=[Equals(A, B)])
SetEquiv.conclude_as_folded()
methodThe conclude_as_folded()
method has the following format:
and is described as attempting to conclude A set_equiv B
from $\forall_{x} [(x \in A) = (x \in B)]$. This is somewhat confusing, since the method is called on the SetEquiv(A, B)
object itself.
SetEquiv(A, B).conclude_as_folded(assumptions=[Forall(x, Equals(InSet(x, A), InSet(x, B)))])
SetEquiv(Set(one, two , three), Set(a, b, c)).conclude_as_folded(
assumptions=[Forall(x, Equals(InSet(x, Set(one, two, three)), InSet(x, Set(a, b, c))))])
# We can use standard pre-defined sets as well
SetEquiv(A, Real).conclude_as_folded(assumptions=[Forall(x, Equals(InSet(x, A), InSet(x, Real)))])
# We must already know or assume that the membership claims are equal
try:
SetEquiv(Set(one, two , three), Set(a, b, c)).conclude_as_folded()
assert False, "Should not make it this far!"
except InstantiationFailure as the_error:
print("InstantiationFailure: {}".format(the_error))
SetEquiv.unfold()
methodThe unfold()
method has the following format:
and from A setequiv B attempts to derive $\forall{x} [ (x \in A) = (x \in B)]$.
SetEquiv(A, B).unfold(assumptions=[SetEquiv(A, B)])
SetEquiv(Set(one, two , three), Set(a, b, c)).unfold(
assumptions=[SetEquiv(Set(one, two , three), Set(a, b, c))])
# We can use standard pre-defined sets as well
SetEquiv(A, Real).unfold(assumptions=[SetEquiv(A, Real)])
# We must already know or assume that the SetEquiv holds in one direction
try:
SetEquiv(Set(one, two , three), Set(a, b, c)).unfold()
assert False, "Should not make it this far!"
except InstantiationFailure as the_error:
print("InstantiationFailure: {}".format(the_error))
SetEquiv.derive_reversed()
methodThe derive_reversed()
method has the following format:
and from A set_equiv B attempts to derive B set_equiv A. This derivation is also an automatic side-effect.
SetEquiv(A, B).derive_reversed(assumptions=[SetEquiv(A, B)])
SetEquiv(Set(one, two , three), Set(a, b, c)).derive_reversed(
assumptions=[SetEquiv(Set(one, two , three), Set(a, b, c))])
# We can use standard pre-defined sets as well
SetEquiv(A, Real).derive_reversed(assumptions=[SetEquiv(A, Real)])
# We must already know or assume that the SetEquiv holds in one direction
try:
SetEquiv(Set(one, two , three), Set(a, b, c)).derive_reversed()
assert False, "Should not make it this far!"
except InstantiationFailure as the_error:
print("InstantiationFailure: {}".format(the_error))
SetEquiv.deduce_not_equiv()
methodThe deduce_not_equiv()
method has the following format:
and attempts to deduce A not_equiv B assuming not(A equiv B), but where self is (A equiv B). This can be a bit confusing …
SetEquiv(A, B).deduce_not_equiv(assumptions=[Not(SetEquiv(A, B))])
SetEquiv(Set(one, two, three), Set(a, b, c)).deduce_not_equiv(assumptions=[Not(SetEquiv(Set(one, two, three), Set(a, b, c)))])
# despite the apparent disconnect between the 'self' SetEquiv, that SetEquiv must
# use the same sets being used in the conclusion
try:
SetEquiv(Set(one, two, four), Set(a, b, c)).deduce_not_equiv(
assumptions=[Not(SetEquiv(Set(one, two, three), Set(a, b, c)))])
assert False, "Should not make it this far!"
except InstantiationFailure as the_error:
print("InstantiationFailure: {}".format(the_error))
SetEquiv.apply_transitivity()
methodThe apply_transitivity()
method has the following format:
From A set_equiv B (self) and B set_equiv C (other) attempt to derive and return A set_equiv C. If "other" is not a SetEquiv, reverse roles and call 'apply_transitivity' from the "other" side.
SetEquiv(Set(one, two, three), Set(two, three, one)).apply_transitivity(
SetEquiv(Set(two, three, one), Set(b, c, a)),
assumptions=[SetEquiv(Set(one, two, three), Set(two, three, one)),
SetEquiv(Set(two, three, one), Set(b, c, a))])
SetEquiv(A, B).apply_transitivity(
SetEquiv(B, C), assumptions=[SetEquiv(A, B), SetEquiv(B, C)])
SetEquiv.deduce_in_bool()
methodThe deduce_in_bool()
method has the following format:
and attempts to deduce and return that this SetEquiv
claim is in the Boolean
set.
SetEquiv(Set(one, two, three), Set(two, three, one)).deduce_in_bool()
SetEquiv(Set(one, two, three), Set(four, five)).deduce_in_bool()
SetEquiv(Set(one, two, three), Set(two, three, a)).deduce_in_bool(assumptions=[Equals(a, one)])
SetNotEquiv.derive_reversed()
methodThe derive_reversed()
method has the following format:
and from A not_equiv B attempts to derive B not_equiv A. This derivation is also an automatic side-effect in the side_effects() method.
SetNotEquiv(A, B).derive_reversed(assumptions=[SetNotEquiv(A, B)])
SetNotEquiv(Set(one, two , three), Set(a, b, c)).derive_reversed(
assumptions=[SetNotEquiv(Set(one, two , three), Set(a, b, c))])
# We can use standard pre-defined sets as well
SetNotEquiv(A, Real).derive_reversed(assumptions=[SetNotEquiv(A, Real)])
# We must already know or assume that the SetNotEquiv holds in one direction
try:
SetNotEquiv(Set(one, two , three), Set(a, b, c)).derive_reversed()
assert False, "Should not make it this far!"
except InstantiationFailure as the_error:
print("InstantiationFailure: {}".format(the_error))
SetNotEquiv.definition()
methodThe definition()
method has the following format:
and returns (A not_equiv B) = Not(A equiv B) starting with self (A not_equiv B).
SetNotEquiv(A, B).definition()
# Notice the definition does not depend on the Truth of the SetNotEquiv claim:
SetNotEquiv(Set(one, two, three), Set(one, two, three)).definition()
# Notice the definition does not depend on the Truth of the SetNotEquiv claim,
# nor on any assumptions supplied:
SetNotEquiv(Set(one, two, three), Set(a, b, c)).definition(assumptions=[Equals(a, one)])
SetNotEquiv.unfold()
methodThe unfold()
method has the following format:
and attempts to derive and return Not(SetEquiv(A, B)) from known or assumed SetNotEquiv(A, B).
SetNotEquiv(A, B).unfold(assumptions=[SetNotEquiv(A, B)])
SetNotEquiv(Set(one, two , three), Set(a, b, c)).unfold(
assumptions=[SetNotEquiv(Set(one, two , three), Set(a, b, c))])
# We can use standard pre-defined sets as well
SetNotEquiv(B, Real).unfold(assumptions=[SetNotEquiv(B, Real)])
# We must already know or assume that the SetNotEquiv holds in one direction
try:
SetNotEquiv(Set(one, two , three), Set(a, b, c)).unfold()
assert False, "Should not make it this far!"
except InstantiationFailure as the_error:
print("InstantiationFailure: {}".format(the_error))
SetNotEquiv.conclude_as_folded()
methodThe conclude_as_folded()
method has the following format:
and attempts to conclude the NotSetEquiv(A, B) from the known or assumed Not(SetEquiv(A, B)).
SetNotEquiv(A, B).conclude_as_folded(assumptions=[Not(SetEquiv(A, B))])
SetNotEquiv(Set(one, two, three), Set(two, three, a)).conclude_as_folded(
assumptions=[Not(SetEquiv(Set(one, two, three), Set(two, three, a)))])
SetNotEquiv.derive_contradiction()
methodThe derive_contradiction()
method has the following format:
and from A not_equiv B, and assuming (A equiv B), derives and returns FALSE.
SetNotEquiv(A, B).derive_contradiction(assumptions=[SetEquiv(A, B), SetNotEquiv(A, B)])
SetNotEquiv(Set(one, two, three), Set(two, three, a)).derive_contradiction(
assumptions=[SetNotEquiv(Set(one, two, three), Set(two, three, a)),
SetEquiv(Set(one, two, three), Set(two, three, a))])
SetNotEquiv.deduce_in_bool()
methodThe deduce_in_bool()
method has the following format:
and attempts to deduce and return that this SetNotEquiv
claim is in the Boolean
set.
SetNotEquiv(Set(one, two, three), Set(two, three, one)).deduce_in_bool()
SetNotEquiv(Set(one, two, three), Set(four, five)).deduce_in_bool()
SetNotEquiv(Set(one, two, three), Set(two, three, a)).deduce_in_bool(assumptions=[Equals(a, one)])
%end demonstrations