Exemplo n.º 1
0
 def _tensorDictFromIterables(tensor, assumptions, requirements):
     '''
     From nested lists of Expressions, create a tensor dictionary, 
     mapping multi-dimensional indices to Expression elements.
     Yields location, element pairs that define a tensor.
     '''
     from proveit._core_ import KnownTruth        
     from .composite import _simplifiedCoord
     from proveit.number import zero, one, Add, subtract
     try:
         coord = zero
         for entry in tensor:
             # simplify the coordinate before moving on
             # (the simplified form will be equated with the original in the
             # sorting relations of the ExprArray).
             coord = _simplifiedCoord(coord, assumptions, requirements)
             if isinstance(entry, KnownTruth):
                 entry = entry.expr # extract the Expression from the KnownTruth
             if isinstance(entry, Expression):
                 loc = (coord,)
                 if isinstance(entry, Iter) and entry.ndims > 1:
                     loc += (zero,)*(entry.ndims-1) # append zeros for the extra dimensions
                 yield loc, entry # yield the location and element
                 if isinstance(entry, Iter):
                     # skip the coordinate ahead over the Embed expression
                     coord = Add(coord, subtract(entry.end_indices[0], entry.start_indices[0]), one)
                 else:
                     coord = Add(coord, one) # shift the coordinate ahead by one
             else:
                 for sub_loc, entry in ExprArray.TensorDictFromIterables(entry):
                     loc = (coord,)+sub_loc
                     yield loc, entry
     except TypeError:
         raise TypeError('An ExprArray must be a dictionary of indices to elements or a nested iterables of Expressions')
Exemplo n.º 2
0
 def join(self, secondSummation, assumptions=frozenset()):
     '''
     Join the "second summation" with "this" summation, deducing and returning
     the equivalence of these summations added with the joined summation.
     Both summation must be over Intervals.
     The relation between the first summation upper bound, UB1, and the second
     summation lower bound, LB2 must be explicitly either UB1 = LB2-1 or LB2=UB1+1.
     '''
     from theorems import sumSplitAfter, sumSplitBefore
     from proveit.number.common import one
     from proveit.number import Sub, Add
     if not isinstance(self.domain, Interval) or not isinstance(secondSummation.domain, Interval):
         raise Exception('Sum joining only implemented for Interval domains')
     if self.summand != secondSummation.summand:
         raise Exception('Sum joining only allowed when the summands are the same')            
     if self.domain.upperBound == Sub(secondSummation.domain.lowerBound, one):
         sumSplit = sumSplitBefore 
         splitIndex = secondSummation.domain.lowerBound
     elif secondSummation.domain.lowerBound == Add(self.domain.upperBound, one):
         sumSplit = sumSplitAfter
         splitIndex = self.domain.upperBound
     else:
         raise Exception('Sum joining only implemented when there is an explicit increment of one from the upper bound and the second summations lower bound')
     lowerBound, upperBound = self.domain.lowerBound, secondSummation.domain.upperBound
     deduceInIntegers(lowerBound, assumptions)
     deduceInIntegers(upperBound, assumptions)
     deduceInIntegers(splitIndex, assumptions)
     return sumSplit.specialize({Operation(f, self.instanceVars):self.summand}).specialize({a:lowerBound, b:splitIndex, c:upperBound, x:self.indices[0]}).deriveReversed()
Exemplo n.º 3
0
 def endCorner(self, tensor_entry_loc):
     '''
     Given an absolute tensor entry location,
     return the absolute location for the "end-corner" of
     the entry.  If the entry is an Iter, then this
     absolute end corner gives the range of the
     iteration inclusively.  Otherwise, the end-corner is
     simply tensor_entry_loc; that is, the start and the 
     end are the same for single-element entries.
     '''
     from proveit.number import one, Add, Subtract
     from .iteration import Iter
     entry = self[self.relEntryLoc(tensor_entry_loc)]
     if isinstance(entry, Iter):
         end_corner = []
         for axis, coord in enumerate(tensor_entry_loc):
             # Add (end-start)+1 of the Iter to get to the end
             # location of the entry along this axis.
             orig_end_coord = Add(
                 coord,
                 Subtract(entry.end_indices[axis],
                          entry.start_indices[axis]), one)
             end_corner.append(self.endCoordSimplifications[orig_end_coord]
                               )  # use the simplified version
         return end_corner  # absolute end-corner for the tensor entry
     return tensor_entry_loc  # single-element entry
Exemplo n.º 4
0
    def getElem(self, indices, base=0, assumptions=USE_DEFAULTS, requirements=None):
        '''
        Return the tensor element at the indices location, given
        as an Expression, using the given assumptions as needed
        to interpret the location expression.  Required
        truths, proven under the given assumptions, that 
        were used to make this interpretation will be
        appended to the given 'requirements' (if provided).
        '''
        from proveit.number import num, Less, Add, subtract
        from .iteration import Iter
        from .composite import _simplifiedCoord
        if len(indices) != self.ndims:
            raise ExprArrayError("The 'indices' has the wrong number of dimensions: %d instead of %d"%(len(indices), self.ndims))
        
        if requirements is None: requirements = [] # requirements won't be passed back in this case

        if base != 0: 
            # subtract off the base if it is not zero
            indices = [subtract(index, num(self.base)) for index in indices]
        tensor_loc = [_simplifiedCoord(index, assumptions, requirements) for index in indices]

        lower_indices = []
        upper_indices = []
        for coord, sorted_coords in zip(tensor_loc, self.sortedCoordLists):
            lower, upper = None, None
            try:
                lower, upper = Less.insert(sorted_coords, coord, assumptions=assumptions)
            except:
                raise ExprArrayError("Could not determine the 'indices' range within the tensor coordinates under the given assumptions")
            # The relationship to the lower and upper coordinate bounds are requirements for determining
            # the element being assessed.
            requirements.append(Less.sort((sorted_coords[lower], coord), reorder=False, assumptions=assumptions))
            requirements.append(Less.sort((coord, sorted_coords[upper]), reorder=False, assumptions=assumptions))
            lower_indices.append(lower)
            upper_indices.append(upper)
        
        if tuple(lower_indices) not in self.entryOrigins or tuple(upper_indices) not in self.entryOrigins:
            raise ExprArrayError("Tensor element could not be found at %s"%str(tensor_loc))
        rel_entry_origin = self.relEntryOrigins[lower_indices]
        if self.relEntryOrigins[upper_indices] != rel_entry_origin:
            raise ExprArrayError("Tensor element is ambiguous for %s under the given assumptions"%str(tensor_loc))
        
        entry = self[rel_entry_origin]
        if isinstance(entry, Iter):
            # indexing into an iteration
            entry_origin = self.tensorLoc(rel_entry_origin)
            iter_start_indices = entry.start_indices
            iter_loc = [Add(iter_start, subtract(coord, origin)) for iter_start, coord, origin in zip(iter_start_indices, tensor_loc, entry_origin)] 
            simplified_iter_loc = [_simplifiedCoord(coord, assumptions, requirements) for coord in iter_loc]
            return entry.getInstance(simplified_iter_loc, assumptions=assumptions, requirements=requirements)
        else:
            # just a single-element entry
            assert lower_indices==upper_indices, "A single-element entry should not have been determined if there was an ambiguous range for 'tensor_loc'"
            return entry
Exemplo n.º 5
0
    def _makeEntryOrigins(self):
        '''
        entryOrigins maps relative indices that contain tensor elements to
        the relative indices of the origin for the corresponding entry.
        Specifically, single-element entries map indices to themselves, but
        multi-element Iter entries map each of the encompassed 
        relative index location to the origin relative index location where
        that Iter entry is stored.
        
        Raise an ExprTensorError if there are overlapping entries.
        '''
        from .iteration import Iter
        from proveit.number import Add, Subtract, one

        # Create the entry_origins dictionary and check for invalid
        # overlapping entries while we are at it.
        rel_entry_origins = dict()
        rel_index_tensor = self.relIndexTensor
        for rel_entry_loc, entry in rel_index_tensor.items():
            if isinstance(entry, Iter):
                loc = self.tensorLoc(rel_entry_loc)

                # corner location at the end of the Embed block:
                end_corner = []
                for axis, coord in enumerate(loc):
                    end_coord = Add(
                        coord,
                        Subtract(entry.end_indices[axis],
                                 entry.start_indices[axis]), one)
                    end_corner.append(self.endCoordSimplifications[end_coord])

                # translate the end corner location to the corresponding relative indices
                rel_entry_end_corner = self.relEntryLoc(end_corner)

                # iterate over all of the relative indexed locations from the starting corner to
                # the ending corner of the Iter block, populating the entry_origins dictionary and
                # making sure none of the locations overlap with something else.
                for p in itertools.product(*[
                        range(start, end) for start, end in zip(
                            rel_entry_loc, rel_entry_end_corner)
                ]):
                    p = tuple(p)
                    if p in rel_entry_origins:
                        raise ExprTensorError(
                            "Overlapping blocks in the ExprTensor")
                    rel_entry_origins[p] = rel_entry_loc
            else:
                # single-element entry.  check for overlap and add to the entry_origins dictionary
                if rel_entry_loc in rel_entry_origins:
                    raise ExprTensorError(
                        "Overlapping blocks in the ExprTensor")
                rel_entry_origins[rel_entry_loc] = rel_entry_loc

        # Return the entry_origins dictionary that we generated.
        return rel_entry_origins
Exemplo n.º 6
0
 def __init__(self, operandA, operandB):
     r'''
     Sub one number from another
     '''
     from proveit.number import Add, isLiteralInt, num
     Operation.__init__(self, Subtract._operator_, (operandA, operandB))
     if all(isLiteralInt(operand) for operand in self.operands):
         # With literal integer operands, we can import useful theorems for evaluation.
         # From c - b, make the a+b which equals c.  This will import the theorems we need.
         Add(num(self.operands[0].asInt() - self.operands[1].asInt()),
             self.operands[1])
Exemplo n.º 7
0
 def distribute(self, assumptions=frozenset()):
     '''
     Given something of the form (a + b + ...) - (x + y + ...), deduce and return
     (a + b + ...) - (x + y + ...) = a + b + ... + (-x) + (-y) + ....
     Assumptions may be needed to deduce that the operands are in Complexes.        
     '''
     # first deduce: (a + b + ...) - (x + y + ...)  = (a + b + ...) + (-x) + (-y) + ...
     from proveit.number import Add
     eqn = Equation()
     if isinstance(self.operands[1], Add):
         from .theorems import distributeSubtraction
         deduceInComplexes(self.operands[0], assumptions)
         deduceInComplexes(self.operands[1].operands, assumptions)
         eqn.update(
             distributeSubtraction.specialize({
                 x:
                 self.operands[0],
                 yEtc:
                 self.operands[1].operands
             }).checked(assumptions))
     else:
         eqn.update(self.convertToAdd(assumptions))
     expr = eqn.eqExpr.rhs
     dummyVar = expr.safeDummyVar()
     # next try to simplify any of the negated terms
     negatedTerms = [term for term in expr.operands[1:]]
     for k, negatedTerm in enumerate(negatedTerms):
         try:
             negTermSimplification = negatedTerm.simplification(assumptions)
             eqn.update(
                 negTermSimplification.substitution(
                     Add(*(expr.terms[:k + 1] + [dummyVar] +
                           expr.terms[k + 2:])),
                     dummyVar)).checked(assumptions)
             expr = eqn.eqExpr.rhs
         except:
             pass  # skip over
     # ungroup the first part if it is a sum: (a + b + ...) + (-x) + (-y) + ... = a + b + ... + (-x) + (-y) + ...
     if isinstance(self.operands[0], Add):
         eqn.update(
             expr.applyTransitivity(expr.ungroup(0)).checked(assumptions))
     return eqn.eqExpr
Exemplo n.º 8
0
 def distribute(self, assumptions=frozenset()):
     '''
     Distribute negation through a sum.
     '''
     from .theorems import distributeNegThroughSum, distributeNegThroughSubtract
     from proveit.number import Add, Sub
     if isinstance(self.operand, Add):
         deduceInComplexes(self.operand.operands, assumptions)
         # distribute the negation over the sum
         eqn = Equation(
             distributeNegThroughSum.specialize(
                 {xEtc: self.operand.operands}))
         # try to simplify each term
         expr = eqn.eqExpr.rhs
         dummyVar = self.safeDummyVar()
         negatedTerms = [term for term in expr.operands]
         for k, negatedTerm in enumerate(negatedTerms):
             try:
                 negTermSimplification = negatedTerm.simplification(
                     assumptions)
                 eqn.update(
                     negTermSimplification.substitution(
                         Add(*(expr.terms[:k] + [dummyVar] +
                               expr.terms[k + 1:])),
                         dummyVar)).checked(assumptions)
                 expr = eqn.eqExpr.rhs
             except:
                 pass  # skip over
         return eqn.eqExpr.checked(assumptions)
     elif isinstance(self.operand, Sub):
         deduceInComplexes(self.operand.operands, assumptions)
         return distributeNegThroughSubtract.specialize({
             x:
             self.operand.operands[0],
             y:
             self.operand.operands[1]
         }).checked(assumptions)
     else:
         raise Exception(
             'Only negation distribution through a sum or subtract is implemented'
         )
Exemplo n.º 9
0
def test():
        substitution.specialize({fx:Not(x), x:a, y:b}, assumptions=[Equals(a, b)])
        expr = Equals(a, Add(b, Frac(c, d), Exp(c, d)))
        gRepl = Lambda.globalRepl(expr, d)
        d_eq_y = Equals(d, y)
        d_eq_y.substitution(gRepl, assumptions=[d_eq_y])
        d_eq_y.substitution(expr, assumptions=[d_eq_y])
        d_eq_y.substitution(expr, assumptions=[d_eq_y]).proof()
        innerExpr = expr.innerExpr()
        innerExpr = innerExpr.rhs
        innerExpr = innerExpr.operands[1]
        innerExpr = innerExpr.denominator
        d_eq_y.substitution(innerExpr, assumptions=[d_eq_y])
        d_eq_y.substitution(expr.innerExpr().rhs.operands[2].exponent, assumptions=[d_eq_y])
        d_eq_y.subRightSideInto(gRepl, assumptions=[d_eq_y,expr])
        d_eq_y.subRightSideInto(expr, assumptions=[d_eq_y,expr])
        y_eq_d = Equals(y, d)
        y_eq_d.subLeftSideInto(gRepl, assumptions=[y_eq_d,expr])
        y_eq_d.subLeftSideInto(expr, assumptions=[y_eq_d,expr])
        y_eq_d.subLeftSideInto(expr, assumptions=[y_eq_d,expr]).proof()
        
Exemplo n.º 10
0
    def substituted(self, exprMap, relabelMap=None, reservedVars=None, assumptions=USE_DEFAULTS, requirements=None):
        '''
        Returns this expression with the substitutions made 
        according to exprMap and/or relabeled according to relabelMap.
        Flattens nested tensors (or lists of lists) that arise from Embed substitutions.
        '''
        from .composite import _simplifiedCoord
        from .iteration import Iter
        from proveit.number import Add
        self._checkRelabelMap(relabelMap)
        if len(exprMap)>0 and (self in exprMap):
            return exprMap[self]._restrictionChecked(reservedVars)

        if requirements is None: requirements = [] # requirements won't be passed back in this case

        tensor = dict()
        for loc, element in self.items():
            subbed_loc = loc.substituted(exprMap, relabelMap, reservedVars, assumptions=assumptions, requirements=requirements)
            subbed_elem = element.substituted(exprMap, relabelMap, reservedVars, assumptions=assumptions, requirements=requirements)
            if isinstance(element, Iter) and isinstance(subbed_elem, ExprArray):
                # An iteration element became an ExprArray upon substitution,
                # so insert the elements directly into this outer ExprArray.
                for sub_loc, sub_elem in subbed_elem.items():
                    net_loc = [_simplifiedCoord(Add(main_coord, sub_coord), assumptions, requirements) for main_coord, sub_coord in zip(subbed_loc, sub_loc)]
                    tensor[net_loc] = subbed_elem
            else:
                tensor[subbed_loc] = subbed_elem
        expr_array = ExprArray(tensor, assumptions)
        expr_array_requirements = expr_array.getRequirements()
        for requirement in expr_array_requirements:
            # check that all ExprArray requirements satisfy restrictions
            requirement._restrictionChecked(reservedVars) # make sure requirements don't use reserved variable in a nested scope
        
        # pass back the new requirements that are different from the ExprArray requirements after making substitutions.
        old_requirements = {requirement.substituted(exprMap, relabelMap, reservedVars) for requirement in self.getRequirements()}
        new_requirements = [requirement for requirement in expr_array_requirements if requirement not in old_requirements]
            
        requirements += new_requirements
        
        return expr_array
Exemplo n.º 11
0
from proveit import Operation
from proveit.logic import Forall, InSet, NotInSet, NotEquals, And, Implies, Equals, Booleans
from proveit.number import Integers, Naturals, NaturalsPos, Interval, Reals, RealsPos, Complexes
from proveit.number import Add, GreaterThan, GreaterThanEquals, LessThan, LessThanEquals
from proveit.number import Len
from proveit.common import a, b, n, m, x, y, P, S, xMulti, xEtc, PxEtc
from proveit.number import zero, one, two, three, four, five, six, seven, eight, nine
from proveit.number.common import Pzero, Pm, P_mAddOne, Pn
from proveit import beginTheorems, endTheorems

beginTheorems(locals())

zeroInNats = InSet(zero, Naturals)

successiveNats = Forall(n, InSet(Add(n, one), Naturals), domain=Naturals)

inductionLemma = Forall(n, Forall(S, Implies(And(InSet(zero, S), Forall(x, InSet(Add(x,one), S), domain=S)), InSet(n, S))), domain=Naturals)

induction = Forall(P, Implies(And(Pzero, Forall(m, P_mAddOne, domain=Naturals, conditions=[Pm])), Forall(n, Pn, Naturals)))

zeroLenExprList = Equals(Len(), zero)

multiVarInduction = Forall(P, Implies(Forall((xMulti, y), Implies(PxEtc, Operation(P, [xEtc, y]))), Forall(xMulti, PxEtc)))

inIntsIsBool = Forall(a, InSet(InSet(a, Integers), Booleans))
inIntsIsBool

notInIntsIsBool = Forall(a, InSet(NotInSet(a, Integers), Booleans))
notInIntsIsBool

intsInReals = Forall(a, InSet(a, Reals), domain=Integers)
Exemplo n.º 12
0
    def substituted(self,
                    exprMap,
                    relabelMap=None,
                    reservedVars=None,
                    assumptions=USE_DEFAULTS,
                    requirements=None):
        '''
        Returns this expression with the substitutions made 
        according to exprMap and/or relabeled according to relabelMap.
        Attempt to automatically expand the iteration if any Indexed 
        sub-expressions substitute their variable for a composite
        (list or tensor).  Indexed should index variables that represent
        composites, but substituting the composite is a signal that
        an outer iteration should be expanded.  An exception is
        raised if this fails.
        '''
        from proveit.logic import Equals
        from proveit.number import Less, LessEq, Subtract, Add, one
        from composite import _simplifiedCoord
        from proveit._core_.expression.expr import _NoExpandedIteration

        assumptions = defaults.checkedAssumptions(assumptions)
        arg_sorting_assumptions = list(assumptions)

        new_requirements = []

        # Collect the iteration ranges from Indexed sub-Expressions
        # whose variable is being replaced with a Composite (list or tensor).
        # If there are not any, we won't expand the iteration at this point.
        # While we are at it, get all of the end points of the
        # ranges along each axis (as well as end points +/-1 that may be
        # needed if there are overlaps): 'special_points'.
        iter_ranges = set()
        iter_params = self.lambda_map.parameters
        special_points = [set() for _ in xrange(len(iter_params))]
        subbed_start = self.start_indices.substituted(exprMap, relabelMap,
                                                      reservedVars,
                                                      assumptions,
                                                      new_requirements)
        subbed_end = self.end_indices.substituted(exprMap, relabelMap,
                                                  reservedVars, assumptions,
                                                  new_requirements)
        try:
            for iter_range in self.lambda_map.body._expandingIterRanges(
                    iter_params, subbed_start, subbed_end, exprMap, relabelMap,
                    reservedVars, assumptions, new_requirements):
                iter_ranges.add(iter_range)
                for axis, (start, end) in enumerate(zip(*iter_range)):
                    special_points[axis].add(start)
                    special_points[axis].add(end)
                    # Preemptively include start-1 and end+1 in case it is required for splitting up overlapping ranges
                    # (we won't add simplification requirements until we find we actually need them.)
                    # Not necesary in the 1D case.
                    # Add the coordinate simplification to argument sorting assumtions -
                    # after all, this sorting does not go directly into the requirements.
                    start_minus_one = _simplifiedCoord(
                        Subtract(start, one),
                        assumptions=assumptions,
                        requirements=arg_sorting_assumptions)
                    end_plus_one = _simplifiedCoord(
                        Add(end, one),
                        assumptions=assumptions,
                        requirements=arg_sorting_assumptions)
                    special_points[axis].update(
                        {start_minus_one, end_plus_one})
                    # Add start-1<start and end<end+1 assumptions to ease argument sorting -
                    # after all, this sorting does not go directly into the requirements.
                    arg_sorting_assumptions.append(Less(
                        start_minus_one, start))
                    arg_sorting_assumptions.append(Less(end, end_plus_one))
                    arg_sorting_assumptions.append(
                        Equals(end, Subtract(end_plus_one, one)))
                    # Also add start<=end to ease the argument sorting requirement even though it
                    # may not strictly be true if an empty range is possible.  In such a case, we
                    # still want things sorted this way while we don't know if the range is empty or not
                    # and it does not go directly into the requirements.
                    arg_sorting_assumptions.append(LessEq(start, end))

            # There are Indexed sub-Expressions whose variable is
            # being replaced with a Composite, so let us
            # expand the iteration for all of the relevant
            # iteration ranges.
            # Sort the argument value ranges.

            arg_sorting_relations = []
            for axis in xrange(self.ndims):
                if len(special_points[axis]) == 0:
                    arg_sorting_relation = None
                else:
                    arg_sorting_relation = Less.sort(
                        special_points[axis],
                        assumptions=arg_sorting_assumptions)
                arg_sorting_relations.append(arg_sorting_relation)

            # Put the iteration ranges in terms of indices of the sorting relation operands
            # (relative indices w.r.t. the sorting relation order).
            rel_iter_ranges = set()
            for iter_range in iter_ranges:
                range_start, range_end = iter_range
                rel_range_start = tuple([
                    arg_sorting_relation.operands.index(arg)
                    for arg, arg_sorting_relation in zip(
                        range_start, arg_sorting_relations)
                ])
                rel_range_end = tuple([
                    arg_sorting_relation.operands.index(arg)
                    for arg, arg_sorting_relation in zip(
                        range_end, arg_sorting_relations)
                ])
                rel_iter_ranges.add((rel_range_start, rel_range_end))

            rel_iter_ranges = sorted(
                self._makeNonoverlappingRangeSet(rel_iter_ranges,
                                                 arg_sorting_relations,
                                                 assumptions,
                                                 new_requirements))

            # Generate the expanded list/tensor to replace the iterations.
            if self.ndims == 1: lst = []
            else: tensor = dict()
            for rel_iter_range in rel_iter_ranges:
                # get the starting location of this iteration range
                start_loc = tuple(
                    arg_sorting_relation.operands[idx]
                    for arg_sorting_relation, idx in zip(
                        arg_sorting_relations, rel_iter_range[0]))
                if rel_iter_range[0] == rel_iter_range[1]:
                    # single element entry (starting and ending location the same)
                    inner_expr_map = dict(exprMap)
                    inner_expr_map.update({
                        param: arg
                        for param, arg in zip(self.lambda_map.parameters,
                                              start_loc)
                    })
                    for param in self.lambda_map.parameters:
                        relabelMap.pop(param, None)
                    entry = self.lambda_map.body.substituted(
                        inner_expr_map, relabelMap, reservedVars, assumptions,
                        new_requirements)
                else:
                    # iterate over a sub-range
                    end_loc = tuple(
                        arg_sorting_relation.operands[idx]
                        for arg_sorting_relation, idx in zip(
                            arg_sorting_relations, rel_iter_range[1]))
                    # Shift the iteration parameter so that the iteration will have the same start-indices
                    # for this sub-range (like shifting a viewing window, moving the origin to the start of the sub-range).
                    # Include assumptions that the lambda_map parameters are in the shifted start_loc to end_loc range.
                    range_expr_map = dict(exprMap)
                    range_assumptions = list(assumptions)
                    for start_idx, param, range_start, range_end in zip(
                            self.start_indices, self.lambda_map.parameters,
                            start_loc, end_loc):
                        range_expr_map[param] = Add(
                            param, Subtract(range_start, start_idx))
                        range_assumptions += Less.sort((start_idx, param),
                                                       reorder=False,
                                                       assumptions=assumptions)
                        range_assumptions += Less.sort(
                            (param, Subtract(range_end, start_idx)),
                            reorder=False,
                            assumptions=assumptions)
                    range_lambda_body = self.lambda_map.body.substituted(
                        range_expr_map, relabelMap, reservedVars,
                        range_assumptions, new_requirements)
                    range_lambda_map = Lambda(self.lambda_map.parameters,
                                              range_lambda_body)
                    # Add the shifted sub-range iteration to the appropriate starting location.
                    end_indices = [
                        _simplifiedCoord(Subtract(range_end, start_idx),
                                         assumptions, new_requirements)
                        for start_idx, range_end in zip(
                            self.start_indices, end_loc)
                    ]
                    entry = Iter(range_lambda_map, self.start_indices,
                                 end_indices)
                if self.ndims == 1: lst.append(entry)
                else: tensor[start_loc] = entry

            if self.ndims == 1:
                subbed_self = compositeExpression(lst)
            else:
                subbed_self = compositeExpression(tensor)

        except _NoExpandedIteration:
            # No Indexed sub-Expressions whose variable is
            # replaced with a Composite, so let us not expand the
            # iteration.  Just do an ordinary substitution.
            subbed_map = self.lambda_map.substituted(exprMap, relabelMap,
                                                     reservedVars, assumptions,
                                                     new_requirements)
            subbed_self = Iter(subbed_map, subbed_start, subbed_end)

        for requirement in new_requirements:
            requirement._restrictionChecked(
                reservedVars
            )  # make sure requirements don't use reserved variable in a nested scope
        if requirements is not None:
            requirements += new_requirements  # append new requirements

        return subbed_self
Exemplo n.º 13
0
negatedPositiveIsNegative

negatedNegativeIsPositive = Forall(a,
                                   GreaterThan(Neg(a), zero),
                                   domain=Reals,
                                   conditions=[LessThan(a, zero)])
negatedNegativeIsPositive

negNotEqZero = Forall(a,
                      NotEquals(Neg(a), zero),
                      domain=Complexes,
                      conditions=[NotEquals(a, zero)])
negNotEqZero

distributeNegThroughSum = Forall([xEtc],
                                 Equals(Neg(Add(xEtc)),
                                        Add(Etcetera(Neg(xMulti)))),
                                 domain=Complexes)
distributeNegThroughSum

distributeNegThroughSumRev = Forall([xEtc],
                                    Equals(Add(Etcetera(Neg(xMulti))),
                                           Neg(Add(xEtc))),
                                    domain=Complexes)
distributeNegThroughSumRev

distributeNegThroughSubtract = Forall([x, y],
                                      Equals(Neg(Sub(x, y)), Add(Neg(x), y)),
                                      domain=Complexes)
distributeNegThroughSubtract
Exemplo n.º 14
0
greaterThanEqualsInBools

notEqualsIsLessThanOrGreaterThan = Forall((a, x),
                                          Or(Less(x, a), Greater(x, a)),
                                          domain=Reals,
                                          conditions=[NotEquals(x, a)])
notEqualsIsLessThanOrGreaterThan

shiftLessThanToLessThanEquals = Forall((a, b),
                                       LessEq(a, b),
                                       domain=Integers,
                                       conditions=[Less(Sub(a, one), b)])
shiftLessThanToLessThanEquals

lessThanEqualsAddRight = Forall([a, b, c],
                                LessEq(Add(a, c), Add(b, c)),
                                domain=Reals,
                                conditions=[LessEq(a, b)])
lessThanEqualsAddRight

lessThanEqualsAddLeft = Forall([a, b, c],
                               LessEq(Add(c, a), Add(c, b)),
                               domain=Reals,
                               conditions=[LessEq(a, b)])
lessThanEqualsAddLeft

lessThanEqualsSubtract = Forall([a, b, c],
                                LessEq(Sub(a, c), Sub(b, c)),
                                domain=Reals,
                                conditions=[LessEq(a, b)])
lessThanEqualsSubtract
Exemplo n.º 15
0
 def _makeNonoverlappingRangeSet(self, rel_iter_ranges,
                                 arg_sorting_relations, assumptions,
                                 requirements):
     '''
     Helper method for substituted.
     Check for overlapping relative iteration ranges, 
     breaking them up when found and returning the new
     set of ranges with no overlaps.
     '''
     from proveit.number import Add, Subtract, one
     from composite import _simplifiedCoord
     owning_range = dict(
     )  # map relative indices to the owning range; overlap occurs when ownership is contested.
     nonoverlapping_ranges = set()
     while len(rel_iter_ranges) > 0:
         rel_iter_range = rel_iter_ranges.pop()
         for p in itertools.product(
                 *
             [xrange(start, end) for start, end in zip(*rel_iter_range)]):
             p = tuple(p)
             # Check for contested ownership
             if p in owning_range and owning_range[
                     p] in nonoverlapping_ranges:
                 # Split along the first axis that differs,
                 # adding the split ranges back in.  If there are still
                 # distinct overlapping ranges after that split, there may be
                 # further splits along different axes.
                 range1, range2 = rel_iter_range, owning_range[p]
                 for axis, (start1, end1, start2,
                            end2) in enumerate(zip(*(range1 + range2))):
                     if start1 != start2 or end1 != end2:
                         # (re)assign range1 to have the earliest start.
                         if start1 > start2:
                             range1, range2 = range2, range1
                             start1, end1, start2, end2 = start2, end2, start1, end1
                         if start1 < start2:
                             # add the first range
                             first_range = (tuple(range1[0]),
                                            tuple(range1[1]))
                             abs_end = _simplifiedCoord(
                                 Subtract(
                                     arg_sorting_relations.operands[start2],
                                     one),
                                 assumptions=assumptions,
                                 requirements=requirements)
                             first_range[1][
                                 axis] = arg_sorting_relations.index(
                                     abs_end)
                             rel_iter_ranges.add(first_range)
                         mid_end = min(end1, end2)
                         if start2 < min(end1, end2):
                             # add the middle ranges (one from each of the originals
                             # where the overlap occurs.
                             for orig_range in (range1, range2):
                                 mid_range = (tuple(orig_range[0]),
                                              tuple(orig_range[1]))
                                 mid_range[1][axis] = end
                                 rel_iter_ranges.add(mid_range)
                         end = max(end1, end2)
                         if mid_end < end:
                             # add the last range
                             last_range = (tuple(range2[0]),
                                           tuple(range2[1]))
                             abs_start = _simplifiedCoord(
                                 Add(
                                     arg_sorting_relations.
                                     operands[mid_end], one),
                                 assumptions=assumptions,
                                 requirements=requirements)
                             first_range[0][
                                 axis] = arg_sorting_relations.index(
                                     abs_start)
                             rel_iter_ranges.add(last_range)
                         break
                 # remove/exclude the obsolete originals
                 nonoverlapping_ranges.discard(owning_range[p])
                 rel_iter_range = None
                 break
             else:
                 owning_range[p] = rel_iter_range
         if rel_iter_range is not None:
             nonoverlapping_ranges.add(rel_iter_range)
     return nonoverlapping_ranges
Exemplo n.º 16
0
    def entryRanges(self, base, start_index, end_index, assumptions,
                    requirements):
        '''
        For each entry of the list that is fully or partially contained in the window defined
        via start_indices and end_indices (as Expressions that can be provably sorted
        against list indices), yield the start and end of the intersection of the
        entry range and the window.
        '''
        from proveit.number import one, num, Add, Subtract, Less
        from proveit.logic import Equals
        from iteration import Iter
        from proveit import ProofFailure

        if requirements is None:
            requirements = []  # requirements won't be passed back in this case

        index = num(base)
        started = False
        prev_end = None

        try:
            start_end_relation = Less.sort([start_index, end_index
                                            ]).prove(assumptions=assumptions)
            if start_end_relation.operands[0] != start_index:
                # end comes before start: the range is empty.  This is the vacuous case.
                requirements.append(start_end_relation)
                return
                yield
        except:
            # Unable to prove that the end comes before the start, so assume
            # this will be a finite iteration (if not, the user can decide
            # how long to wait before they realize they are missing something).
            pass

        # Iterate over the entries and track the true element index,
        # including ranges of iterations (Iter objects).
        for i, entry in enumerate(self):
            if not started:
                # We have not yet encounted an entry within the desired window,
                # see if this entry is in the desired window.
                if index == start_index:
                    started = True  # Now we've started
                else:
                    try:
                        start_relation = Less.sort([start_index, index],
                                                   reorder=False,
                                                   assumptions=assumptions)
                        requirements.append(start_relation)
                        if start_relation.operator == Less._operator_ and prev_end is not None:
                            # The start of the window must have occurred before this entry,
                            # and there was a previous entry:
                            yield (start_index, prev_end
                                   )  # Do the range for the previous entry.
                        started = True  # Now we've started
                    except ProofFailure:
                        pass  # We have not started yet.

            # Obtain the ending index of the entry (entry_end) and the next_index
            # (entry_end+1).
            entry_end = index  # unless it is an Iter:
            if isinstance(entry, Iter):
                entry_span = Subtract(entry.end_index, entry.start_index)
                entry_end = _simplifiedCoord(Add(index, entry_span),
                                             assumptions, requirements)

            arrived_at_end = False
            if index == end_index:
                arrived_at_end = True
            else:
                try:
                    index_eq_end = Equals(end_index,
                                          index).prove(assumptions=assumptions,
                                                       automation=False)
                    requirements.append(index_eq_end)
                    arrived_at_end == True
                except ProofFailure:
                    next_index = _simplifiedCoord(Add(entry_end, one),
                                                  assumptions, requirements)
                    """
                    # TO KEEP THINGS SIMPLE, LET'S INSIST THAT THE INDEX MUST MATCH THE END EXACTLY TO STOP
                    # (NOT GOING BEYOND WITHOUT MATCHING).
                    # The exception is when the range is empty which we test at the beginning.
                                                       
                    # See if this entry takes us to the end of the window or beyond.
                    try:
                        print next_index, end_index
                        Less.sort([next_index, end_index], reorder=False, assumptions=assumptions)
                    except ProofFailure:
                        arrived_at_end = True # we have presumably encountered the end
                        if entry_end != end_index:
                            # we require a proven relation that we are at the end
                            end_relation = Less.sort([end_index, next_index], reorder=False, assumptions=assumptions)
                            requirements.append(end_relation)
                    """

            if arrived_at_end:
                if started:
                    # Yield from the start of the entry to the end of the window:
                    yield (index, end_index)
                    break
                else:
                    # The full window is within this entry.
                    start_relation = Less.sort([index, start_index],
                                               reorder=False,
                                               assumptions=assumptions)
                    requirements.append(start_relation)
                    yield (
                        start_index, end_index
                    )  # Yield the full window that is within a single entry.
                    break
            elif started:
                # We have encountered the start but not the end.
                yield (index, entry_end)  # Yield the full range of the entry.

            index = next_index  # Move on to the next entry.
            prev_end = entry_end

        if not arrived_at_end:
            raise IndexError("ExprList index out of range")
Exemplo n.º 17
0
squarePosEq

expNotEqZero = Forall([a, b], NotEquals(Exp(a,b), zero), domain=Complexes, conditions=[NotEquals(a, zero)])
expNotEqZero

expZeroEqOne = Forall([a], Equals(Exp(a, zero), one), domain=Complexes, conditions=[NotEquals(a, zero)])
expZeroEqOne

exponentiatedZero = Forall([x], Equals(Exp(zero, x), zero), domain=Complexes, conditions=[NotEquals(x, zero)])
exponentiatedZero

exponentiatedOne = Forall([x], Equals(Exp(one, x), one), domain=Complexes)
exponentiatedOne

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

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

addOneRightInExp = Forall([a,b],
                Equals(Exp(a,Add(b,one)),
                       Mult(Exp(a,b),a)),
                domain = Complexes, conditions=[NotEquals(a, zero)])
addOneRightInExp
Exemplo n.º 18
0
    def __init__(self,
                 tensor,
                 shape=None,
                 styles=None,
                 assumptions=USE_DEFAULTS,
                 requirements=tuple()):
        '''
        Create an ExprTensor either with a simple, dense tensor (list of lists ... of lists) or
        with a dictionary mapping coordinates (as tuples of expressions that represent integers) 
        to expr elements or Blocks.
        Providing starting and/or ending location(s) can extend the bounds of the tensor beyond
        the elements that are supplied.
        '''
        from .composite import _simplifiedCoord
        from proveit._core_ import KnownTruth
        from proveit.number import Less, Greater, zero, one, num, Add, Subtract

        assumptions = defaults.checkedAssumptions(assumptions)
        requirements = []
        if not isinstance(tensor, dict):
            tensor = {
                loc: element
                for loc, element in ExprTensor._tensorDictFromIterables(
                    tensor, assumptions, requirements)
            }

        # Map direct compositions for the end-coordinate of Iter elements
        # to their simplified forms.
        self.endCoordSimplifications = dict()

        # generate the set of distinct coordinates for each dimension
        coord_sets = None  # simplified versions
        full_tensor = dict()
        ndims = None
        if shape is not None:
            shape = ExprTensor.locAsExprs(shape)
            ndims = len(shape)
        for loc, element in tensor.items():
            if isinstance(element, KnownTruth):
                element = element.expr  # extract the Expression from the KnownTruth
            ndims = len(loc)
            if coord_sets is None:
                coord_sets = [set() for _ in range(ndims)]
            elif len(coord_sets) != ndims:
                if shape is not None:
                    raise ValueError(
                        "length of 'shape' is inconsistent with number of dimensions for ExprTensor locations"
                    )
                else:
                    raise ValueError(
                        "inconsistent number of dimensions for locations of the ExprTensor"
                    )
            for axis, coord in enumerate(list(loc)):
                if isinstance(coord, int):
                    coord = num(
                        coord)  # convert from Python int to an Expression
                    loc[axis] = coord
                coord_sets[axis].add(coord)
                if isinstance(element, Iter):
                    # Add (end-start)+1 of the Iter to get to the end
                    # location of the entry along this axis.
                    orig_end_coord = Add(
                        coord,
                        Subtract(element.end_indices[axis],
                                 element.start_indices[axis]), one)
                    end_coord = _simplifiedCoord(orig_end_coord, assumptions,
                                                 requirements)
                    self.endCoordSimplifications[orig_end_coord] = end_coord
                    coord_sets[axis].add(end_coord)
            full_tensor[tuple(loc)] = element

        if ndims is None:
            raise ExprTensorError("Empty ExprTensor is not allowed")
        if ndims <= 1:
            raise ExprTensorError(
                "ExprTensor must be 2 or more dimensions (use an ExprList for something 1-dimensional"
            )

        # in each dimension, coord_indices will be a dictionary
        # that maps each tensor location coordinate to its relative entry index.
        coord_rel_indices = []
        self.sortedCoordLists = []
        self.coordDiffRelationLists = []
        for axis in range(ndims):  # for each axis
            # KnownTruth sorting relation for the simplified coordinates used along this axis
            # (something with a form like a < b <= c = d <= e, that sorts the tensor location coordinates):
            coord_sorting_relation = Less.sort(coord_sets[axis],
                                               assumptions=assumptions)
            sorted_coords = list(coord_sorting_relation.operands)

            if shape is None:
                # Since nothing was explicitly specified, the shape is dictacted by extending
                # one beyond the last coordinate entry.
                sorted_coords.append(Add(sorted_coords[-1], one))
            else:
                sorted_coords.append(
                    shape[axis]
                )  # append the coordinate for the explicitly specified shape
            if sorted_coords[0] != zero:
                sorted_coords.insert(
                    0, zero
                )  # make sure the first of the sorted coordinates is zero.

            self.sortedCoordLists.append(ExprList(sorted_coords))

            # Add in coordinate expressions that explicitly indicate the difference between coordinates.
            # These may be used in generating the latex form of the ExprTensor.
            diff_relations = []
            for c1, c2 in zip(sorted_coords[:-1], sorted_coords[1:]):
                diff = _simplifiedCoord(Subtract(c2, c1), assumptions,
                                        requirements)
                # get the relationship between the difference of successive coordinate and zero.
                diff_relation = Greater.sort([zero, diff],
                                             assumptions=assumptions)
                if isinstance(diff_relation, Greater):
                    if c2 == sorted_coords[-1] and shape is not None:
                        raise ExprTensorError(
                            "Coordinates extend beyond the specified shape in axis %d: %s after %s"
                            % (axis, str(coord_sorting_relation.operands[-1]),
                               str(shape[axis])))
                    assert tuple(diff_relation.operands) == (
                        diff, zero), 'Inconsistent Less.sort results'
                    # diff > 0, let's compare it with one now
                    diff_relation = Greater.sort([one, diff],
                                                 assumptions=assumptions)
                requirements.append(diff_relation)
                diff_relations.append(diff_relation)
            self.coordDiffRelationLists.append(ExprList(diff_relations))

            # map each coordinate expression to its index into the sorting_relation operands
            coord_rel_indices.append(
                {coord: k
                 for k, coord in enumerate(sorted_coords)})

        # convert from the full tensor with arbitrary expression coordinates to coordinates that are
        # mapped according to sorted relation enumerations.
        rel_index_tensor = dict()
        for loc, element in full_tensor.items():
            rel_index_loc = (
                rel_index_map[coord]
                for coord, rel_index_map in zip(loc, coord_rel_indices))
            rel_index_tensor[rel_index_loc] = element

        sorted_keys = sorted(rel_index_tensor.keys())
        Expression.__init__(self, [
            'ExprTensor',
            str(ndims), ';'.join(str(key) for key in sorted_keys)
        ],
                            self.sortedCoordLists +
                            self.coordDiffRelationLists +
                            [rel_index_tensor[key] for key in sorted_keys],
                            styles=styles,
                            requirements=requirements)
        self.ndims = ndims
        self.relIndexTensor = rel_index_tensor

        # entryOrigins maps relative indices that contain tensor elements to
        # the relative indices of the origin for the corresponding entry.
        # Specifically, single-element entries map indices to themselves, but
        # multi-element Iter entries map each of the encompassed
        # relative index location to the origin relative index location where
        # that Iter entry is stored.
        self.relEntryOrigins = self._makeEntryOrigins()

        # the last coordinates of the sorted coordinates along each eaxis define the shape:
        self.shape = ExprList(
            [sorted_coords[-1] for sorted_coords in self.sortedCoordLists])
Exemplo n.º 19
0
from proveit.logic import Forall, InSet, Equals
from proveit.number import Integers, Naturals, NaturalsPos, Reals, RealsPos, RealsNeg, Complexes
from proveit.number import Add, GreaterThan, LessThan
from proveit.common import a, b, x, aEtc, cEtc, xEtc, yEtc, zEtc, vEtc, wEtc
from proveit.number.common import zero
from proveit import beginTheorems, endTheorems

beginTheorems(locals())

addIntClosure = Forall([xEtc], InSet(Add(xEtc),Integers), domain = Integers)
addIntClosure

addNatClosure = Forall((a, b), InSet(Add(a, b), Naturals), domain=Naturals)
addNatClosure

addRealClosure = Forall([xEtc], InSet(Add(xEtc),Reals), domain=Reals)
addRealClosure

addComplexClosure = Forall([xEtc], InSet(Add(xEtc),Complexes), domain = Complexes)
addComplexClosure

addNatPosClosure = Forall((aEtc, b, cEtc), InSet(Add(aEtc, b, cEtc), NaturalsPos), domain=Naturals, conditions=[GreaterThan(b, zero)])
addNatPosClosure

addZero = Forall(x, Equals(Add(zero, x), x), domain=Complexes)
addZero

addComm = Forall([vEtc,wEtc,xEtc,yEtc,zEtc],
                 Equals(
                        Add(vEtc,wEtc,xEtc,yEtc,zEtc),
                        Add(vEtc,yEtc,xEtc,wEtc,zEtc)
Exemplo n.º 20
0
divideNotEqZero

fractionNotEqZero = Forall([a, b],
                           NotEquals(Fraction(a, b), zero),
                           domain=ComplexesSansZero)
fractionNotEqZero

fracZeroNumer = Forall(x, Equals(Fraction(zero, x), zero), domain=Complexes)
fracZeroNumer

fracOneDenom = Forall(x, Equals(Fraction(x, one), x), domain=Complexes)
fracOneDenom

distributeFractionThroughSum = Forall([xEtc, y],
                                      Equals(
                                          Fraction(Add(xEtc), y),
                                          Add(Etcetera(Fraction(xMulti, y)))),
                                      domain=Complexes,
                                      conditions=[NotEquals(y, zero)])
distributeFractionThroughSum

distributeFractionThroughSumRev = Forall([xEtc, y],
                                         Equals(
                                             Add(Etcetera(Fraction(xMulti,
                                                                   y))),
                                             Fraction(Add(xEtc), y)),
                                         domain=Complexes,
                                         conditions=[NotEquals(y, zero)])
distributeFractionThroughSumRev

distributeFractionThroughSubtract = Forall([x, y, z],
Exemplo n.º 21
0
                      Equals(Exp(a, zero), one),
                      domain=Complexes,
                      conditions=[NotEquals(a, zero)])
expZeroEqOne

exponentiatedZero = Forall([x],
                           Equals(Exp(zero, x), zero),
                           domain=Complexes,
                           conditions=[NotEquals(x, zero)])
exponentiatedZero

exponentiatedOne = Forall([x], Equals(Exp(one, x), one), domain=Complexes)
exponentiatedOne

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

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

addOneRightInExp = Forall([a, b],
                          Equals(Exp(a, Add(b, one)), Mult(Exp(a, b), a)),
                          domain=Complexes,
                          conditions=[NotEquals(a, zero)])
addOneRightInExp
Exemplo n.º 22
0
    def merger(self, assumptions=USE_DEFAULTS):
        '''
        If this is an tuple of expressions that can be directly merged 
        together into a single ExprRange, return this proven 
        equivalence.  For example,
        {j \in Naturals, k-(j+1) \in Naturals} 
        |- (x_1, .., x_j, x_{j+1}, x_{j+2}, ..., x_k) = (x_1, ..., x_k)
        '''
        from proveit._core_.expression.lambda_expr import Lambda
        from .expr_range import ExprRange
        from proveit.relation import TransRelUpdater
        from proveit.core_expr_types.tuples._theorems_ import (
            merge, merge_front, merge_back, merge_extension, merge_pair,
            merge_series)
        from proveit._common_ import f, i, j, k, l, x
        from proveit.number import Add, one

        # A convenience to allow successive update to the equation via
        # transitivities (starting with self=self).
        eq = TransRelUpdater(self, assumptions)

        # Determine the position of the first ExprRange item and get the
        # lambda map.
        first_range_pos = len(self)
        lambda_map = None
        for _k, item in enumerate(self):
            if isinstance(item, ExprRange):
                lambda_map = Lambda(item.lambda_map.parameter,
                                    item.lambda_map.body)
                first_range_pos = _k
                break

        if 1 < first_range_pos:
            if lambda_map is None:
                raise NotImplementedError("Means of extracting a lambda "
                                          "map has not been implemented")
                pass  # need the lambda map
            # Collapse singular items at the beginning.
            front_singles = ExprTuple(eq.expr[:first_range_pos])
            i_sub = lambda_map.extractArgument(front_singles[0])
            j_sub = lambda_map.extractArgument(front_singles[-1])
            if len(front_singles) == 2:
                # Merge a pair of singular items.
                front_merger = merge_pair.specialize(
                    {
                        f: lambda_map,
                        i: i_sub,
                        j: j_sub
                    },
                    assumptions=assumptions)
            else:
                # Merge a series of singular items in one shot.
                front_merger = merge_series.specialize(
                    {
                        f: lambda_map,
                        x: front_singles,
                        i: i_sub,
                        j: j_sub
                    },
                    assumptions=assumptions)
            eq.update(
                front_merger.substitution(self.innerExpr()[:first_range_pos],
                                          assumptions=assumptions))

        if len(eq.expr) == 1:
            # We have accomplished a merger down to one item.
            return eq.relation

        if len(eq.expr) == 2:
            # Merge a pair.
            if isinstance(eq.expr[0], ExprRange):
                if isinstance(eq.expr[1], ExprRange):
                    # Merge a pair of ExprRanges.
                    item = eq.expr[1]
                    other_lambda_map = Lambda(item.lambda_map.parameter,
                                              item.lambda_map.body)
                    if other_lambda_map != lambda_map:
                        raise ExprTupleError(
                            "Cannot merge together ExprRanges "
                            "with different lambda maps: %s vs %s" %
                            (lambda_map, other_lambda_map))
                    _i, _j = eq.expr[0].start_index, eq.expr[0].end_index
                    _k, _l = eq.expr[1].start_index, eq.expr[1].end_index
                    merger = \
                        merge.specialize({f:lambda_map, i:_i, j:_j, k:_k, l:_l},
                                         assumptions=assumptions)
                else:
                    # Merge an ExprRange and a singular item.
                    _i, _j = eq.expr[0].start_index, eq.expr[0].end_index
                    _k = lambda_map.extractArgument(eq.expr[1])
                    if _k == Add(_j, one):
                        merger = merge_extension.specialize(
                            {
                                f: lambda_map,
                                i: _i,
                                j: _j
                            },
                            assumptions=assumptions)
                    else:
                        merger = merge_back.specialize(
                            {
                                f: lambda_map,
                                i: _i,
                                j: _j,
                                k: _k
                            },
                            assumptions=assumptions)
            else:
                # Merge a singular item and ExprRange.
                iSub = lambda_map.extractArgument(eq.expr[0])
                jSub, kSub = eq.expr[1].start_index, eq.expr[1].end_index
                merger = \
                    merge_front.specialize({f:lambda_map, i:iSub, j:jSub,
                                            k:kSub}, assumptions=assumptions)
            eq.update(merger)
            return eq.relation

        while len(eq.expr) > 1:
            front_merger = ExprTuple(*eq.expr[:2]).merger(assumptions)
            eq.update(
                front_merger.substitution(eq.expr.innerExpr(assumptions)[:2],
                                          assumptions=assumptions))
        return eq.relation
Exemplo n.º 23
0
multZero = Forall(x, Equals(Mult(zero, x), zero), domain=Complexes)
multZero

multComm = Forall([vEtc, wEtc, xEtc, yEtc, zEtc],
                  Equals(Mult(vEtc, wEtc, xEtc, yEtc, zEtc),
                         Mult(vEtc, yEtc, xEtc, wEtc, zEtc)),
                  domain=Complexes)
multComm

multAssocRev = Forall([xEtc, yEtc, zEtc],
                      Equals(Mult(xEtc, Mult(yEtc), zEtc),
                             Mult(xEtc, yEtc, zEtc)))
multAssocRev

distributeThroughSum = Forall([xEtc, yEtc, zEtc],
                              Equals(Mult(xEtc, Add(yEtc), zEtc),
                                     Add(Etcetera(Mult(xEtc, yMulti, zEtc)))),
                              domain=Complexes)
distributeThroughSum

distributeThroughSumRev = Forall([xEtc, yEtc, zEtc],
                                 Equals(
                                     Add(Etcetera(Mult(xEtc, yMulti, zEtc))),
                                     Mult(xEtc, Add(yEtc), zEtc)),
                                 domain=Complexes)
distributeThroughSumRev

distributeThroughSubtract = Forall([wEtc, x, y, zEtc],
                                   Equals(
                                       Mult(wEtc, Sub(x, y), zEtc),
                                       Sub(Mult(wEtc, x, zEtc),
Exemplo n.º 24
0
summationComplexClosure = Forall([P, S],
                                 Implies(
                                     Forall(xMulti,
                                            InSet(PxEtc, Complexes),
                                            domain=S),
                                     InSet(Sum(xMulti, PxEtc, domain=S),
                                           Complexes)))
summationComplexClosure

sumSplitAfter = Forall(
    f,
    Forall([a, b, c],
           Equals(
               Sum(x, fx, Interval(a, c)),
               Add(Sum(x, fx, Interval(a, b)),
                   Sum(x, fx, Interval(Add(b, one), c)))),
           domain=Integers,
           conditions=[LessThanEquals(a, b),
                       LessThan(b, c)]))
sumSplitAfter

sumSplitBefore = Forall(
    f,
    Forall([a, b, c],
           Equals(
               Sum(x, fx, Interval(a, c)),
               Add(Sum(x, fx, Interval(a, Sub(b, one))),
                   Sum(x, fx, Interval(b, c)))),
           domain=Integers,
           conditions=[LessThan(a, b), LessThanEquals(b, c)]))
sumSplitBefore
Exemplo n.º 25
0
                                        domain=IntervalCO(a, b)), domain=Reals)
relaxIntervalCO

relaxIntervalOC = Forall((a, b), Forall(x, InSet(x, IntervalCC(a, b)), 
                                        domain=IntervalOC(a, b)), domain=Reals)
relaxIntervalOC

relaxIntervalOOleft = Forall((a, b), Forall(x, InSet(x, IntervalCO(a, b)), 
                                            domain=IntervalOO(a, b)), domain=Reals)
relaxIntervalOOleft

relaxIntervalOOright = Forall((a, b), Forall(x, InSet(x, IntervalOC(a, b)), 
                                             domain=IntervalOO(a, b)), domain=Reals)
relaxIntervalOOright

notIntIfBetweenSuccessiveInts = Forall(n, Forall(x, NotInSet(x, Integers), domain=IntervalOO(n, Add(n, one))), domain=Integers)
notIntIfBetweenSuccessiveInts

eInRealsPos = InSet(e,RealsPos)
eInRealsPos

eNotZero = NotEquals(e,zero)
eNotZero

piInRealsPos = InSet(pi,RealsPos)
piInRealsPos

piNotZero = NotEquals(pi, zero)
piNotZero

endTheorems(locals(), __package__)
Exemplo n.º 26
0
from proveit.common import n, xMulti, xEtc, x, y, S
from common import zero, one, two
from proveit import beginAxioms, endAxioms

beginAxioms(locals())

# Define the set of Naturals as, essentially, the minimum set that contains zero and all of its successors;
# that is, n is in Naturals iff n is in all sets that contain zero and all successors.
naturalsDef = Forall(
    n,
    Equals(
        InSet(n, Naturals),
        Forall(
            S,
            Implies(
                And(InSet(zero, S), Forall(x, InSet(Add(x, one), S),
                                           domain=S)), InSet(n, S)))))

# Define the length of an ExpressionList inductively.
exprListLengthDef = And(
    Equals(Len(), zero),
    Forall((xMulti, y), Equals(Len(xEtc, y), Add(Len(xEtc), one))))

naturalsPosDef = Forall(n,
                        Iff(InSet(n, NaturalsPos), GreaterThanEquals(n, one)),
                        domain=Naturals)
naturalsPosDef

integersDef = Equals(Integers,
                     Union(Naturals, SetOfAll(n, Neg(n), domain=Naturals)))
Exemplo n.º 27
0
                      domain=Complexes,
                      conditions=[NotEquals(a, zero)])
absNotEqZero

absElim = Forall(x, Equals(Abs(x), x), domain=RealsPos)
absElim

absIneq = Forall((x, y),
                 Iff(LessThanEquals(Abs(x), y),
                     And(LessThanEquals(Neg(y), x), LessThanEquals(x, y))),
                 domain=Reals,
                 conditions=[GreaterThanEquals(y, zero)])
absIneq

triangleInequality = Forall([a, b],
                            LessThanEquals(Abs(Add(a, b)), Add(Abs(a),
                                                               Abs(b))),
                            domain=Complexes)
triangleInequality

absProd = Forall(xEtc,
                 Equals(Abs(Mult(xEtc)), Mult(Etcetera(Abs(xMulti)))),
                 domain=Complexes)
absProd

absFrac = Forall([a, b],
                 Equals(Abs(Fraction(a, b)), Fraction(Abs(a), Abs(b))),
                 domain=Complexes)
absFrac

modAbsScaled = Forall((a, b, c),
Exemplo n.º 28
0
from proveit import Operation
from proveit.number import Add, zero, one
from proveit._common_ import k, m, n, P
from proveit.number.sets.integer._common_ import *

Pzero = Operation(P, zero)
Pn = Operation(P, n)
P_nAddOne = Operation(P, Add(n, one))
Pm = Operation(P, m)
P_mAddOne = Operation(P, Add(m, one))
Pk = Operation(P, k)
Exemplo n.º 29
0
notEqualsIsLessThanOrGreaterThan = Forall((a, x),
                                          Or(LessThan(x, a), GreaterThan(x,
                                                                         a)),
                                          domain=Reals,
                                          conditions=[NotEquals(x, a)])
notEqualsIsLessThanOrGreaterThan

shiftLessThanToLessThanEquals = Forall((a, b),
                                       LessThanEquals(a, b),
                                       domain=Integers,
                                       conditions=[LessThan(Sub(a, one), b)])
shiftLessThanToLessThanEquals

lessThanEqualsAddRight = Forall([a, b, c],
                                LessThanEquals(Add(a, c), Add(b, c)),
                                domain=Reals,
                                conditions=[LessThanEquals(a, b)])
lessThanEqualsAddRight

lessThanEqualsAddLeft = Forall([a, b, c],
                               LessThanEquals(Add(c, a), Add(c, b)),
                               domain=Reals,
                               conditions=[LessThanEquals(a, b)])
lessThanEqualsAddLeft

lessThanEqualsSubtract = Forall([a, b, c],
                                LessThanEquals(Sub(a, c), Sub(b, c)),
                                domain=Reals,
                                conditions=[LessThanEquals(a, b)])
lessThanEqualsSubtract
Exemplo n.º 30
0
# phase: Eigenvalue phase of u w.r.t. U.  U u = e^{i \varphi} u.
#        This \varphi is the phase that is the objective of phase estimation.
phase_ = Literal(pkg, 'phase', {LATEX: r'\varphi'})

# t: Number of qubit registers for the quantum phase estimation.
#    We prove that this is the bits of precision of phase estimation.
t_ = Literal(pkg, 't')

# Psi: Outcome of register qubits following the quantum phase estimation circuit.
Psi_ = Literal(pkg, 'PSI', {STRING: 'Psi', LATEX: r'\Psi'})
# psi: indexed intermediate output registers inside the quantum phase estimation circuit.
psi_ = Literal(pkg, 'psi', {STRING: 'psi', LATEX: r'\psi'})
psi_k = SubIndexed(psi_, k)
psi_t = SubIndexed(psi_, t_)
psi_next = SubIndexed(psi_, Add(k, one))
psi_1 = SubIndexed(psi_, one)

U_pow_two_pow_k = Exp(U_, Exp(two, k))

# m: Random variable for the measurement of Psi as an integer from the register's binary representation.
m_ = Literal(pkg, 'm')

# phase_m: Random variable for the phase result of the quantum phase estimation.
#          phase_m = m / 2^t
phase_m_ = Literal(pkg, 'phase_m', {LATEX: r'\varphi_m'})

# b: The "best" outcome of m such that phase_m is as close as possible to phase.
b_ = Literal(pkg, 'b')

# 2^t