import proveit
from proveit import defaults
from proveit import ExprTuple, ExprRange
from proveit import a, b, c, d, e, f, g, k, l, m, n, x, y, A, B, C
from proveit.core_expr_types import a_k
from proveit.logic import Equals, Forall, InSet, NotEquals
from proveit.numbers import Less, greater, LessEq, greater_eq, Neg, Exp, Mult, Div, frac
from proveit.numbers import zero, one,two, three,four, five, six, seven, eight
from proveit.numbers import Integer, Natural, NaturalPos, Real, RealPos, RealNeg, RealPos, RealNonNeg, RealNonPos
from proveit.numbers import Add, Complex, Neg, subtract, num
%begin demonstrations
Add(num(2), num(5)).evaluation()
Add(num(-3), num(4)).evaluation()
Add(num(3), num(-4)).evaluation()
Add(num(-3), num(-3)).evaluation()
Add(num(12), num(-3)).evaluation()
Add(num(10), num(1)).evaluation()
Add(num(19), num(1)).evaluation()
# multi-digit addition is currently only implemented for adding 1.
from proveit.logic import EvaluationError
try:
Add(num(19), num(10)).evaluation()
except EvaluationError as _e:
print(_e)
print('because multi-digit addition is not implemented beyond adding 1')
Add(frac(one, two), frac(one, two)).evaluation()
Add(one, frac(one, two)).evaluation()
Add(frac(one, three), one).evaluation()
subtract(one, frac(one, two)).evaluation()
Add(frac(num(2), num(3)), frac(num(3), num(2))).evaluation()
# This one fails because mult-digit addition is not implemented
try:
Add(frac(num(5), num(4)), frac(num(3), num(2))).evaluation()
except EvaluationError as _e:
print(_e)
print('because multi-digit addition is not implemented beyond adding 1')
quick_simplification
method¶The quick_simplification
method performs simplifications with respect to combining integers and expanding expression ranges in a quick-n-dirty manner that is appropriate for displaying purposes (e.g, expression ranges) where an actual proof is not necessary.
Add(Add(b, num(5)), num(4)).quick_simplification()
Add(num(5), num(5)).quick_simplification()
Add(num(5), num(-5)).quick_simplification()
Add(b, num(5)).quick_simplification()
Add(b, num(0)).quick_simplification()
Add(b, Add(Neg(c), num(-5))).quick_simplification()
Add(Add(b, num(2)), Add(c, num(5))).quick_simplification()
Add(Add(b, num(2)), Add(Neg(b), num(2))).quick_simplification()
Add(Add(b, num(5)), Add(c, num(-5))).quick_simplification()
Add(Add(b, num(5)), Add(Neg(c), num(5))).quick_simplification()
Add(num(-5), Add(c, num(5))).quick_simplification()
Add(num(-5), num(5)).quick_simplification()
Can also handle ranges of terms.
Add(Add(ExprRange(k, a_k, one, n), b),
Add(Neg(c), Neg(Add(ExprRange(k, a_k, one, n))))).quick_simplification()
Add(Add(ExprRange(k, a_k, one, n), b),
Add(c, ExprRange(k, a_k, one, n))).quick_simplification()
Add(Add(ExprRange(k, a_k, one, n), b),
Add(Neg(c), Neg(Add(ExprRange(k, a_k, one, subtract(n, two)))))).quick_simplification()
Add(Add(ExprRange(k, a_k, one, n), b),
Add(Neg(c), Add(ExprRange(k, a_k, one, subtract(n, two))))).quick_simplification()
Add(Add(ExprRange(k, a_k, one, n), b),
Add(Neg(c), Neg(Add(ExprRange(k, a_k, three, subtract(n, two)))))).quick_simplification()
Add(Add(ExprRange(k, a_k, one, n), b),
Add(Neg(c), Add(ExprRange(k, a_k, three, subtract(n, two))))).quick_simplification()
Add(Add(ExprRange(k, a_k, three, n), b),
Add(Neg(c), Neg(Add(ExprRange(k, a_k, one, subtract(n, two)))))).quick_simplification()
Add(Add(ExprRange(k, a_k, one, m), b),
Add(Neg(c), Neg(Add(ExprRange(k, a_k, one, n))))).quick_simplification()
Add(Add(ExprRange(k, Neg(a_k), one, m), b),
Add(Neg(c), Neg(Add(ExprRange(k, a_k, one, n))))).quick_simplification()
Add(Add(ExprRange(k, a_k, one, num(5)), b),
Add(Neg(c), Neg(Add(ExprRange(k, a_k, one, num(7)))))).quick_simplification()
Add(ExprRange(k, a_k, one, zero), b).quick_simplification()
The following simplifications come with actual proofs.
Add(b, b, b, b).simplification(assumptions=[InSet(b, Complex)])
Add(b, b, b, b).simplified(assumptions=[InSet(b, Complex)])
help(Add(b, b, b, b).simplified)
help(Equals(c, Add(b, b, b, b)).prove(
assumptions=[Equals(c, Add(b, b, b, b))]).inner_expr().rhs.simplify)
Equals(c, Add(b, b, b, b)).prove(
assumptions=[Equals(c, Add(b, b, b, b))]).inner_expr().rhs.simplification(
assumptions=[InSet(b, Complex)])
Add(one, zero, four, three).evaluation()
Equals(Add(one, two, three, one), seven).prove()
Add(Mult(one, b), Mult(three, b)).simplification(assumptions=[InSet(b, Complex)])
Add(b, Mult(three, b)).factorization(b, pull='right', assumptions=[InSet(a, Complex), InSet(c, Complex), InSet(b, Complex)])
Add(b, Mult(three, b), Mult(two, b)).factorization(b, pull='right', assumptions=[InSet(a, Complex), InSet(c, Complex), InSet(b, Complex)])
Add(b, Mult(three, b), Mult(two, b)).simplification(
assumptions=[InSet(a, Complex), InSet(c, Complex), InSet(b, Complex)])
Add(Mult(one, two), b, c, Mult(three, b), Mult(two, b), Mult(one, c)).simplification(
assumptions=[InSet(a, Complex), InSet(c, Complex), InSet(b, Complex)])
Add(Mult(one, two), b, c, Mult(three, b), Mult(two, b), Neg(b), Mult(one, c)).simplification(
assumptions=[InSet(a, Complex), InSet(c, Complex), InSet(b, Complex)])
#Add(Mult(c,b), Mult(b,c), Mult(c, a), a, b, c, one, two, three, Mult(two, c), Mult(three,b), Mult(four, a)).simplification([InSet(a, Complex), InSet(b, Complex), InSet(c, Complex)])
#Add(Mult(a,b), c, b,a).simplification([InSet(a, Complex), InSet(b, Complex), InSet(c, Complex)])
Add(a, one, a).simplification(assumptions=[InSet(a, Complex)])
Add(Mult(two, b), b, a, c, Mult(zero, d)).simplification(
assumptions=[InSet(a, Complex), InSet(c, Complex), InSet(b, Complex), InSet(d, Complex)])
Add(a,b,c,a,b,a,c).simplification(assumptions=[InSet(a, Complex), InSet(b, Complex), InSet(c, Complex)])
Add(a,b,c,a,b,a,c,b,a,c,a).simplification(assumptions=[InSet(a, Complex), InSet(b, Complex), InSet(c, Complex)])
Add(Neg(one), Neg(two)).evaluation()
# Multi-digit arithmetic needs to be implemented in order to
# get this to work w.r.t. indexing. So we comment this out for now.
#Add(a,b,c,a,b,a,c,b,a,c,a,a).simplification([InSet(a, Complex), InSet(b, Complex), InSet(c, Complex)]).proof()
Add(one, c, two, three, c, one,c).simplification(assumptions=[InSet(c, Complex)])
expr = Add(c, Neg(one), b, Add(two, three), Neg(c), Add(c, zero, c)).simplified(
assumptions=[InSet(c, Complex),InSet(b, Complex)])
Add(one, Neg(one), two, Neg(two)).cancelation(0, 1, auto_simplify=False)
Add(one, Neg(one), two, Neg(two)).cancelation(0, 1, auto_simplify=True)
Add(a, Neg(b), Neg(a), b).cancelations(assumptions=[InSet(a, Complex), InSet(b, Complex)], auto_simplify=False)
Add(a, Neg(b), Neg(a), b).cancelations(assumptions=[InSet(a, Complex), InSet(b, Complex)], auto_simplify=True)
Add(one, a, A, zero, b, B, C, c, one, three, A).simplification(
assumptions=[InSet(a, Complex), InSet(A, Complex), InSet(b, Complex), InSet(B, Complex),
InSet(c, Complex), InSet(C, Complex)])
Add(a, one, two , c, b, a, zero, b, c, c, three).simplification(
assumptions=[InSet(a, Complex), InSet(b, Complex), InSet(c, Complex)])
Add(two, three, four, a, a, c, zero, c, b, b).simplification(
assumptions=[InSet(a, Complex), InSet(b, Complex), InSet(c, Complex)])
Add(Neg(one), Neg(one)).simplification()
subtract(three, one).evaluation()
Add(zero, two, three, zero).evaluation()
Add(one, zero, one, three).evaluation()
Add(a, one, two , c, b, a, zero, b, c, c, three).simplification(
assumptions=[InSet(a, Real), InSet(b, Real), InSet(c, Real)])
InSet(Add(a,b), Integer).prove(assumptions=[InSet(a, Integer), InSet(b,Integer)])
InSet(Add(a,b,c,d), Integer).prove(
assumptions=[InSet(a,Integer),InSet(b, Integer), InSet(c, Integer), InSet(d,Integer)])
InSet(Add(a,b), Natural).prove(assumptions=[InSet(a, Natural), InSet(b, Natural)])
InSet(Add(a,b,c,d), Natural).prove(assumptions=[InSet(a,Natural), InSet(b, Natural), InSet(c,Natural), InSet(d, Natural)])
InSet(Add(a,b), Real).prove(assumptions=[InSet(a, Real), InSet(b,Real)])
InSet(Add(a,b,c,d), Real).prove(assumptions=[InSet(a,Real), InSet(b,Real), InSet(c, Real), InSet(d, Real)])
InSet(Add(a,b), Complex).prove(assumptions=[InSet(a, Complex), InSet(b, Complex)])
InSet(Add(a,b,c,d), Complex).prove(assumptions=[InSet(a, Complex), InSet(b, Complex), InSet(c, Complex), InSet(d,Complex)])
InSet(Add(a,b,one,d), NaturalPos).prove(assumptions=[InSet(a, Natural), InSet(b, Natural), InSet(c, Natural), InSet(d, Natural)])
Add(zero, b).zero_eliminations(assumptions=[InSet(b,Complex)])
Add(a,b,c,d).commutation(1,3, assumptions=[InSet(a,Real), InSet(b,Real), InSet(c, Real), InSet(d,Real)])
Add(one, two, three, four, five, six, one).association(3, length=2, assumptions = [], auto_simplify=False)
#Equals(subtract(two, one),one), Equals(subtract(one, one), zero), Equals(subtract(three, one), two), Less(zero,Less(one, Less(two, three)))
greater(Add(one, two, three, one), three)
greater(Add(one, two, three, one), three).prove(
assumptions=[InSet(two, RealPos), InSet(three, Real), InSet(one, RealPos)])
Less(Add(Neg(one), Neg(two), three, Neg(one)), three).prove(
assumptions=[InSet(two, RealNeg), InSet(three, Real), InSet(one, RealNeg),
InSet(Neg(one), RealNeg), InSet(Neg(two), RealNeg)])
subtract(x,x).evaluation(assumptions=[InSet(x, Complex)])
subtract(one,one).evaluation()
InSet(Neg(one), Real).prove()
#test = Add(Mult(two, b), Mult(three,b), b, Neg(b)).factor(b, assumptions=[InSet(two, Complex), InSet(three, Complex), InSet(b, Exp(Complex,one)),InSet(one, Complex), InSet(Neg(one), Complex), InSet(b, Real)])
#test = Add(Mult(two, b), Mult(three,b), b, Neg(b)).factor(b, assumptions=[InSet(Neg(one), Complex), InSet(b, Real)])
Add(Mult(two, b), Mult(three,b), b, Neg(b)).factorization(
b, pull='right', assumptions=[InSet(b, Real)], auto_simplify=False)
Add(Mult(two, b), Mult(three,b), b, Neg(b)).factorization(
b, pull='left', assumptions=[InSet(b, Real)], auto_simplify=False)
Add(Mult(two, b), Mult(three,b), b, Neg(b)).factorization(
b, pull='left', assumptions=[InSet(b, Real)])
Add(a,b,c,d,e,f,g).commutation(4, 2, assumptions=[InSet(a,Real),InSet(b,Real),InSet(c,Real),InSet(d,Real),InSet(e,Real),InSet(f,Real),InSet(g,Real)])
#m.prove([Add(m, subtract(one, one))])
Some working assumptions about some variables and parameters (side note: it might be useful to create an incidental derivation to produce the ExprRange $(a_1 \in \mathbb{C}), ..., (a_n \in \mathbb{C})$ from the Forall expression $\forall_{k\in\{1, 2, \ldots, n\}}\left(a_{k}\in\mathbb{C}\right)$).
assumptions = [InSet(a, Complex), InSet(b, Complex), InSet(c, Complex), InSet(d, Complex),
NotEquals(b, zero), NotEquals(d, zero), InSet(n, NaturalPos),
InSet(m, Natural), ExprRange(k, InSet(a_k, Complex), one, n)]
Some example Div
s to add together:
example_div_01, example_div_02, example_div_03 = (
frac(a, d), frac(b, d), frac(c, b) )
And (at last!), some example sums:
example_sum_01, example_sum_02, example_sum_03, example_sum_04, example_sum_05, example_sum_06 = (
Add(example_div_01, example_div_02),
Add(ExprRange(k, frac(a_k, d), one, n)),
Add(example_div_01, example_div_02, ExprRange(k, frac(a_k, d), one, n)),
Add(example_div_01, example_div_02, example_div_03),
Add(example_div_01, example_div_02, Mult(a,d)),
Add(ExprRange(k, frac(d, a_k), one, m)))
example_sum_01
example_sum_01.combining_terms(assumptions=assumptions)
# The Add.combine_like_denoms simplification directive is False by default:
example_sum_01.simplification(assumptions=assumptions)
# We can temporarily set Add.combine_like_denoms to True
with Add.temporary_simplification_directives() as tmp_directives:
tmp_directives.combine_like_denoms = True
example_sum_01.simplification(assumptions=assumptions)
example_sum_02
example_sum_02.combining_terms(assumptions=assumptions)
# The Add.combine_like_denoms simplification directive is False by default:
example_sum_02.simplification(assumptions=assumptions)
# We can temporarily set Add.combine_like_denoms to True
with Add.temporary_simplification_directives() as tmp_directives:
tmp_directives.combine_like_denoms = True
example_sum_02.simplification(assumptions=assumptions)
Given that the simplification() process works with that single ExprRange of Divs, it's interesting to see that we run into trouble when taking the sum of two such sums. Consider:
sum_two_expr_ranges = Add(example_sum_02, example_sum_02)
try:
InSet(example_sum_02, Complex).prove(assumptions=assumptions)
except Exception as the_exception:
print("Exception: {}".format(the_exception))
In fact, that InstantiationFailure due to the unsatisfied condition of the sum being in Complex is an interesting error. Notice that we cannot even get that from a goal-oriented manual request, even if we augment the assumptions to be more explicit about each frac itself being Complex:
try:
InSet(example_sum_02, Complex).prove(
assumptions=assumptions+[ExprRange(k, InSet(frac(a_k, d), Complex), one, n)])
except Exception as the_exception:
print("Exception: {}".format(the_exception))
Simplifying a term that is an Add consisting of both simple terms and an ExprRange leads to a problem not yet addressed.
example_sum_03
The direct calling of the Add.combining_terms() works just fine:
example_sum_03.combining_terms(assumptions=assumptions)
But the automatic simplification (without setting Add.combine_like_denoms to True) raises an AttributeError:
try:
example_sum_03.simplification(assumptions=assumptions)
except AttributeError as the_exception:
print("AttributeError: {}".format(the_exception))
But the automatic simplification when setting Add.combine_like_denoms to True works just fine:
# interestingly, this still works fine:
with Add.temporary_simplification_directives() as tmp_directives:
tmp_directives.combine_like_denoms = True
example_sum_03.simplification(assumptions=assumptions)
example_sum_04
# this should raise an error, because the addends are not all like terms
try:
example_sum_04.combining_terms(assumptions=assumptions)
except ValueError as the_error:
print("ValueError: {}".format(the_error))
example_sum_04.simplification(assumptions=assumptions)
with Add.temporary_simplification_directives() as tmp_directives:
tmp_directives.combine_like_denoms = True
example_sum_04.simplification(assumptions=assumptions)
example_sum_05
# this should raise an error, because the addends are not all like terms
try:
example_sum_05.combining_terms(assumptions=assumptions)
except Exception as the_exception:
print("Exception: {}".format(the_exception))
# The Add.combine_like_denoms simplification directive is False by default:
example_sum_05.simplification(assumptions=assumptions)
# But we can temporarily set Add.combine_like_denoms to True:
with Add.temporary_simplification_directives() as tmp_directives:
tmp_directives.combine_like_denoms = True
example_sum_05.simplification(assumptions=assumptions)
We shouldn't be able to combine a sum of terms like $(\frac{d}{a_1}+\frac{d}{a_2}+\ldots+\frac{d}{a_m})$, but the error(s) being raised indicate that there is some other problem occurring that needs addressed (in fact there are both ValueError and NotImplementedError being raised):
example_sum_06
# should raise an error when blindly calling combining_terms()
# when not all terms are like-terms:
try:
example_sum_06.combining_terms(assumptions=assumptions)
except Exception as the_exception:
print("Exception: {}".format(the_exception))
# simplification should do nothing here:
example_sum_06.simplification(assumptions=assumptions)
# Now, combine Div terms where possible,
# BUT the parameter-dependent fractions are a problem
try:
with Add.temporary_simplification_directives() as tmp_directives:
tmp_directives.combine_like_denoms = True
example_sum_06.simplification(assumptions=assumptions)
except Exception as the_exception:
print("Exception: {}".format(the_exception))
Testing the deduce_bound()
method.
term_relations = [Less(a, c), Less(b, d)]
assumptions = term_relations + [InSet(a, Real), InSet(b, Real), InSet(c, Real), InSet(d, Real)]
Add(a, b).deduce_bound(term_relations[0], assumptions=assumptions)
Add(a, b).deduce_bound(term_relations[1], assumptions=assumptions)
Add(a, b).deduce_bound(term_relations, assumptions=assumptions)
term_relations = [greater(a, c), greater(b, d)]
assumptions = term_relations + [InSet(a, Real), InSet(b, Real), InSet(c, Real), InSet(d, Real)]
Add(a, b).deduce_bound(term_relations[0], assumptions=assumptions)
Add(a, b).deduce_bound(term_relations[1], assumptions=assumptions)
Add(a, b).deduce_bound(term_relations, assumptions=assumptions)
Add(a, b, c, d).bound_by_term(
1, assumptions=[InSet(a, RealPos), InSet(b, Real), InSet(c, RealPos), InSet(d, RealPos)])
Add(a, b, c, d).bound_by_term(
2, assumptions=[InSet(a, RealNeg), InSet(b, RealNeg), InSet(c, Real), InSet(d, RealNeg)])
Add(a, b, c, d).bound_by_term(
0, assumptions=[InSet(a, Real), InSet(b, RealNonNeg), InSet(c, RealNonNeg), InSet(d, RealNonNeg)])
Add(a, b, c, d).bound_by_term(
3, assumptions=[InSet(a, RealNonPos), InSet(b, RealNonPos), InSet(c, RealNonPos), InSet(d, Real)])
Two expressions that have the same canonical form can be proven to be equal via automation.
defaults.assumptions = [InSet(a, RealNeg), InSet(b, RealNeg), InSet(c, Real), InSet(d, RealNeg)]
expr1 = Add(d, c, Mult(two, b), c, frac(a, two))
display(expr1)
expr1.canonical_form()
expr2 = Add(a, Neg(frac(a, two)), b, d, b, Mult(two, c))
display(expr2)
expr2.canonical_form()
Equals(expr1, expr2).prove()
Equals(Add(c, b, d, a), Add(d, b, a, c)).prove()
Equals(Add(d, c, b, a), Add(b, a, d, c)).prove()
This even works in a nested manner
Equals(Add(Mult(b, a), d, c, a), Add(d, c, Mult(a, b), a)).prove()
%end demonstrations