import proveit
from proveit import Literal, used_vars, free_vars
from proveit import a, b, c, d, f, n, x, y
from proveit.logic import And, Boolean, InSet, Equals, NotEquals
from proveit.numbers import zero, one, two, three, four, five, six, frac, num
from proveit.numbers import (Integer, Natural, NaturalPos,
Rational, RationalNonZero, RationalPos, Real,
RealNonNeg, RealNonPos, RealPos, Complex, ComplexNonZero)
from proveit.numbers import Add, Neg, Div, Exp, greater, greater_eq, Mult, sqrt, subtract
from proveit.numbers.exponentiation import sqrt_of_prod
%begin demonstrations
The `Exp` class allows us to represent exponentiation expressions such as $2^3$, $x^y$, or $(x-3)^2$. This ``_demonstrations_`` notebook explores the `Exp` (exponentiation) class, its axioms and common theorems, and related methods.
It is straightforward to construct expressions involving exponentiation. Here are some basic examples of such expressions:
# basic expression with exponent
Exp(x, y)
# exponentials involving variables and numbers
example1, example2, example3 = Exp(x, two), Exp(two, three), subtract(one, Exp(a, two))
# A sqrt portrayed with a radical is produced using the special sqrt() call,
# which invokes the Exp() class behind the scenes with special formatting
sqrt(Add(x, two))
Let's define a simple example exponential expression, $(x-y)^2$, and look at some of its attributes.
x_minus_y_quantity_squared = Exp(subtract(x,y), two)
x_minus_y_quantity_squared.expr_info()
We can access the base and exponent separately, and identify the `Exp` operator as the outermost operation:
x_minus_y_quantity_squared.base
x_minus_y_quantity_squared.exponent
x_minus_y_quantity_squared.operator
We can grab all the components (base and exponent) of the expression simultaneously as a tuple of expressions. We can also get a list of the variables and a separate list of the *free* variables in the expression (of course, in this expression, all the variables are also free variables):
x_minus_y_quantity_squared.operands
used_vars(x_minus_y_quantity_squared)
free_vars(x_minus_y_quantity_squared)
The ``axioms`` for the exponentiation theory establish the basic definitions of exponentiation … Actually, right now we have no separate axioms for the exponentiation theory.
The ``theorems`` for the exponentiation theory establish many of the basic laws of exponentiation as well as some closure principles.
# Some example test expressions involving Exp or sqrt()
exp_test_01, exp_test_02, exp_test_03 = Exp(x, y), Exp(two, three), sqrt(two)
Exp(three, three).evaluation()
Some testing of closure theorems.
InSet(exp_test_01, NaturalPos).prove(assumptions=[InSet(x, Natural), InSet(y, Natural)])
InSet(exp_test_01, Natural).prove(assumptions=[InSet(x, Natural), InSet(y, Natural)])
InSet(exp_test_01, Integer).prove(assumptions=[InSet(x, Integer), InSet(y, Natural)])
InSet(exp_test_01, Rational).prove(assumptions=[InSet(x, Rational), InSet(y, Natural)])
InSet(exp_test_01, Rational).prove(assumptions=[InSet(x, RationalNonZero), InSet(y, Integer)])
InSet(exp_test_01, RationalNonZero).prove(assumptions=[InSet(x, RationalNonZero), InSet(y, Integer)])
InSet(exp_test_01, RationalPos).prove(assumptions=[InSet(x, RationalPos), InSet(y, Integer)])
InSet(exp_test_01, Real).prove(assumptions=[InSet(x, Real), InSet(y, Natural)])
InSet(exp_test_01, Real).prove(assumptions=[InSet(x, RealPos), InSet(y, Integer)])
InSet(exp_test_01, RealPos).prove(assumptions=[InSet(x, RealPos), InSet(y, Integer)])
InSet(exp_test_01, RealNonNeg).prove(assumptions=[InSet(x, RealNonNeg), InSet(y, Integer)])
InSet(Exp(x, frac(one, two)), RealNonNeg).prove(assumptions=[InSet(x, RealNonNeg)])
InSet(exp_test_01, Complex).prove(assumptions=[InSet(x, Complex), InSet(y, Complex)])
InSet(exp_test_01, ComplexNonZero).prove(assumptions=[InSet(x, ComplexNonZero), InSet(y, Complex)])
InSet(Exp(three, two), RealPos).prove()
exp_test_03
InSet(exp_test_03, RealPos).prove()
InSet(two, RealPos).prove()
two_in_real_k_t = InSet(two, Real).prove()
two_in_real_k_t.proof()
sqrt2_is_complex = InSet(exp_test_03, Complex).prove()
t_ = Literal('t')
two_to_power_t = Exp(two, t_)
InSet(two_to_power_t, NaturalPos).prove(assumptions=[InSet(t_, NaturalPos)])
Testing the formatting of some Exp() and sqrt() outputs
InSet(exp_test_03, RealPos).prove()
Exp(x, frac(one, two))
sqrt_test = sqrt(Add(one, frac(a, b)))
sqrt_test
Add(two, sqrt_test)
Testing the Mult.combining_exponents() method (after eliminating Sqrt class)
mult_of_exps_test_01 = Mult(Exp(a, b), Exp(a, c))
mult_of_exps_test_02 = Mult(sqrt(two), sqrt(two))
mult_of_exps_test_03 = Mult(Exp(two, b), sqrt(two))
mult_of_exps_test_01.combining_exponents(assumptions=[InSet(a, RealPos), InSet(b, Complex), InSet(c, Complex), NotEquals(a, zero)])
mult_of_exps_test_02.expr_info()
mult_of_exps_test_02.combining_exponents(auto_simplify=False)
mult_of_exps_test_02.combining_exponents()
mult_of_exps_test_03.combining_exponents(assumptions=[InSet(b, Complex), InSet(frac(one, two), Complex), NotEquals(two, zero)])
expr_01, expr_02, expr_03, expr_04 = (
Exp(a, b), Exp(a, Add(b, c)), Exp(a, Add(b, c, d)), Exp(two, Add(one, two, c)))
# some general assumptions
temp_assumptions = [InSet(a, RealPos), InSet(b, RealPos),
InSet(c, RealPos), InSet(d, RealPos)]
# nothing to do if the exponent is not a sum:
try:
expr_01.exponent_separation()
except Exception as the_exception:
print("Error: {}".format(the_exception))
# a 2-addend exponent
expr_02.exponent_separation(assumptions=temp_assumptions)
# a 3-addend exponent
expr_03.exponent_separation(assumptions=temp_assumptions)
# a 3-addend exponent
expr_04.exponent_separation(assumptions=temp_assumptions)
factorization_assumptions = [InSet(a, Real), InSet(b, Real)]
exp_a_b = Exp(a, b)
# when the desired factor supplied is just the expression itself
exp_a_b.factorization(Exp(a, b), assumptions = factorization_assumptions)
# when the desired factor supplied is just the base itself
# and the base is known to be a non-zero Real
exp_a_b.factorization(
a,
assumptions = [InSet(a, Real), InSet(b, Integer), NotEquals(a, zero)])
# when the desired factor supplied is just the base itself
# and the base is known to be in RealPos
exp_a_b.factorization(
a,
assumptions = [InSet(a, RealPos), InSet(b, Integer)])
# and a more concrete case, illustrating the simplification
# of the resulting exponent(s) in the factors. Yay!
Exp(a, four).factorization(
a,
assumptions = [InSet(a, RealPos)])
# and a case like we encounter in the QPE package. Yay!
from proveit.physics.quantum.QPE import _t
Exp(two, _t).factorization(two, assumptions = [InSet(_t, NaturalPos)])
# now we can do some simple Div.cancelation() involving Exp class
Div(Exp(two, _t), two).cancelation(two, assumptions = [InSet(_t, NaturalPos)])
# and a special case
Exp(two, one).factorization(two)
# more generally, factor out a^c from a^b
Exp(a, b).factorization(
Exp(a, c),
assumptions = [InSet(a, RealPos), InSet(b, Integer), InSet(c, Integer)])
# Even more generally, factor out a^d from (a*b)^c
Exp(Mult(a, b), c).factorization(
a, pull='left',
assumptions = [InSet(a, RealPos), InSet(b, Integer),
InSet(c, RealPos)])
# Pull to the right
Exp(a, c).factorization(
a, pull='right', group_remainder=True,
assumptions = [InSet(a, RealPos), InSet(b, Integer),
InSet(c, RealPos)])
Exp(Mult(a, b), c).factorization(
a, pull='right', group_remainder=True,
assumptions = [InSet(a, RealPos), InSet(b, Integer),
InSet(c, RealPos)])
Exp(Mult(a, b), c).factorization(
Exp(a, c),
assumptions = [InSet(a, RealPos), InSet(b, Integer),
InSet(c, RealPos), InSet(d, Integer)])
Exp(Mult(a, b), c).factorization(
Exp(a, c), pull='right', group_remainder=True,
assumptions = [InSet(a, RealPos), InSet(b, Integer),
InSet(c, RealPos), InSet(d, Integer)])
Exp(Mult(a, b), c).factorization(
Exp(a, d), pull='right',
assumptions = [InSet(a, RealPos), InSet(b, Integer),
InSet(c, RealPos), InSet(d, Integer)])
Exp(Mult(a, b), c).factorization(
Exp(a, d), group_remainder=True,
assumptions = [InSet(a, RealPos), InSet(b, Integer),
InSet(c, RealPos), InSet(d, Integer)])
expr_mult_02, expr_mult_03 = (
Exp(Mult(a, b), f),
Exp(Mult(a, b, c), f))
# some general assumptions
temp_assumptions = [InSet(a, RealPos), InSet(b, NaturalPos), InSet(c, RealPos),
InSet(d, RealPos), InSet(f, Complex),
NotEquals(a, zero), NotEquals(b, zero), NotEquals(c, zero)]
expr_mult_02.distribution(assumptions=temp_assumptions)
expr_mult_03.distribution(assumptions=temp_assumptions)
expr_div_02 = Exp(Div(a, b), f)
expr_div_02.distribution(assumptions=temp_assumptions)
expr_exp_02 = Exp(Exp(a, b), f)
expr_exp_02.distribution(assumptions=temp_assumptions)
Exp.bound_via_operand_bound()
for $x^a$ where we know a relation for base $x$¶from proveit import a, b, c, d, u, v, w, x, y, z, defaults
from proveit.numbers import greater, greater_eq, Less, LessEq, RealNeg, RealNonNeg
defaults.assumptions = [InSet(a, RealPos), InSet(b, RealNonNeg), InSet(c, RealNeg),
InSet(d, RealNonPos), InSet(u, RealNeg), InSet(v, RealNeg),
InSet(x, Real), InSet(y, Real), InSet(z, Real),
InSet(w, RealPos), Less(u, v), LessEq(u, c),
greater(x, zero), greater(y, x), LessEq(x, z)]
exp_x_a, exp_x_b, exp_x_c, exp_x_d, exp_u_2 = Exp(x, a), Exp(x, b), Exp(x, c), Exp(x, d), Exp(u, two)
# Case (1): pos exponent, Less relation
exp_x_a.bound_via_operand_bound(Less(x, y))
# Case (2): pos exponent, LessEq relation
exp_x_a.bound_via_operand_bound(LessEq(x, z))
# Case (3): non-neg exponent, Less relation
exp_x_b.bound_via_operand_bound(Less(x, y))
# Case (4): non-neg exponent, LessEq relation
exp_x_b.bound_via_operand_bound(LessEq(x, z))
# Case (5): neg exponent, Less relation
exp_x_c.bound_via_operand_bound(Less(x, y))
# Case (6): neg exponent, LessEq relation
exp_x_c.bound_via_operand_bound(LessEq(x, z))
# Case (7): non-pos exponent, Less relation
exp_x_d.bound_via_operand_bound(Less(x, y))
# Case (8): non-pos exponent, LessEq relation
exp_x_d.bound_via_operand_bound(LessEq(x, z))
# Case (9): exponent = 2, Less relation, negative base
exp_u_2.bound_via_operand_bound(Less(u, v))
# Case (10): exponent = 2, LessEq relation, negative base
exp_u_2.bound_via_operand_bound(LessEq(u, c))
# more concrete case
Exp(w, two).bound_via_operand_bound(LessEq(w, two),
assumptions = defaults.assumptions + (LessEq(w, two),))
# more concrete case
from proveit.numbers import four
Exp(w, frac(one, two)).bound_via_operand_bound(LessEq(w, four),
assumptions = defaults.assumptions +
(LessEq(w, four), greater(frac(one, two), zero)))
# more concrete case
from proveit.numbers import four
Exp(w, three).bound_via_operand_bound(greater(w, four),
assumptions = defaults.assumptions +
(greater(w, four),))
Exp.bound_via_operand_bound()
for $a^x$ where we know a relation for exponent $x$¶from proveit import a, b, c, d, u, v, w, x, y, z, defaults
from proveit.numbers import greater, greater_eq, Less, LessEq, RealNeg, RealNonNeg
defaults.assumptions = [greater(a, one), greater(b, one), greater(c, one), greater(d, one),
InSet(a, Real), InSet(b, Real), InSet(c, Real),
InSet(d, Real), InSet(u, Real), InSet(v, Real), InSet(w, Real),
InSet(x, Real), InSet(y, Real), InSet(z, Real),
Less(x, y), LessEq(x, z), greater(x, v), greater_eq(x, w)]
exp_a_x, exp_b_x, exp_c_x, exp_d_x, exp_2_u = Exp(a, x), Exp(b, y), Exp(c, z), Exp(d, x), Exp(two, u)
# Case (1): base > 1, Less relation
exp_a_x.bound_via_operand_bound(Less(x, y))
# Case (2): base > 1, LessEq relation
exp_a_x.bound_via_operand_bound(LessEq(x, z))
# Case (3): base > 1, greater relation
exp_a_x.bound_via_operand_bound(greater(x, v))
# Case (4): base > 1, greater_eq relation
exp_a_x.bound_via_operand_bound(greater_eq(x, w))
Exp.power_of_log_reduction()
¶from proveit.numbers import Log
Exp(a, Log(a,x)).power_of_log_reduction(assumptions=[InSet(a, RealPos), InSet(x, RealPos), NotEquals(a, one)])
Exp(two, Log(two, Add(x, two))).power_of_log_reduction(
assumptions=[InSet(x, Real), greater(x, two)])
Exp.shallow_simplification()
¶Exp(two, Add(x, y, Neg(two))).canonical_form()
Exp(two, Add(x, y, Neg(two))).shallow_simplification(assumptions=[InSet(x, Complex), InSet(y, Complex)])
Exp(a, Log(a,x)).shallow_simplification(assumptions=[InSet(a, RealPos), InSet(x, RealPos), NotEquals(a, one)])
Exp(two, Log(two, Add(x, two))).shallow_simplification(
assumptions=[InSet(x, Real), greater(x, two)])
Exp(Add(a, Neg(b), Neg(c)), four).canonical_form() == Exp(Add(b, c, Neg(a)), four).canonical_form()
Equals(Exp(Add(a, Neg(b), Neg(c)), four), Exp(Add(b, c, Neg(a)), four)).prove(
assumptions=[InSet(a, Complex), InSet(b, Complex), InSet(c, Complex)])
%end demonstrations