import proveit
from proveit import a, b, c, d, x, L
from proveit.logic import Equals, InSet
from proveit.numbers import NaturalPos, Real, RealPos, Interval, IntervalCO
from proveit.numbers import Abs, Add, ModAbs, Mod, subtract, one, zero
%begin demonstrations
Some introductory comments here about the importance of modular arithmetic and its representation within Prove-It.
It is straightforward to construct modular arithmetic expressions and absolute value expressions. Here are some basic examples of such expressions:
# basic modular expression
Mod(a, b)
# basic ModAbs expression
ModAbs(a, b)
Let's define a simple Mod expression, $(a+b) \thinspace\text{mod}\thinspace c$, and look at some of its attributes.
a_plus_b_mod_c = Mod(Add(a, b), c)
a_mod_b = Mod(a, b)
We can use the `expr_info()` method to look at the how our mod expression is structured:
a_plus_b_mod_c.expr_info()
The operator for a Mod expression is simply the `mod` string:
a_plus_b_mod_c.operator
We can get a tuple of the operands and a list of the variables. We can also get a separate list of the *free* variables in the expression (of course, in this expression, all the variables are also free variables):
a_plus_b_mod_c.operands
from proveit import used_vars, free_vars
used_vars(a_plus_b_mod_c)
free_vars(a_mod_b)
We can replace selected variables in our expression with other variables:
a_plus_b_mod_c.basic_replaced({a:d})
And if needed we can reach down further into the expression to extract and manipulate specific pieces of the expression:
new = a_plus_b_mod_c.operands[0].basic_replaced({a:d})
The ``axioms`` for modular arithmetic …
Mod(x, L).simplification(assumptions=[InSet(L, NaturalPos), InSet(x, Interval(zero, subtract(L, one)))])
Mod(x, L).simplification(assumptions=[InSet(L, RealPos), InSet(x, IntervalCO(zero, L))])
Mod(Mod(x, L), L).simplification(assumptions=[InSet(L, RealPos), InSet(x, Real)])
ModAbs(Mod(x, L), L).simplification(assumptions=[InSet(L, RealPos), InSet(x, Real)])
Some temporary testing while the `modular` theory and demonstrations page are developed (this material can be deleted later once the demonstrations page is more established).
Testing `Mod.deduce_in_number_set()` method for constants and variables.
from proveit.logic import InSet, NotEquals
from proveit.numbers import zero, two, three, Integer, Natural, NaturalPos, Real
three_mod_two = Mod(three, two)
a_mod_b = Mod(a, b)
Testing `Mod.deduce_in_interval()` method.
three_mod_two.deduce_in_interval()
a_mod_b.deduce_in_interval(
assumptions=[InSet(a, Real), InSet(b, Real), NotEquals(b, zero)])
Testing `Mod.deduce_in_number_set()` method.
# deduce that int mod int is in the Integer set
three_mod_two.deduce_in_number_set(Integer)
# deduce that int mod int is in the Integer set
a_mod_b.deduce_in_number_set(
Integer,
assumptions=[InSet(a, Integer), InSet(b, Integer), NotEquals(b, zero)])
# deduce that int mod int is in the Natural set
three_mod_two.deduce_in_number_set(Natural)
# deduce that int mod int is in the Real set
three_mod_two.deduce_in_number_set(Real)
# deduce that int mod int is in the Real set
a_mod_b.deduce_in_number_set(
Real,
assumptions=[InSet(a, Real), InSet(b, Real), NotEquals(b, zero)])
# What happens if we try to deduce into an incorrect set?
try:
three_mod_two.deduce_in_number_set(NaturalPos)
except Exception as e:
print("EXCEPTION: ", e)
Testing `ModAbs` methods.
abs_three_mod_two = ModAbs(three, two)
abs_a_mod_b = ModAbs(a, b)
str(abs_three_mod_two)
abs_three_mod_two.deduce_in_number_set(Integer)
abs_three_mod_two.deduce_in_number_set(Real)
# what happens if we try to deduce into an incorrect set?
try:
abs_three_mod_two.deduce_in_number_set(Natural)
except Exception as the_exception:
print("EXCEPTION: ", the_exception)
Set some temporary assumptions for testing ModAbs methods:
from proveit import a, b, N
from proveit.numbers import Abs, Div, LessEq, subtract
temp_assumptions = [InSet(a, Real), InSet(b, Real), InSet(N, RealPos)]
ModAbs.difference_reversal()
¶ModAbs(subtract(a, b), N).difference_reversal(assumptions=temp_assumptions)
simplification
examples: removing redundant mods and removing abs¶# actually this is still an oversight; should do something like
# |(|a| mod N)| mod N = |a| mod N (I think)
ModAbs(Add(ModAbs(a, N), b), N).simplification()
ModAbs(Add(Mod(a, N), b), N).simplification(assumptions=temp_assumptions)
ModAbs(Add(Mod(a, N), b), N).simplification(
assumptions=temp_assumptions+[LessEq(Abs(Add(a, b)), Div(N, two))])
ModAbs(Add(a, b), N).simplification(
assumptions=temp_assumptions+[LessEq(Abs(Add(a, b)), Div(N, two))])
The following example eliminates a redundant (mod N) inside, then eliminates the unnecessary (mod N) outside, and finally eliminates the absolute value altogether:
from proveit.numbers import greater
ModAbs(Add(Mod(a, N), b), N).simplification(
assumptions=(
temp_assumptions+
[LessEq(Abs(Add(a, b)), Div(N, two)), greater(Add(a, b), zero)]))
%end demonstrations