Ejemplo n.º 1
0
 def add_reduction(reduction, _radius, _theta):
     '''
     Add the given reduction.  First check that its left and
     rights sides are as expected: the left should be the polar
     form and the right should be the original expression.
     '''
     polar_form = Mult(_radius, Exp(e, Mult(i, _theta)))
     assert (isinstance(reduction, Judgment)
             and isinstance(reduction.expr, Equals)
             and reduction.lhs == polar_form and reduction.rhs
             == orig_expr), ("Reduction, %s, not a judgement "
                             "for %s = %s" %
                             (reduction, polar_form, orig_expr))
     if do_include_unit_length_reduction and _radius == one:
         # As a unit length complex number, let's include the
         # reduction from the unit length form in case a unit length
         # formula is applied (cover the bases).
         # The 'automation' allowed here is negligible (assuming
         # we have already proven appropriate set membership by this
         # point).
         reductions.add(reduction.inner_expr().lhs.eliminate_one(
             0, automation=True))
         # But prepare for a multi-stage reduction:
         # 1 * exp[i * theta] = 1 * orig_expr = orig_expr
         reductions.add(
             Mult(one, orig_expr).one_elimination(0, automation=True))
     elif reduction.lhs != reduction.rhs:
         reductions.add(reduction)
Ejemplo n.º 2
0
    def exponent_separation(self, **defaults_config):
        '''
        From self of the form x^{a+b} deduce and return the equality
        x^{a+b} = x^a x^b. For example,
            Exp(x, Add(two, c)).split_exponent_sum()
        (with the apprpriate assumptions) should return:
            |- (x^{2+c}) =  x^2 x^c.
        '''
        # among other things, convert any assumptions=None
        # to assumptions=()
        # assumptions = defaults.checkedAssumptions(assumptions)

        from proveit.numbers import Add, Mult

        # implement only for the case in which exponent is an Add
        if not isinstance(self.exponent, Add):
            raise NotImplementedError(
            "'Exp.exponent_separation()' implemented only for cases in which "
            "the exponent appears as a sum (i.e. in the Add class). The "
            "exponent in this case is {0}.".format(self.exponent))

        # list the addends in the exponent, which become exponents
        the_exponents = self.exponent.operands

        # list the new exponential factors
        the_new_factors = [Exp(self.base, new_exp) if new_exp != one
                           else self.base for new_exp in the_exponents]

        # create the new equivalent product (Mult)
        mult_equiv = Mult(*the_new_factors)

        # use the Mult.exponent_combination() to deduce equality to self
        exp_separated = mult_equiv.exponent_combination()

        replacements = list(defaults.replacements)
        if defaults.auto_simplify:
            with Mult.temporary_simplification_directives() as tmp_directives:
                # Don't recombine the exponents after separating them.
                tmp_directives.combine_exponents = False
                replacements.append(mult_equiv.shallow_simplification())

        # reverse the equality relationship and return
        return exp_separated.derive_reversed(replacements=replacements,
                                             auto_simplify=False)
Ejemplo n.º 3
0
 def add_reduction(reduction, _theta):
     '''
     Add the given reduction.  First check that its left and
     rights sides are as expected: the left should be the polar
     form and the right should be the original expression.
     '''
     polar_form = Exp(e, Mult(i, _theta))
     assert (isinstance(reduction, Judgment)
             and isinstance(reduction.expr, Equals)
             and reduction.lhs == polar_form and reduction.rhs == orig_expr)
     if reduction.lhs != reduction.rhs:
         reductions.add(reduction)
Ejemplo n.º 4
0
                      Sum(y_etc, frac(Py_etc, z), domain=S)),
               domain=Complex)))
distributefrac_through_summation

distributefrac_through_summation_rev = Forall(
    [P, S],
    Implies(
        Forall(y_etc, InSet(Py_etc, Complex), domain=S),
        Forall(z,
               Equals(Sum(y_etc, frac(Py_etc, z), domain=S),
                      frac(Sum(y_etc, Py_etc, domain=S), z)),
               domain=Complex)))
distributefrac_through_summation_rev

frac_in_prod = Forall([w_etc, x, y, z_etc],
                      Equals(Mult(w_etc, frac(x, y), z_etc),
                             frac(Mult(w_etc, x, z_etc), y)),
                      domain=Complex)
frac_in_prod

frac_in_prod_rev = Forall([w_etc, x, y, z_etc],
                          Equals(frac(Mult(w_etc, x, z_etc), y),
                                 Mult(w_etc, frac(x, y), z_etc)),
                          domain=Complex)
frac_in_prod_rev

prod_of_fracs = Forall([x, y, z, w],
                       Equals(Mult(frac(x, z), frac(y, w)),
                              frac(Mult(x, y), Mult(z, w))),
                       domain=Complex)
prod_of_fracs
Ejemplo n.º 5
0
    def factorization(self,
                      the_factor,
                      pull="left",
                      group_factors=True,
                      field=None,
                      **defaults_config):
        '''
        Deduce an equality between this VecAdd expression and a
        version in which either:
        (1) the scalar factor the_factor has been factored out in
            front (or possibly out behind) to produce a new ScalarMult;
        OR
        (2) the tensor product factor the_factor has been factored
            out in front (or possible out behind) to produce a new
            TensorProd.
        For example, if
            x = VecAdd(ScalarMult(a, v1), ScalarMult(a, v2))
        then x.factorization(a) produces:
            |- x = ScalarMult(a, VecAdd(v1, v2)).
        Prove-It will need to know or be able to derive a vector space
        in which the vectors live.
        This method only works if the terms of the VecAdd are all
        ScalarMult objects or all TensorProd objects.
        In the case of all ScalarMult objects, any nested ScalarMult
        objects are first flattened if possible.
        Note: In the case of a VecAdd of all TensorProd objects,
        the lack of commutativity for tensor products limits any
        factorable tensor product factors to those occurring on the
        far left or far right of each tensor product term. Thus, for
        example, if
        x = VecAdd(TensorProd(v1, v2, v3), TensorProd(v1, v4, v5))
        we can call x.factorization(v1) to obtain
        |- x =
        TensorProd(v1, VecAdd(TensorProd(v2, v3), TensorProd(v4, v5))),
        but we cannot factor v1 our of the expression
        y = VecAdd(TensorProd(v2, v1, v3), TensorProd(v4, v1, v5))
        '''

        expr = self
        eq = TransRelUpdater(expr)

        replacements = list(defaults.replacements)

        from proveit.linear_algebra import ScalarMult, TensorProd
        from proveit.numbers import one, Mult

        # Case (1) VecAdd(ScalarMult, ScalarMult, ..., ScalarMult)
        if all(isinstance(op, ScalarMult) for op in self.operands):
            # look for the_factor in each scalar;
            # code based on Add.factorization()
            _b = []
            for _i in range(expr.terms.num_entries()):
                # remove nesting of ScalarMults
                term = expr.terms[_i].shallow_simplification().rhs
                expr = eq.update(
                    expr.inner_expr().terms[_i].shallow_simplification())
                # simplify the scalar part of the ScalarMult
                term = term.inner_expr().scalar.shallow_simplification().rhs
                expr = eq.update(expr.inner_expr().terms[_i].scalar.
                                 shallow_simplification())
                if hasattr(term.scalar, 'factorization'):
                    term_scalar_factorization = term.scalar.factorization(
                        the_factor,
                        pull,
                        group_factors=group_factors,
                        group_remainder=True,
                        preserve_all=True)
                    if not isinstance(term_scalar_factorization.rhs, Mult):
                        raise ValueError(
                            "Expecting right hand side of each factorization "
                            "to be a product. Instead obtained: {}".format(
                                term_scalar_factorization.rhs))
                    if pull == 'left':
                        # the grouped remainder on the right
                        _b.append(
                            ScalarMult(
                                term_scalar_factorization.rhs.operands[-1],
                                term.scaled))
                    else:
                        # the grouped remainder on the left
                        _b.append(
                            ScalarMult(
                                term_scalar_factorization.rhs.operands[0],
                                term.scaled))
                    # substitute in the factorized term
                    expr = eq.update(
                        term_scalar_factorization.substitution(
                            expr.inner_expr().terms[_i].scalar,
                            preserve_all=True))
                else:
                    if term.scalar != the_factor:
                        raise ValueError(
                            "Factor, %s, is not present in the term at "
                            "index %d of %s!" % (the_factor, _i, self))
                    if pull == 'left':
                        replacements.append(
                            Mult(term.scalar, one).one_elimination(1))
                    else:
                        replacements.append(
                            Mult(one, term.scalar).one_elimination(0))
                    _b.append(ScalarMult(one, term.scaled))

            if not group_factors and isinstance(the_factor, Mult):
                factor_sub = the_factor.operands
            else:
                factor_sub = ExprTuple(the_factor)

            # pull left/right not really relevant for the ScalarMult
            # cases; this simplification step still seems relevant
            if defaults.auto_simplify:
                # Simplify the remainder of the factorization if
                # auto-simplify is enabled.
                replacements.append(VecAdd(*_b).simplification())

            from proveit import K, i, k, V, a
            # Perhaps here we could search through the operands to find
            # an appropriate VecSpace? Or maybe it doesn't matter?
            vec_space_membership = expr.operands[0].deduce_in_vec_space(
                field=field)
            _V_sub = vec_space_membership.domain
            _K_sub = VecSpaces.known_field(_V_sub)
            _i_sub = expr.operands.num_elements()
            _k_sub = the_factor
            _a_sub = ExprTuple(*_b)

            from proveit.linear_algebra.scalar_multiplication import (
                distribution_over_vectors)
            distribution = distribution_over_vectors.instantiate(
                {
                    V: _V_sub,
                    K: _K_sub,
                    i: _i_sub,
                    k: _k_sub,
                    a: _a_sub
                },
                replacements=replacements)

            # need to connect the distributed version back to the
            # original self, via a shallow_simplification() of
            # each of the ScalarMult terms resulting in the distribution
            for _i in range(len(distribution.rhs.operands.entries)):
                distribution = (distribution.inner_expr().rhs.operands[_i].
                                shallow_simplify())

            eq.update(distribution.derive_reversed())

        # Case (2) VecAdd(TensorProd, TensorProd, ..., TensorProd)
        elif all(isinstance(op, TensorProd) for op in self.operands):
            # if hasattr(the_factor, 'operands'):
            #     print("the_factor has operands: {}".format(the_factor.operands))
            #     the_factor_tuple = the_factor.operands.entries
            # else:
            #     print("the_factor does not have operands: {}".format(the_factor))
            #     the_factor_tuple = (the_factor,)
            if isinstance(the_factor, TensorProd):
                the_factor_tuple = the_factor.operands.entries
            else:
                the_factor_tuple = (the_factor, )
            # Setting the default_field here because the field
            # used manually in the association step somehow gets lost
            VecSpaces.default_field = field
            # look for the_factor in each TensorProd appearing in
            # the VecAdd operands, looking at the left vs. right
            # sides depending on the 'pull' direction specified
            _b = []  # to hold factors left behind
            for _i in range(expr.terms.num_entries()):
                # Notice we're not ready to deal with ExprRange
                # versions of Add operands here!
                # We are also implicitly assuming that each TensorProd
                # has at least two operands
                term = expr.terms[_i]
                if hasattr(term, 'operands'):
                    term_tuple = term.operands.entries
                else:
                    term_tuple = (term, )
                if pull == 'left':
                    # look for factor at left-most-side
                    if the_factor_tuple != term_tuple[0:len(the_factor_tuple)]:
                        raise ValueError(
                            "VecAdd.factorization() expecting the_factor "
                            "{0} to appear at the leftmost side of each "
                            "addend, but {0} does not appear at the "
                            "leftmost side of the addend {1}.".format(
                                the_factor, term))
                    else:
                        # we're OK, so save away the remainder of
                        # factors from the rhs of the term,
                        # and group any multi-term factor on the left
                        if len(term_tuple[len(the_factor_tuple):]) == 1:
                            _b.append(term_tuple[-1])
                        else:
                            _b.append(
                                TensorProd(
                                    *term_tuple[len(the_factor_tuple):]))
                            # then create an associated version of the
                            # expr to match the eventual thm instantiation
                            # ALSO NEED TO DO THIS FOR THE RIGHT CASE
                            expr = eq.update(
                                expr.inner_expr().operands[_i].association(
                                    len(the_factor_tuple),
                                    len(term_tuple) - len(the_factor_tuple),
                                    preserve_all=True))
                        # perhaps we actually don't need the assoc step?
                        # if len(the_factor_tuple) != 1:
                        #     expr = eq.update(expr.inner_expr().operands[_i].
                        #             association(0, len(the_factor_tuple),
                        #                     preserve_all=True))

                elif pull == 'right':
                    # look for factor at right-most-side
                    if the_factor_tuple != term_tuple[-(
                            len(the_factor_tuple)):]:
                        raise ValueError(
                            "VecAdd.factorization() expecting the_factor "
                            "{0} to appear at the rightmost side of each "
                            "addend, but {0} does not appear at the "
                            "rightmost side of the addend {1}.".format(
                                the_factor, term))
                    else:
                        # we're OK, so save away the remainder of
                        # factors from the lhs of the term,
                        # and group any multi-term factor on the right
                        if len(term_tuple[0:-(len(the_factor_tuple))]) == 1:
                            _b.append(term_tuple[0])
                        else:
                            _b.append(
                                TensorProd(
                                    *term_tuple[0:-(len(the_factor_tuple))]))
                            # then create an associated version of the
                            # expr to match the eventual thm instantiation
                            expr = eq.update(
                                expr.inner_expr().operands[_i].association(
                                    0,
                                    len(term_tuple) - len(the_factor_tuple),
                                    preserve_all=True))
                        # perhaps we actually don't need the assoc step?
                        # if len(the_factor_tuple) != 1:
                        #     expr = eq.update(expr.inner_expr().operands[_i].
                        #             association(
                        #                 len(term_tuple)-len(the_factor_tuple),
                        #                 len(the_factor_tuple),
                        #                 preserve_all=True))

                else:
                    raise ValueError(
                        "VecAdd.factorization() requires 'pull' argument "
                        "to be specified as either 'left' or 'right'.")

            # now ready to instantiate the TensorProd/VecAdd
            # theorem: tensor_prod_distribution_over_add
            # and derive it's reversed result
            from proveit.linear_algebra.tensors import (
                tensor_prod_distribution_over_add)
            from proveit import a, b, c, i, j, k, K, V
            from proveit.numbers import zero, one, num
            # useful to get ahead of time the num of operands
            # in the_factor and define the replacement
            # if hasattr(the_factor, 'operands'):
            #     num_factor_entries = num(the_factor.operands.num_entries())
            #     factor_entries = the_factor.operands.entries
            # else:
            #     num_factor_entries = one
            #     factor_entries = (the_factor,)
            # useful to get ahead of time the num of operands
            # in the_factor and define the replacement
            if isinstance(the_factor, TensorProd):
                num_factor_entries = num(the_factor.operands.num_entries())
                factor_entries = the_factor.operands.entries
            else:
                num_factor_entries = one
                factor_entries = (the_factor, )
            # call deduce_in_vec_space() on the original self
            # instead of the current expr, otherwise we can run into
            # compications due to the associated sub-terms
            vec_space_membership = self.operands[0].deduce_in_vec_space(
                field=field)
            _V_sub = vec_space_membership.domain
            _K_sub = VecSpaces.known_field(_V_sub)
            if pull == 'left':
                # num of operands in left the_factor
                _i_sub = num_factor_entries
                # num of operands in right factor
                _k_sub = zero
                # the actual factor operands
                _a_sub = factor_entries
                # the other side is empty
                _c_sub = ()
            elif pull == 'right':
                # left side is empty
                _i_sub = zero
                # right side has the factor
                _k_sub = num_factor_entries
                # left side is empty
                _a_sub = ()
                # right side has the factor
                _c_sub = factor_entries
            _j_sub = num(len(_b))
            _b_sub = ExprTuple(*_b)

            from proveit.linear_algebra.tensors import (
                tensor_prod_distribution_over_add)
            impl = tensor_prod_distribution_over_add.instantiate(
                {
                    V: _V_sub,
                    K: _K_sub,
                    i: _i_sub,
                    j: _j_sub,
                    k: _k_sub,
                    a: _a_sub,
                    b: _b_sub,
                    c: _c_sub
                },
                preserve_all=True)

            conseq = impl.derive_consequent()

            eq.update(conseq.derive_reversed())

        else:
            print("Not yet an identified case. Sorry!")

        return eq.relation
Ejemplo n.º 6
0
    def eliminate_common_factors(self, **defaults_config):
        '''
        Eliminate all factors in common between the divisor and the
        dividend.  For example, from (k a)|(k b), derive and return a|b.
        k must be a non-zero complex number.
        '''
        from . import common_factor_elimination
        from proveit.numbers import Mult, one
        if self.lhs == self.rhs:
            # From x | x return 1 | 1.  It's vacuous, but whatever.
            return Divides(one, one).prove()
        elif (isinstance(self.lhs, Mult) and isinstance(self.rhs, Mult)):

            # Handle the basic case in which the divisor and
            # the dividend are each the product of two factors and
            # the first of these is in common between them.
            if (self.lhs.operands.is_double()
                    and self.rhs.operands.is_double()):
                lhs1 = self.lhs.operands[0]
                lhs2 = self.lhs.operands[1]
                rhs1 = self.rhs.operands[0]
                rhs2 = self.rhs.operands[1]
                deduce_number_set(lhs1)

                if (lhs1 == rhs1 and InSet(lhs1, Complex).proven()
                        and NotEquals(lhs1, zero).proven()):
                    return common_factor_elimination.instantiate({
                        a: lhs2,
                        b: rhs2,
                        k: lhs1
                    })

            # Try to convert it to the basic case via factorization
            # and try again.
            rhs_factors = set(self.rhs.operands.entries)
            common_factors = [
                factor for factor in self.lhs.factors if factor in rhs_factors
            ]
            # Pull the common factors out to the front.
            if len(common_factors) == 0:
                return self.prove()  # No common factors to eliminate.
            lhs_factorization = self.lhs.factorization(common_factors,
                                                       pull='left',
                                                       group_factors=True,
                                                       group_remainder=True,
                                                       preserve_all=True)
            rhs_factorization = self.rhs.factorization(common_factors,
                                                       pull='left',
                                                       group_factors=True,
                                                       group_remainder=True,
                                                       preserve_all=True)
            # Prove this "divides" but the substitute factorized forms.
            divides_proof = self.prove()
            if lhs_factorization.lhs != lhs_factorization.rhs:
                divides_proof = lhs_factorization.sub_right_side_into(
                    divides_proof)
            if rhs_factorization.lhs != rhs_factorization.rhs:
                divides_proof = rhs_factorization.sub_right_side_into(
                    divides_proof)
            lhs1, lhs2 = lhs_factorization.rhs.operands
            rhs1, rhs2 = rhs_factorization.rhs.operands
            return common_factor_elimination.instantiate({
                a: lhs2,
                b: rhs2,
                k: lhs1
            })
        elif isinstance(self.lhs, Mult) and self.rhs in self.lhs.factors:
            # From (k z) | k return z | 1.  Why not?
            dividend = Mult(self.rhs, one)
            divides = Divides(self.lhs, dividend)
            divides_proof = divides.eliminate_common_factors()
            return divides_proof.inner_expr().lhs.dividend.one_elimination(1)
        elif isinstance(self.rhs, Mult) and self.lhs in self.rhs.factors:
            # From (k z) | k return z | 1.  Why not?
            divisor = Mult(self.lhs, one)
            divides = Divides(divisor, self.rhs)
            divides_proof = divides.eliminate_common_factors()
            return divides_proof.inner_expr().lhs.divisor.one_elimination(1)

        # There are no common factors.
        return self.prove()
Ejemplo n.º 7
0
from proveit import Etcetera
from proveit.logic import Forall, InSet, Equals, NotEquals, Implies
from proveit.numbers import Mult, Natural, NaturalPos, Integer, Real, RealPos, Complex, Add, Sub, Sum
from proveit.common import a, b, x, y, P, S, y_multi, v_etc, w_etc, x_etc, y_etc, z_etc, Py_etc
from proveit.numbers.common import zero, one, ComplexSansZero
from proveit import begin_theorems, end_theorems

begin_theorems(locals())

mult_assoc = Forall([x_etc, y_etc, z_etc],
                    Equals(Mult(x_etc, y_etc, z_etc),
                           Mult(x_etc, Mult(y_etc), z_etc)))
mult_assoc

mult_nat_closure = Forall((a, b), InSet(Mult(a, b), Natural), domain=Natural)
mult_nat_closure

mult_nat_pos_closure = Forall((a, b),
                              InSet(Mult(a, b), NaturalPos),
                              domain=NaturalPos)
mult_nat_pos_closure

mult_int_closure = Forall([x_etc], InSet(Mult(x_etc), Integer), domain=Integer)
mult_int_closure

mult_real_closure = Forall([x_etc], InSet(Mult(x_etc), Real), domain=Real)
mult_real_closure

mult_real_pos_closure = Forall([x_etc],
                               InSet(Mult(x_etc), RealPos),
                               domain=RealPos)
Ejemplo n.º 8
0
    def factorization(self,
                      the_factors,
                      pull="left",
                      group_factors=True,
                      group_remainder=True,
                      **defaults_config):
        '''
        Return the proven factorization (equality with the factored
        form) from pulling the factor(s) from this division to the 
        "left" or "right".  If there are multiple occurrences, the first
        occurrence is used.
        If group_factors is True, the factors are
        grouped together as a sub-product.
        The group_remainder parameter is not relevant here but kept
        for consistency with other factorization methods.

        Examples:

            [(a*b)/(c*d)].factorization((a/c))
            proves (a*b)/(c*d) = (a/c)*(b/d)
            [(a*b)/(c*d)].factorization((1/c))
            proves (a*b)/(c*d) = (1/c)*(a*b/d)
            [(a*b)/(c*d)].factorization(a, pull='right')
            proves (a*b)/(c*d) = (b/(c*d))*a
            [a/(c*d)].factorization(a, pull='right')
            proves a/(c*d) = (1/(c*d))*a
            [(a*b)/d].factorization((a/d), pull='right')
            proves (a*b)/d = b*(a/d)
        '''
        from proveit.numbers import one, Mult
        from . import mult_frac_left, mult_frac_right, prod_of_fracs
        expr = self
        eq = TransRelUpdater(expr)
        if the_factors == self:
            return eq.relation  # self = self
        if isinstance(the_factors, Div):
            the_factor_numer = the_factors.numerator
            the_factor_denom = the_factors.denominator
        else:
            the_factor_numer = the_factors
            the_factor_denom = one
        replacements = []
        # Factor out a fraction.
        if expr.denominator == the_factor_denom:
            # Factor (x/z) from (x*y)/z.
            # x or y may be 1.
            if the_factor_numer not in (one, expr.numerator):
                expr = eq.update(expr.inner_expr().numerator.factorization(
                    the_factors.numerator,
                    pull=pull,
                    group_factors=True,
                    group_remainder=True,
                    preserve_all=True))
            if pull == 'left':
                # factor (x*y)/z into (x/z)*y
                thm = mult_frac_left
                if the_factor_numer == one:
                    # factor y/z into (1/z)*y
                    _x = one
                    _y = expr.numerator
                    replacements.append(
                        Mult(_x, _y).one_elimination(0, preserve_all=True))
            else:
                # factor (x*y)/z into x*(y/z)
                thm = mult_frac_right
                if the_factor_numer == one:
                    # factor x/z into x*(1/z)
                    _x = expr.numerator
                    _y = one
                    replacements.append(
                        Mult(_x, _y).one_elimination(1, preserve_all=True))
            if the_factor_numer != one:
                assert expr.numerator.operands.num_entries() == 2
                _x = expr.numerator.operands.entries[0]
                _y = expr.numerator.operands.entries[1]
            _z = expr.denominator
            eq.update(
                thm.instantiate({
                    x: _x,
                    y: _y,
                    z: _z
                },
                                replacements=replacements))
        else:
            # Factor (x*y)/(z*w) into (x/z)*(y/w).
            thm = prod_of_fracs
            if the_factor_denom not in (one, expr.denominator):
                expr = eq.update(expr.inner_expr().denominator.factorization(
                    the_factor_denom,
                    pull=pull,
                    group_factors=True,
                    preserve_all=True))
                assert expr.denominator.operands.num_entries() == 2
                _z = expr.denominator.operands.entries[0]
                _w = expr.denominator.operands.entries[1]
            elif (pull == 'left') == (the_factor_denom == one):
                # Factor (x*y)/w into x*(y/w).
                _z = one
                _w = expr.denominator
                replacements.append(
                    Mult(_z, _w).one_elimination(0, preserve_all=True))
            else:
                # Factor (x*y)/z into (x/z)*y.
                _z = expr.denominator
                _w = one
                replacements.append(
                    Mult(_z, _w).one_elimination(1, preserve_all=True))
            # Factor the numerator parts unless there is a 1 numerator.
            if the_factor_numer not in (one, expr.numerator):
                expr = eq.update(expr.inner_expr().numerator.factorization(
                    the_factor_numer,
                    pull=pull,
                    group_factors=True,
                    group_remainder=True,
                    preserve_all=True))
                assert expr.numerator.operands.num_entries() == 2
                # Factor (x*y)/(z*w) into (x/z)*(y/w)
                _x = expr.numerator.operands.entries[0]
                _y = expr.numerator.operands.entries[1]
            elif (pull == 'left') == (the_factor_numer == one):
                # Factor y/(z*w) into (1/z)*(y/w)
                _x = one
                _y = expr.numerator
                replacements.append(
                    Mult(_x, _y).one_elimination(0, preserve_all=True))
            else:
                # Factor x/(y*z) into (x/y)*(1/z)
                _x = expr.numerator
                _y = one
                replacements.append(
                    Mult(_x, _y).one_elimination(1, preserve_all=True))
            # create POSSIBLE replacements for inadvertently generated
            # fractions of the form _x/1 (i.e. _z = 1)
            # or _y/1 (i.e. _w = 1):
            if _z == one:
                replacements.append(
                    frac(_x, _z).divide_by_one_elimination(preserve_all=True))
            if _w == one:
                replacements.append(
                    frac(_y, _w).divide_by_one_elimination(preserve_all=True))

            eq.update(
                thm.instantiate({
                    x: _x,
                    y: _y,
                    z: _z,
                    w: _w
                },
                                replacements=replacements,
                                preserve_expr=expr))

        return eq.relation
Ejemplo n.º 9
0
    def cancelation(self, term_to_cancel, **defaults_config):
        '''
        Deduce and return an equality between self and a form in which
        the given operand has been canceled on the numerator and
        denominator.  For example,
        [(a*b)/(b*c)].cancelation(b) would return
        (a*b)/(b*c) = a / c.
        Assumptions or previous work might be required to establish
        that the term_to_cancel is non-zero.
        '''
        from proveit.numbers import Mult, one
        expr = self
        eq = TransRelUpdater(expr)

        if self.numerator == self.denominator == term_to_cancel:
            # x/x = 1
            from . import frac_cancel_complete
            return frac_cancel_complete.instantiate({x: term_to_cancel})

        if term_to_cancel != self.numerator:
            # try to catch Exp objects here as well?
            # after all, Exp(term_to_cancel, n) has factors!
            if (not isinstance(self.numerator, Mult)
                    or term_to_cancel not in self.numerator.operands):
                raise ValueError("%s not in the numerator of %s" %
                                 (term_to_cancel, self))
            # Factor the term_to_cancel from the numerator to the left.
            expr = eq.update(expr.inner_expr().numerator.factorization(
                term_to_cancel,
                group_factors=True,
                group_remainder=True,
                preserve_all=True))
        if term_to_cancel != self.denominator:
            if (not isinstance(self.denominator, Mult)
                    or term_to_cancel not in self.denominator.operands):
                raise ValueError("%s not in the denominator of %s" %
                                 (term_to_cancel, self))
            # Factor the term_to_cancel from the denominator to the left.
            expr = eq.update(expr.inner_expr().denominator.factorization(
                term_to_cancel,
                group_factors=True,
                group_remainder=True,
                preserve_all=True))
        if expr.numerator == expr.denominator == term_to_cancel:
            # Perhaps it reduced to the trivial x/x = 1 case via
            # auto-simplification.
            expr = eq.update(expr.cancelation(term_to_cancel))
            return eq.relation
        else:
            # (x*y) / (x*z) = y/z with possible automatic reductions
            # via 1 eliminations.
            from . import frac_cancel_left
            replacements = list(defaults.replacements)
            if expr.numerator == term_to_cancel:
                numer_prod = Mult(term_to_cancel, one)
                _y = one
                replacements.append(
                    numer_prod.one_elimination(1,
                                               preserve_expr=term_to_cancel))
            else:
                _y = expr.numerator.operands[1]
            if expr.denominator == term_to_cancel:
                denom_prod = Mult(term_to_cancel, one)
                _z = one
                replacements.append(
                    denom_prod.one_elimination(1,
                                               preserve_expr=term_to_cancel))
            else:
                _z = expr.denominator.operands[1]
            expr = eq.update(
                frac_cancel_left.instantiate({
                    x: term_to_cancel,
                    y: _y,
                    z: _z
                },
                                             replacements=replacements,
                                             preserve_expr=expr))
            return eq.relation
Ejemplo n.º 10
0
    def factorization(self,
                      the_factors,
                      pull="left",
                      group_factors=True,
                      group_remainder=None,
                      **defaults_config):
        '''
        Return the proven factorization (equality with the factored
        form) from pulling the factor(s) from this summation to the 
        "left" or "right".
        If group_factors is True, the factors will be grouped together 
        as a sub-product.  group_remainder is not relevant kept for 
        compatibility with other factor methods.
        '''
        from proveit import ExprTuple, var_range, IndexedVar
        from proveit.numbers.multiplication import distribute_through_summation
        from proveit.numbers import Mult, one
        if not isinstance(the_factors, Expression):
            # If 'the_factors' is not an Expression, assume it is
            # an iterable and make it a Mult.
            the_factors = Mult(*the_factors)
        if not free_vars(the_factors).isdisjoint(self.instance_params):
            raise ValueError(
                'Cannot factor anything involving summation indices '
                'out of a summation')
        expr = self
        # for convenience updating our equation
        eq = TransRelUpdater(expr)

        # We may need to factor the summand within the summation
        summand_assumptions = defaults.assumptions + self.conditions.entries
        summand_factorization = self.summand.factorization(
            the_factors,
            pull,
            group_factors=group_factors,
            group_remainder=True,
            assumptions=summand_assumptions)
        if summand_factorization.lhs != summand_factorization.rhs:
            gen_summand_factorization = summand_factorization.generalize(
                self.instance_params, conditions=self.conditions)
            expr = eq.update(
                expr.instance_substitution(gen_summand_factorization,
                                           preserve_all=True))
        if not group_factors and isinstance(the_factors, Mult):
            factors = the_factors.factors
        else:
            factors = ExprTuple(the_factors)
        if pull == 'left':
            _a = factors
            _c = ExprTuple()
            summand_remainder = expr.summand.factors[-1]
        elif pull == 'right':
            _a = ExprTuple()
            _c = factors
            summand_remainder = expr.summand.factors[0]
        else:
            raise ValueError("'pull' must be 'left' or 'right', not %s" % pull)
        _b = self.instance_params
        _i = _a.num_elements()
        _j = _b.num_elements()
        _k = _c.num_elements()
        _f = Lambda(expr.instance_params, summand_remainder)
        _Q = Lambda(expr.instance_params, expr.condition)
        _impl = distribute_through_summation.instantiate(
            {
                i: _i,
                j: _j,
                k: _k,
                f: _f,
                Q: _Q,
                b: _b
            }, preserve_all=True)
        quantified_eq = _impl.derive_consequent(preserve_all=True)
        eq.update(quantified_eq.instantiate({a: _a, c: _c}, preserve_all=True))

        return eq.relation
Ejemplo n.º 11
0
def complex_polar_coordinates(expr,
                              *,
                              radius_must_be_nonneg=True,
                              nonneg_radius_preferred=True,
                              do_include_unit_length_reduction=True,
                              reductions=None):
    '''
    Given an expression, expr, of the complex number polar form,
        r * exp(i * theta),
    or something obviously equivalent to this, where r and theta are 
    Real (and r is preferably RealNonNeg) under the given assumptions, 
    return
        (r, theta)
    as a tuple pair. If defaults.automation=False, the r and theta must
    already be known to be RealNonNeg and Real respectively. If
    defaults.automation=True, we may attempt to prove these through 
    automation.
    
    If radius_must_be_nonneg and nonneg_radius_preferred are False, 
    we won't worry about ensuring that r is non-negative (so the result
    can be ambiguous).  If radius_must_be_nonneg is True, a ValueError
    will be raised if we can't convert to a form where r is known to be
    non-negative.
    
    If expr is not exactly in this complex number polar form and
    'reductions' is provided as a set, add to the 'reductions' set
    an equation that equates the exact form on the left with the
    original form on the right.  This may be useful to use as
    'reductions' in instantiations of theorems that employ the
    complex number polar form so it may perform proper reductions
    to the desired form.  For example, if expr=5 is provided,
    the added reduction will be
        5 * exp(i * 0) = 5.
    
    If do_include_unit_length_reduction is True,  we will included
    reductions so that it will reduce from the unit length
    form as well.  For example, if expr=1 is provided, the added
    reductions will be
        exp(i * 0) = 1
        1 * 1 = 1.
    This also works in a way that cascades when reducing from the
    general polar form:
        1 * exp(i * 0) = 1 * 1 = 1
    
    Raise ValueError if the expr is not obviously equivalent to a
    complex number polar form.

    Also see unit_length_complex_polar_angle.
    '''
    from . import complex_polar_negation, complex_polar_radius_negation
    from proveit.logic import InSet, Equals
    from proveit.numbers import deduce_in_number_set, deduce_number_set
    from proveit.numbers import zero, one, e, i, pi
    from proveit.numbers import Real, RealNonPos, RealNonNeg, Complex
    from proveit.numbers import Add, LessEq, Neg, Mult, Exp
    orig_expr = expr
    automation = defaults.automation
    simplify = defaults.auto_simplify
    if reductions is None: reductions = set()

    def add_reduction(reduction, _radius, _theta):
        '''
        Add the given reduction.  First check that its left and
        rights sides are as expected: the left should be the polar
        form and the right should be the original expression.
        '''
        polar_form = Mult(_radius, Exp(e, Mult(i, _theta)))
        assert (isinstance(reduction, Judgment)
                and isinstance(reduction.expr, Equals)
                and reduction.lhs == polar_form and reduction.rhs
                == orig_expr), ("Reduction, %s, not a judgement "
                                "for %s = %s" %
                                (reduction, polar_form, orig_expr))
        if do_include_unit_length_reduction and _radius == one:
            # As a unit length complex number, let's include the
            # reduction from the unit length form in case a unit length
            # formula is applied (cover the bases).
            # The 'automation' allowed here is negligible (assuming
            # we have already proven appropriate set membership by this
            # point).
            reductions.add(reduction.inner_expr().lhs.eliminate_one(
                0, automation=True))
            # But prepare for a multi-stage reduction:
            # 1 * exp[i * theta] = 1 * orig_expr = orig_expr
            reductions.add(
                Mult(one, orig_expr).one_elimination(0, automation=True))
        elif reduction.lhs != reduction.rhs:
            reductions.add(reduction)

    def raise_not_valid_form(extra_msg=None):
        if extra_msg is None: extra_msg = ""
        raise ValueError("%s not in a form that is obviously "
                         "reducible from an r * exp(i*theta) form. %s" %
                         (orig_expr, extra_msg))

    if (isinstance(expr, Exp)
            or (isinstance(expr, Neg) and isinstance(expr.operand, Exp))):
        # exp(i * theta) reduced from 1 * exp(i * theta).
        # or exp(i * (theta + pi)) reduced from -exp(i * theta).
        inner_reductions = set()
        _theta = unit_length_complex_polar_angle(expr,
                                                 reductions=inner_reductions)
        deduce_in_number_set(_theta, Complex)
        deduce_in_number_set(Mult(i, _theta), Complex)
        deduce_in_number_set(Exp(e, Mult(i, _theta)), Complex)
        _r = one
        expr = Mult(_r, Exp(e, Mult(i, _theta)))
        # reduction: 1*exp(i * theta) = exp(i * theta)
        reduction = expr.one_elimination(0, preserve_all=True)
        # reduction: 1*exp(i * theta) = orig_expr
        if len(inner_reductions) > 0:
            reduction = reduction.inner_expr().rhs.substitute(
                inner_reductions.pop().rhs, preserve_all=True)
        # Add the reduction and return the coordinates.
        add_reduction(reduction, _r, _theta)
        return (_r, _theta)
    elif isinstance(expr, Neg):
        # expr = -(r*exp(i*theta0)) = r*exp(i*(theta0 + pi))
        inner_reductions = set()
        # obtain the theta of the negated expression.
        _r, _theta0 = complex_polar_coordinates(
            expr.operand,
            radius_must_be_nonneg=radius_must_be_nonneg,
            nonneg_radius_preferred=nonneg_radius_preferred,
            reductions=inner_reductions)
        # theta = theta0 + pi
        _theta = Add(_theta0, pi)
        if defaults.auto_simplify:
            # simplify theta
            theta_simplification = _theta.simplification()
            inner_reductions.add(theta_simplification)
            _theta = theta_simplification.rhs
        deduce_in_number_set(_theta, Complex)
        deduce_in_number_set(Mult(i, _theta), Complex)
        deduce_in_number_set(Exp(e, Mult(i, _theta)), Complex)
        # reduction: r*exp(i*theta) = orig_expr [via -(r*exp(i*theta0))]
        reduction = complex_polar_negation.instantiate(
            {
                r: _r,
                theta: _theta0
            },
            replacements=inner_reductions,
            auto_simplify=False)
        # Add the reduction and return the coordinates.
        add_reduction(reduction, _r, _theta)
        return (_r, _theta)

    # Search for an exponentiation factor with base of 'e' and an
    # imaginary number in the exponent.
    complex_exp_factor_idx = None
    if isinstance(expr, Mult):
        i_factor_idx = None
        for idx, factor in enumerate(expr.factors):
            if isinstance(factor, Exp) and factor.base == e:
                # exp(x) type factor; check for imaginary number in
                # exponent.
                contains_imaginary_factor = False
                sub_expr = factor.exponent
                if isinstance(sub_expr, Neg):
                    sub_expr = sub_expr.operand
                if isinstance(sub_expr, Mult):
                    if i in sub_expr.operands.entries:
                        contains_imaginary_factor = True
                else:
                    contains_imaginary_factor = (sub_expr == i)
                if contains_imaginary_factor:
                    # Found imaginary number in an exponent.
                    if ((complex_exp_factor_idx is not None)
                            or (i_factor_idx is not None)):
                        # We already have an imaginary number in
                        # an exponent.  We can only have one.
                        raise_not_valid_form()
                    complex_exp_factor_idx = idx
                    deduce_in_number_set(sub_expr, Complex)
    if complex_exp_factor_idx is None:
        # No exp(i theta) factor.  Let's multiply by exp(i * 0).
        exp_i0 = Exp(e, Mult(i, zero))
        expr = Mult(expr, exp_i0)
        inner_reductions = set()
        _r, _theta = complex_polar_coordinates(
            expr,
            radius_must_be_nonneg=radius_must_be_nonneg,
            nonneg_radius_preferred=nonneg_radius_preferred,
            do_include_unit_length_reduction=False,
            reductions=inner_reductions)
        assert _theta == zero
        deduce_in_number_set(exp_i0, Complex)
        # reduction: r * exp(i * theta) = orig_expr * exp(i * 0)
        if len(inner_reductions) > 0:
            reduction = inner_reductions.pop()
        else:
            reduction = Equals(expr, expr).conclude_via_reflexivity()
        # reduction: r * exp(i * theta) = orig_expr
        reduction = reduction.inner_expr().rhs.simplify(
            preserve_expr=orig_expr)
        add_reduction(reduction, _r, _theta)
        return (_r, _theta)

    # expr in ... * exp(... * i * ...) * ... form
    # Obtain the theta from exp(... * i * ...) = exp[i * theta0].
    inner_reductions = set()
    _theta0 = unit_length_complex_polar_angle(
        expr.factors[complex_exp_factor_idx], reductions=inner_reductions)
    expr = Mult(*expr.factors.entries[:complex_exp_factor_idx],
                Exp(e, Mult(i, _theta0)),
                *expr.factors.entries[complex_exp_factor_idx + 1:])
    # reduction: ... * expr[i * theta0] * ... = orig_expr
    if len(inner_reductions) > 0:
        reduction = expr.inner_expr().operands[1].substitution(
            inner_reductions.pop().rhs, preserve_all=True)
    else:
        reduction = Equals(expr, expr).conclude_via_reflexivity()
    if not expr.operands.is_double() or complex_exp_factor_idx != 1:
        # Pull the exp(i*theta) type factor to the right.
        # reduction: r0 * exp(i * theta0) = orig_expr
        for factor in expr.factors:
            # Deduce the factors are complex numbers ahead of time
            # in case automation is disabled.
            deduce_in_number_set(factor, Complex)
        reduction = reduction.inner_expr().lhs.factor(complex_exp_factor_idx,
                                                      pull='right',
                                                      group_remainder=True,
                                                      preserve_all=True)
        expr = reduction.lhs
    # expr: r0 * exp(i * theta0)
    assert expr.operands.is_double() and isinstance(expr.operands[1], Exp)
    # Check that r0 is real and that we know it's relation with zero.
    _r0 = expr.operands[0]
    _r0_ns = deduce_number_set(_r0).domain
    if Real.includes(_r0_ns):
        InSet(_r0, Real).prove()
    else:
        raise_not_valid_form("%s not known to be real." % _r0)
    is_known_nonneg = RealNonNeg.includes(_r0_ns)
    is_known_nonpos = RealNonPos.includes(_r0_ns)
    if radius_must_be_nonneg:
        # We must know the relationship between r0 and 0 so we
        # can ensure r is non-negative.
        if not nonneg_radius_preferred:
            ValueError("nonneg_radius_preferred must be True if "
                       "radius_must_be_nonneg is True.")
        if not (is_known_nonneg or is_known_nonpos):
            raise_not_valid_form("Relation of %s to 0 is unknown and "
                                 "radius_must_be_nonneg is True." % _r0)
    if nonneg_radius_preferred and is_known_nonpos:
        # r0 <= 0, so we must negate it and add pi to the angle.
        inner_reductions = {reduction}
        # theta: theta + pi
        _theta = Add(_theta0, pi)
        if simplify:
            # simplify theta
            theta_simplification = _theta.simplification()
            inner_reductions.add(theta_simplification)
            _theta = theta_simplification.rhs
        # r: -r0
        _r = Neg(_r0)
        if simplify:
            # simplify radius
            radius_simplification = _r.simplification()
            inner_reductions.add(radius_simplification)
            _r = radius_simplification.rhs
        # reduction: r*exp(i*theta) = orig_expr [via r0*exp(i*theta0))]
        reduction = complex_polar_radius_negation.instantiate(
            {
                r: _r0,
                theta: _theta0
            },
            replacements=inner_reductions,
            auto_simplify=False)
    else:
        _r, _theta = _r0, _theta0
    # Add the reduction and return the coordinates.
    add_reduction(reduction, _r, _theta)
    return (_r, _theta)
Ejemplo n.º 12
0
def unit_length_complex_polar_angle(expr, *, reductions=None):
    '''
    Given an expression, expr, of the complex number polar form,
        exp(i * theta),
    or something obviously equivalent to this, where r is RealNonNeg 
    and theta is Real under the given assumptions, return theta.
    If defaults.automation=False, theta must already be known to be 
    Real. If defaults.automation=True, we may attempt to prove these 
    through automation.
    
    If expr is not exactly in this complex number polar form and
    'reductions' is provided as a set, add to the 'reductions' set
    an equation that equates the exact form on the left with the
    original form on the right.  This may be useful to use as
    'replacements' in instantiations of theorems that employ the
    complex number polar form so it may perform proper reductions
    to the desired form.  For example, if expr=1 is provided,
    the added reduction will be
        exp(i * 0) = 1
    
    Raise ValueError if the expr is not obviously equivalent to a
    complex number polar form.
    
    Also see complex_polar_coordinates.
    '''
    from proveit import ExprRange
    from proveit.logic import Equals, InSet
    from proveit.numbers import deduce_in_number_set, deduce_number_set
    from proveit.numbers import zero, one, e, i, pi
    from proveit.numbers import Add, Neg, Mult, Exp, Real, Complex
    from . import unit_length_complex_polar_negation
    if reductions is None: reductions = set()

    orig_expr = expr

    def raise_not_valid_form(extra_msg=None):
        if extra_msg is None: extra_msg = ""
        raise ValueError("%s not in a form that is obviously "
                         "reducible from an exp(i*theta) form. %s" %
                         (orig_expr, extra_msg))

    automation = defaults.automation
    simplify = defaults.auto_simplify

    def add_reduction(reduction, _theta):
        '''
        Add the given reduction.  First check that its left and
        rights sides are as expected: the left should be the polar
        form and the right should be the original expression.
        '''
        polar_form = Exp(e, Mult(i, _theta))
        assert (isinstance(reduction, Judgment)
                and isinstance(reduction.expr, Equals)
                and reduction.lhs == polar_form and reduction.rhs == orig_expr)
        if reduction.lhs != reduction.rhs:
            reductions.add(reduction)

    if expr == one:
        # expr = 1 = exp(i * 0)
        _theta = zero
        expr = Exp(e, Mult(i, _theta))
        # reduction: exp(i * 0) = 1
        reduction = expr.simplification()
        # Add the reduction and return theta.
        add_reduction(reduction, _theta)
        return _theta
    if isinstance(expr, Exp) and expr.base == e:
        if expr.exponent == i:
            # expr = exp(i) = exp(i * 1)
            _theta = one
            expr = Exp(e, Mult(i, one))
            # reduction: exp(i * 1) = exp(i)
            reduction = expr.inner_expr().exponent.one_elimination(1)
            # Add the reduction and return theta.
            add_reduction(reduction, _theta)
            return _theta
        if hasattr(expr.exponent, 'factorization'):
            if (isinstance(expr.exponent, Mult)
                    and expr.exponent.operands.is_double()
                    and expr.exponent.operands[0] == i):
                # Already in the proper form.  No reduction needed,
                # but we do need to check that theta is real.
                _theta = expr.exponent.factors[1]
                _theta_ns = deduce_number_set(_theta).domain
                if not Real.includes(_theta_ns):
                    raise_not_valid_form("%s known to be %s but not Real." %
                                         (_theta, _theta_ns))
                deduce_in_number_set(_theta, Real)
                return _theta
            try:
                # Factor i in the exponent, pulling to the left to
                # get into exp(i * theta) form.
                for operand in expr.exponent.operands:
                    # Deduce the operands are complex numbers ahead of
                    # time in case automation is disabled.
                    deduce_in_number_set(operand, Complex)
                factorization = expr.inner_expr().exponent.factorization(
                    i, pull='left', group_remainder=True, preserve_all=True)
                expr = factorization.rhs
                assert isinstance(expr.exponent, Mult)
                assert expr.exponent.factors.is_double()
                assert expr.exponent.factors[0] == i
                _theta = expr.exponent.factors[1]
                _theta_ns = deduce_number_set(_theta).domain
                if not Real.includes(_theta_ns):
                    raise_not_valid_form("%s known to be %s but not Real." %
                                         (_theta, _theta_ns))
                # reduction: exp(i * theta) = orig_expr
                reduction = factorization.derive_reversed()
                # Add the reduction and return theta.
                add_reduction(reduction, _theta)
                return _theta
            except ValueError:
                raise_not_valid_form()
    if isinstance(expr, Neg):
        # expr = -exp(i*theta0) = exp(i*(theta0 + pi)) = exp(i*theta)
        inner_reductions = set()
        # obtain the theta of the negated expression.
        _theta0 = unit_length_complex_polar_angle(expr.operand,
                                                  reductions=inner_reductions)
        # theta = theta0 + pi
        _theta = Add(_theta0, pi)
        if simplify:
            # simplify theta
            theta_simplification = _theta.simplification()
            inner_reductions.add(theta_simplification)
            _theta = theta_simplification.rhs
        # reduction: exp(i*theta) = orig_expr [via -exp(i*theta0)]
        reduction = unit_length_complex_polar_negation.instantiate(
            {theta: _theta0},
            replacements=inner_reductions,
            auto_simplify=False)
        # Add the reduction and return theta.
        add_reduction(reduction, _theta)
        return _theta

    raise_not_valid_form()
Ejemplo n.º 13
0
def exp_neg_2pi_i_on_two_pow_t(*exp_factors):
    from proveit.physics.quantum.QPE import _two_pow_t
    return exp(Neg(frac(Mult(*((two, pi, i) + exp_factors)), _two_pow_t)))
Ejemplo n.º 14
0
def exp2pi_i(*exp_factors):
    from proveit.numbers import Mult, pi, i
    return exp(Mult(*((two, pi, i) + exp_factors)))
Ejemplo n.º 15
0
            Abs(x), y), And(
                LessThanEquals(
                    Neg(y), x), LessThanEquals(
                        x, y))), domain=Real, conditions=[
                            GreaterThanEquals(
                                y, zero)])
abs_ineq

# transferred by wdc 3/11/2020
triangle_inequality = Forall([a, b], LessThanEquals(
    Abs(Add(a, b)), Add(Abs(a), Abs(b))), domain=Complex)
triangle_inequality

# transferred by wdc 3/11/2020
abs_prod = Forall(x_etc,
                  Equals(Abs(Mult(x_etc)),
                         Mult(Etcetera(Abs(x_multi)))),
                  domain=Complex)
abs_prod

# transferred by wdc 3/11/2020
abs_frac = Forall([a, b],
                  Equals(Abs(frac(a, b)), frac(Abs(a), Abs(b))),
                  domain=Complex)
abs_frac

# transferred by wdc 3/11/2020
mod_abs_scaled = Forall(
    (a, b, c), Equals(
        Mult(
            a, ModAbs(
Ejemplo n.º 16
0
                         Equals(Exp(a, zero), one),
                         domain=Complex,
                         conditions=[NotEquals(a, zero)])
exp_zero_eq_one

exponentiated_zero = Forall([x],
                            Equals(Exp(zero, x), zero),
                            domain=Complex,
                            conditions=[NotEquals(x, zero)])
exponentiated_zero

exponentiated_one = Forall([x], Equals(Exp(one, x), one), domain=Complex)
exponentiated_one

sum_in_exp = Forall([a, b, c],
                    Equals(Exp(a, Add(b, c)), Mult(Exp(a, b), Exp(a, c))),
                    domain=Complex,
                    conditions=[NotEquals(a, zero)])
sum_in_exp

sum_in_exp_rev = Forall([a, b, c],
                        Equals(Mult(Exp(a, b), Exp(a, c)), Exp(a, Add(b, c))),
                        domain=Complex,
                        conditions=[NotEquals(a, zero)])
sum_in_exp_rev

add_one_right_in_exp = Forall([a, b],
                              Equals(Exp(a, Add(b, one)), Mult(Exp(a, b), a)),
                              domain=Complex,
                              conditions=[NotEquals(a, zero)])
add_one_right_in_exp
Ejemplo n.º 17
0
distribute_neg_through_sum

distribute_neg_through_sum_rev = Forall([x_etc],
                                        Equals(Add(Etcetera(Neg(x_multi))),
                                               Neg(Add(x_etc))),
                                        domain=Complex)
distribute_neg_through_sum_rev

distribute_neg_through_subtract = Forall([x, y],
                                         Equals(Neg(Sub(x, y)), Add(Neg(x),
                                                                    y)),
                                         domain=Complex)
distribute_neg_through_subtract

neg_times_pos = Forall([x, y],
                       Equals(Mult(Neg(x), y), Neg(Mult(x, y))),
                       domain=Complex)
neg_times_pos

neg_times_pos_rev = Forall([x, y],
                           Equals(Neg(Mult(x, y)), Mult(Neg(x), y)),
                           domain=Complex)
neg_times_pos_rev

pos_times_neg = Forall([x, y],
                       Equals(Mult(x, Neg(y)), Neg(Mult(x, y))),
                       domain=Complex)
pos_times_neg

pos_times_neg_rev = Forall([x, y],
                           Equals(Neg(Mult(x, y)), Mult(x, Neg(y))),