Exemple #1
0
def _deduceRequirement(condition, assumptions):
    from proveit.number import num, LessThan, GreaterThan, GreaterThanEquals, Abs
    from proveit.number.complex.theorems import absIsNonNeg
    if isinstance(condition, In):
        domain = condition.domain
        elem = condition.element
        deduceInNumberSet(elem, numberSet=domain, assumptions=assumptions)
    elif isinstance(condition, NotEquals) and condition.rhs == num(0):
        deduceNotZero(condition.lhs, assumptions=assumptions)
    elif isinstance(condition, GreaterThan) and condition.rhs == num(0):
        deducePositive(condition.lhs, assumptions=assumptions)
    elif isinstance(condition, GreaterThanEquals) and condition.rhs == num(0):
        if isinstance(condition.lhs, Abs):
            condition.lhs.deduceGreaterThanEqualsZero(assumptions=assumptions)
        else:
            try:
                # if it is in Naturals, this comes naturally
                deduceInNaturals(condition.lhs, assumptions)
                Naturals.deduceMemberLowerBound(
                    condition.lhs).checked(assumptions)
            except:
                # May also extend with deduceNonNegative, but that isn't implemented yet.
                pass
    elif isinstance(condition, GreaterThanEquals) and condition.rhs == num(1):
        try:
            # if it is in NaturalsPos, this comes naturally
            deduceInNaturalsPos(condition.lhs, assumptions)
            NaturalsPos.deduceMemberLowerBound(
                condition.lhs).checked(assumptions)
        except:
            pass
    elif isinstance(condition, LessThan) and condition.rhs == num(0):
        deduceNegative(condition.lhs, assumptions=assumptions)
def apply_association_thm(expr,
                          startIdx,
                          length,
                          thm,
                          assumptions=USE_DEFAULTS):
    from proveit.logic import Equals
    from proveit.number import num
    beg, end = startIdx, startIdx + length
    if beg < 0: beg = len(expr.operands) + beg  # use wrap-around indexing
    if not length >= 2:
        raise IndexError(
            "The 'length' must be 2 or more when applying association.")
    if end > len(expr.operands):
        raise IndexError("'startIdx+length' out of bounds: %d > %d." %
                         (end, len(expr.operands)))
    if beg == 0 and end == len(expr.operands):
        # association over the entire range is trivial:
        return Equals(expr, expr).prove()  # simply the self equality
    l, m, n, AA, BB, CC = thm.allInstanceVars()
    return thm.specialize(
        {
            l: num(beg),
            m: num(end - beg),
            n: num(len(expr.operands) - end),
            AA: expr.operands[:beg],
            BB: expr.operands[beg:end],
            CC: expr.operands[end:]
        },
        assumptions=assumptions)
Exemple #3
0
    def deduceEquality(self,
                       equality,
                       assumptions=USE_DEFAULTS,
                       minimal_automation=False):
        from proveit import ExprRange
        from proveit.logic import Equals
        if not isinstance(equality, Equals):
            raise ValueError("The 'equality' should be an Equals expression")
        if equality.lhs != self:
            raise ValueError("The left side of 'equality' should be 'self'")

        from proveit.number import num, one

        # Handle the special counting cases.  For example,
        #   (1, 2, 3, 4) = (1, ..., 4)
        _n = len(self)
        if all(self[_k] == num(_k + 1) for _k in range(_n)):
            if (isinstance(equality.rhs, ExprTuple) and len(equality.rhs) == 1
                    and isinstance(equality.rhs[0], ExprRange)):
                expr_range = equality.rhs[0]
                if (expr_range.start_index == one
                        and expr_range.end_index == num(_n)):
                    if len(self) >= 10:
                        raise NotImplementedError("counting range equality "
                                                  "not implemented for more "
                                                  "then 10 elements")
                    import proveit.number.numeral.deci
                    equiv_thm = proveit.number.numeral.deci._theorems_\
                                .__getattr__('count_to_%d_range'%_n)
                    return equiv_thm
        raise NotImplementedError("ExprTuple.deduceEquality not implemented "
                                  "for this case: %s." % self)
Exemple #4
0
 def deriveSwap(self, i, j, assumptions=USE_DEFAULTS):
     '''
     From (A and ... and H and I and J or ... or L and M or N and ... and Q), assuming in Booleans and given
     the beginning and end of the groups to be switched,
     derive and return (A and ... and H and M and J and ... and L and I and N and ... and Q).
     Created by JML on 6/10/19
     '''
     from ._theorems_ import swap
     from proveit.number import num
     if 0 < i < j < len(self.operands) - 1:
         return swap.specialize(
             {
                 l: num(i),
                 m: num(j - i - 1),
                 n: num(len(self.operands) - j - 1),
                 AA: self.operands[:i],
                 B: self.operands[i],
                 CC: self.operands[i + 1:j],
                 D: self.operands[j],
                 EE: self.operands[j + 1:]
             },
             assumptions=assumptions)
     else:
         raise IndexError(
             "Beginnings and ends must be of the type: 0<i<j<length.")
Exemple #5
0
 def deducePartInBool(self, indexOrExpr, assumptions=USE_DEFAULTS):
     '''
     Deduce X in Booleans from (A and B and .. and X and .. and Z) in Booleans
     provided X by expression or index number.
     '''
     from ._theorems_ import eachInBool
     idx = indexOrExpr if isinstance(indexOrExpr, int) else list(
         self.operands).index(indexOrExpr)
     if idx < 0 or idx >= len(self.operands):
         raise IndexError("Operand out of range: " + str(idx))
     if len(self.operands) == 2:
         if idx == 0: return self.deduceLeftInBool(assumptions)
         elif idx == 1: return self.deduceRightInBool(assumptions)
     else:
         from proveit.number import num
         mVal, nVal = num(idx), num(len(self.operands) - idx - 1)
         return eachInBool.specialize(
             {
                 m: mVal,
                 n: nVal,
                 AA: self.operands[:idx],
                 B: self.operands[idx],
                 CC: self.operands[idx + 1:]
             },
             assumptions=assumptions)
Exemple #6
0
 def deriveViaMultiDilemma(self, conclusion, assumptions=USE_DEFAULTS):
     '''
     From (A or B) as self, and assuming A => C, B => D, and A, B, C, and D are Booleans,
     derive and return the conclusion, C or D.
     '''
     from ._theorems_ import constructiveDilemma, destructiveDilemma, constructiveMultiDilemma, destructiveMultiDilemma
     from proveit.logic import Not, Or
     from proveit.number import num
     assert isinstance(conclusion, Or) and len(conclusion.operands) == len(
         self.operands
     ), "deriveViaMultiDilemma requires conclusion to be a disjunction, the same number of operands as self."
     # Check for destructive versus constructive dilemma cases.
     if all(isinstance(operand, Not) for operand in self.operands) and all(
             isinstance(operand, Not) for operand in conclusion.operands):
         # destructive case.
         if len(self.operands) == 2:
             # From Not(C) or Not(D), A => C, B => D, conclude Not(A) or Not(B)
             return destructiveDilemma.specialize(
                 {
                     C: self.operands[0].operand,
                     D: self.operands[1].operand,
                     A: conclusion.operands[0].operand,
                     B: conclusion.operands[1].operand
                 },
                 assumptions=assumptions)
         # raise NotImplementedError("Generalized destructive multi-dilemma not implemented yet.")
         # Iterated destructive case.  From (Not(A) or Not(B) or Not(C) or Not(D)) as self
         negatedOperandsSelf = [
             operand.operand for operand in self.operands
         ]
         negatedOperandsConc = [
             operand.operand for operand in conclusion.operands
         ]
         return destructiveMultiDilemma.specialize(
             {
                 m: num(len(self.operands)),
                 A: negatedOperandsSelf,
                 B: negatedOperandsConc
             },
             assumptions=assumptions)
     else:
         # constructive case.
         if len(self.operands) == 2:
             # From (A or B), A => C, B => D, conclude C or D.
             return constructiveDilemma.specialize(
                 {
                     A: self.operands[0],
                     B: self.operands[1],
                     C: conclusion.operands[0],
                     D: conclusion.operands[1]
                 },
                 assumptions=assumptions)
         #raise NotImplementedError("Generalized constructive multi-dilemma not implemented yet.")
         return constructiveMultiDilemma.specialize(
             {
                 m: num(len(self.operands)),
                 A: self.operands,
                 B: conclusion.operands
             },
             assumptions=assumptions)
Exemple #7
0
 def concludeViaExample(self, trueOperand, assumptions=USE_DEFAULTS):
     '''
     From one true operand, conclude that this 'or' expression is true.
     Requires all of the operands to be in the set of BOOLEANS.
     '''
     from proveit.number import num
     from ._theorems_ import nandIfNotOne, nandIfNotLeft, nandIfNotRight
     index = self.operands.index(trueOperand)
     if len(self.operands) == 2:
         if index == 0:
             return nandIfNotLeft.specialize(
                 {
                     A: self.operands[0],
                     B: self.operands[1]
                 },
                 assumptions=assumptions)
         elif index == 1:
             return nandIfNotRight.specialize(
                 {
                     A: self.operands[0],
                     B: self.operands[1]
                 },
                 assumptions=assumptions)
     return nandIfNotOne.specialize(
         {
             m: num(index),
             n: num(len(self.operands) - index - 1),
             AA: self.operands[:index],
             B: self.operands[index],
             CC: self.operands[index + 1:]
         },
         assumptions=assumptions)
Exemple #8
0
    def conversionToAddition(self, assumptions=USE_DEFAULTS):
        '''
        From multiplication by an integer as the first factor,
        derive and return the equivalence of this multiplication
        to a repeated addition; for example, 3*c = c + c + c.
        '''
        from ._axioms_ import multDef
        if hasattr(self.operands[0], 'asInt'):
            reps = self.operands[0].asInt()
        else:
            raise ValueError(
                "Cannot 'expandAsAddition' unless the first operand is a literal integer: %s"
                % str(self))

        expr = self
        eq = TransRelUpdater(
            self, assumptions)  # for convenience updating our equation
        # Group together the remaining factors if necessary:
        if len(self.operands) > 2:
            expr = eq.update(
                expr.association(1,
                                 len(self.operands) - 1, assumptions))
        _x = self.operands[1]
        _n = num(reps)
        eq.update(
            multDef.specialize({
                n: _n,
                a: [_x] * reps,
                x: _x
            },
                               assumptions=assumptions))
        return eq.relation
Exemple #9
0
 def distribute(self, assumptions=USE_DEFAULTS):
     '''
     Distribute the absolute value over a product or fraction.
     Assumptions may be needed to deduce that the sub-operands are
     complex numbers.
     This works fine for the Abs(Div()) case, but still
     eliciting an extractInitArgValue error related to a multi-
     variable domain condition for the Mult case. See _demos_ pg
     for an example; WW thinks this is a prob with iterations and
     we'll fix/update this later.
     '''
     from ._theorems_ import absFrac, absProd
     from proveit._common_ import n, xx
     from proveit.number import num, Complexes, Div, Mult
     if isinstance(self.operand, Div):
         return absFrac.specialize(
             {
                 a: self.operand.numerator,
                 b: self.operand.denominator
             },
             assumptions=assumptions)
     elif isinstance(self.operand, Mult):
         from proveit._common_ import xx
         theOperands = self.operand.operands
         return absProd.specialize(
             {
                 n: num(len(theOperands)),
                 xx: theOperands
             },
             assumptions=assumptions)
     else:
         raise ValueError(
             'Unsupported operand type for Abs.distribute() '
             'method: ', str(self.operand.__class__))
Exemple #10
0
    def equivalence(self, assumptions=USE_DEFAULTS):
        '''
        From the EnumMembership object [element in {a, ..., n}],
        deduce and return:
        |– [element in {x, y, ..}] = [(element=a) or ... or (element=a)]
        '''
        from ._axioms_ import enumSetDef
        from ._theorems_ import singletonDef
        enum_elements = self.domain.elements

        if len(enum_elements) == 1:
            return singletonDef.instantiate(
                {
                    x: self.element,
                    y: enum_elements[0]
                },
                assumptions=assumptions)
        else:
            return enumSetDef.instantiate(
                {
                    n: num(len(enum_elements)),
                    x: self.element,
                    y: enum_elements
                },
                assumptions=assumptions)
Exemple #11
0
    def distribution(self, assumptions=USE_DEFAULTS):
        '''
        Distribute negation through a sum, deducing and returning
        the equality between the original and distributed forms.
        '''
        from ._theorems_ import distributeNegThroughBinarySum
        from ._theorems_ import distributeNegThroughSubtract, distributeNegThroughSum
        from proveit.number import Add, num
        from proveit.relation import TransRelUpdater
        expr = self
        eq = TransRelUpdater(
            expr, assumptions)  # for convenience updating our equation

        if isinstance(self.operand, Add):
            # Distribute negation through a sum.
            add_expr = self.operand
            if len(add_expr.operands) == 2:
                # special case of 2 operands
                if isinstance(add_expr.operands[1], Neg):
                    expr = eq.update(
                        distributeNegThroughSubtract.specialize(
                            {
                                a: add_expr.operands[0],
                                b: add_expr.operands[1].operand
                            },
                            assumptions=assumptions))
                else:
                    expr = eq.update(
                        distributeNegThroughBinarySum.specialize(
                            {
                                a: add_expr.operands[0],
                                b: add_expr.operands[1]
                            },
                            assumptions=assumptions))
            else:
                # distribute the negation over the sum
                expr = eq.update(distributeNegThroughSum.specialize({
                    n:
                    num(len(add_expr.operands)),
                    xx:
                    add_expr.operands
                }),
                                 assumptions=assumptions)
            assert isinstance(
                expr, Add
            ), "distributeNeg theorems are expected to yield an Add expression"
            # check for double negation
            for k, operand in enumerate(expr.operands):
                assert isinstance(
                    operand, Neg
                ), "Each term from distributeNegThroughSum is expected to be negated"
                if isinstance(operand.operand, Neg):
                    expr = eq.update(
                        expr.innerExpr().operands[k].doubleNegSimplification())
            return eq.relation
        else:
            raise Exception(
                'Only negation distribution through a sum or subtract is implemented'
            )
Exemple #12
0
 def equivalence(self, element, assumptions=USE_DEFAULTS):
     '''
     Deduce and return and [element in (A union B ...)] = [(element in A) or (element in B) ...]
     where self = (A union B ...).
     '''
     from ._axioms_ import unionDef
     element = self.element
     operands = self.domain.operands
     return unionDef.specialize({l:num(len(operands)), x:element, AA:operands}, assumptions=assumptions)
Exemple #13
0
def QubitRegisterSpace(num_Qbits):
    '''
    Transplanted here beginning 2/13/2020 by wdc, from the old
    physics/quantum/common.py
    '''
    # need some extra curly brackets around the Exp() expression
    # to allow the latex superscript to work on something
    # already superscripted
    return TensorExp({Exp(Complexes, num(2))}, num_Qbits)
Exemple #14
0
 def unfold(self, assumptions=USE_DEFAULTS):
     '''
     From [element in (A union B ...)], derive and return [(element in A) or (element in B) ...],
     where self represents (A union B ...). 
     '''
     from ._theorems_ import membershipUnfolding
     from proveit.number import num
     element = self.element
     operands = self.domain.operands
     return membershipUnfolding.specialize({m:num(len(operands)), x:element, AA:operands}, assumptions=assumptions)
Exemple #15
0
 def unfold(self, assumptions=USE_DEFAULTS):
     '''
     From [element in {x, y, ..}], derive and return [(element=x) or (element=y) or ..].
     '''
     from ._theorems_ import unfoldSingleton, unfold
     enum_elements = self.domain.elements
     if len(enum_elements) == 1:
         return unfoldSingleton.specialize({x:self.element, y:enum_elements[0]},assumptions=assumptions)
     else:
         return unfold.specialize({l:num(len(enum_elements)), x:self.element, yy:enum_elements}, assumptions=assumptions)
Exemple #16
0
 def equivalence(self, assumptions=USE_DEFAULTS):
     '''
     Deduce and return and [element not in (A union B ...)] = [(element not in A) and (element not in B) ...]
     where self = (A union B ...).
     '''
     from ._theorems_ import nonmembershipEquiv
     from proveit.number import num
     element = self.element
     operands = self.domain.operands
     return nonmembershipEquiv.specialize({m:num(len(operands)), x:element, AA:operands}, assumptions=assumptions)
Exemple #17
0
 def conclude(self, assumptions=USE_DEFAULTS):
     '''
     From [element not in A] and [element not in B] ..., derive and return [element not in (A union B ...)],
     where self represents (A union B ...). 
     '''
     from ._theorems_ import nonmembershipFolding
     from proveit.number import num
     element = self.element
     operands = self.domain.operands
     return nonmembershipFolding.specialize({m:num(len(operands)), x:element, AA:operands}, assumptions=assumptions)
Exemple #18
0
 def locAsExprs(loc):
     from proveit.number import num
     loc_exprs = []
     for coord in loc:
         if isinstance(coord, int):
             coord = num(coord) # convert int to an Expression
         if not isinstance(coord, Expression):
             raise TypeError("location coordinates must be Expression objects (or 'int's to convert to Expressions)")
         loc_exprs.append(coord)
     return loc_exprs
Exemple #19
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
Exemple #20
0
 def concludeViaDemorgans(self, assumptions=USE_DEFAULTS):
     '''
     # created by JML 6/28/19
     From A and B and C conclude Not(Not(A) or Not(B) or Not(C))
     '''
     from ._theorems_ import demorgansLawOrToAnd, demorgansLawOrToAndBin
     from proveit.number import num
     if len(self.operands) == 2:
         return demorgansLawOrToAndBin.specialize({A:self.operands[0], B:self.operands[1]}, assumptions=assumptions)
     else:
         return demorgansLawOrToAnd.specialize({m:num(len(self.operands)), A:self.operands}, assumptions=assumptions)
Exemple #21
0
 def deduceInBool(self, assumptions=USE_DEFAULTS):
     '''
     Attempt to deduce, then return, that this 'and' expression is in the set of BOOLEANS.
     '''
     
     from ._theorems_ import binaryClosure, closure
     if len(self.operands)==2:
         return binaryClosure.specialize({A:self.operands[0], B:self.operands[1]}, assumptions=assumptions)
     else:
         from proveit.number import num    
     return closure.specialize({m:num(len(self.operands)), A:self.operands}, assumptions=assumptions)
Exemple #22
0
 def equivalence(self):
     '''
     Deduce and return and [element not in {x, y, ..}] = [(element != x) and (element != y) and ...]
     where self = {y}.
     '''
     from ._theorems_ import notInSingletonEquiv, nonmembershipEquiv
     enum_elements = self.domain.elements
     if len(enum_elements) == 1:
         return notInSingletonEquiv.specialize({x:self.element, y:enum_elements})
     else:
         return nonmembershipEquiv.specialize({l:num(len(enum_elements)), x:self.element, yy:enum_elements})
Exemple #23
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])
Exemple #24
0
 def evaluation(self, assumptions=USE_DEFAULTS):
     '''
     Given operands that evaluate to TRUE or FALSE, derive and
     return the equality of this expression with TRUE or FALSE. 
     '''
     from ._axioms_ import orTT, orTF, orFT, orFF  # load in truth-table evaluations
     from ._theorems_ import trueEval, falseEval
     from proveit.logic.boolean._common_ import TRUE, FALSE
     trueIndex = -1
     for i, operand in enumerate(self.operands):
         if operand != TRUE and operand != FALSE:
             # The operands are not always true/false, so try the default evaluation method
             # which will attempt to evaluate each of the operands.
             return Operation.evaluation(self, assumptions)
         if operand == TRUE:
             trueIndex = i
     if len(self.operands) == 2:
         # This will automatically return orTT, orTF, orFT, or orFF
         return Operation.evaluation(self, assumptions)
     if trueIndex >= 0:
         # one operand is TRUE so the whole disjunction evaluates to TRUE.
         from proveit.number import num
         mVal, nVal = num(trueIndex), num(
             len(self.operands) - trueIndex - 1)
         return trueEval.specialize(
             {
                 m: mVal,
                 n: nVal,
                 AA: self.operands[:trueIndex],
                 CC: self.operands[trueIndex + 1:]
             },
             assumptions=assumptions)
     else:
         # no operand is TRUE so the whole disjunction evaluates to FALSE.
         from proveit.number import num
         return falseEval.specialize(
             {
                 m: num(len(self.operands)),
                 AA: self.operands
             },
             assumptions=assumptions)
Exemple #25
0
    def innerNegMultSimplification(self, idx, assumptions=USE_DEFAULTS):
        '''
        Equivalence method to derive a simplification when negating
        a multiplication with a negated factor.  For example,
        -(a*b*(-c)*d) = a*b*c*d.
        See Mult.negSimplification where this may be used indirectly.
        '''
        from proveit.number import Mult, num
        from ._theorems_ import multNegLeftDouble, multNegRightDouble, multNegAnyDouble

        mult_expr = self.operand
        if not isinstance(mult_expr, Mult):
            raise ValueError(
                "Operand expected to be a Mult expression for %s" %
                (idx, str(self)))
        if not isinstance(mult_expr.operands[idx], Neg):
            raise ValueError(
                "Operand at the index %d expected to be a negation for %s" %
                (idx, str(mult_expr)))

        if len(mult_expr.operands) == 2:
            if idx == 0:
                return multNegLeftDouble.specialize({a: mult_expr.operands[1]},
                                                    assumptions=assumptions)
            else:
                return multNegRightDouble.specialize(
                    {a: mult_expr.operands[0]}, assumptions=assumptions)
        aVal = mult_expr.operands[:idx]
        bVal = mult_expr.operands[idx]
        cVal = mult_expr.operands[idx + 1:]
        mVal = num(len(aVal))
        nVal = num(len(cVal))
        return multNegAnyDouble.specialize(
            {
                m: mVal,
                n: nVal,
                AA: aVal,
                B: bVal,
                CC: cVal
            },
            assumptions=assumptions)
Exemple #26
0
 def distinctSubsetExistence(self, elems=None, assumptions=USE_DEFAULTS):
     '''
     Assuming the cardinality of the domain can be proven to be >= 2,
     proves and returns that there exists distinct elements in that domain.
     '''
     from proveit.number import num
     from ._theorems_ import distinctSubsetExistence, distinctPairExistence
     if len(elems)==2:
         aVar, bVar = elems
         return distinctPairExistence.specialize({S:self.domain}, relabelMap={a:aVar, b:bVar}, assumptions=assumptions)
     else:
         return distinctSubsetExistence.specialize({S:self.domain, N:num(len(elems))}, relabelMap={xMulti:elems}, assumptions=assumptions)
Exemple #27
0
 def deduceInNumberSet(self, numberSet, assumptions=USE_DEFAULTS):
     # edited by JML 7/20/19
     from ._theorems_ import multIntClosure, multIntClosureBin, multNatClosure, multNatClosureBin, multNatPosClosure, multNatClosureBin, multRealClosure, multRealClosureBin, multRealPosClosure, multRealPosClosureBin, multComplexClosure, multComplexClosureBin
     from proveit.number import num
     if hasattr(self, 'number_set'):
         numberSet = numberSet.number_set
     bin = False
     if numberSet == Integers:
         if len(self.operands) == 2:
             thm = multIntClosureBin
             bin = True
         else:
             thm = multIntClosure
     elif numberSet == Naturals:
         if len(self.operands) == 2:
             thm = multNatsClosureBin
             bin = True
         else:
             thm = multNatsClosure
     elif numberSet == NaturalsPos:
         if len(self.operands) == 2:
             thm = multNatsPosClosureBin
             bin = True
         else:
             thm = multNatsPosClosure
     elif numberSet == Reals:
         if len(self.operands) == 2:
             thm = multRealClosureBin
             bin = True
         else:
             thm = multRealClosure
     elif numberSet == RealsPos:
         if len(self.operands) == 2:
             thm = multRealsPosClosureBin
             bin = True
         else:
             thm = multRealPosClosure
     elif numberSet == Complexes:
         if len(self.operands) == 2:
             thm = multComplexClosureBin
             bin = True
         else:
             thm = multComplexClosure
     else:
         msg = "'deduceInNumberSet' not implemented for the %s set"%str(numberSet)
         raise ProofFailure(InSet(self, numberSet), assumptions, msg)
     from proveit._common_ import AA
     # print("thm", thm)
     # print("self in deduce in number set", self)
     # print("self.operands", self.operands)
     if bin:
         return thm.specialize({a:self.operands[0], b:self.operands[1]}, assumptions=assumptions)
     return thm.specialize({m:num(len(self.operands)),AA:self.operands}, assumptions=assumptions)
Exemple #28
0
def apply_disassociation_thm(expr, idx, thm=None, assumptions=USE_DEFAULTS):
    from proveit.number import num
    if idx < 0: idx = len(expr.operands) + idx  # use wrap-around indexing
    if idx >= len(expr.operands):
        raise IndexError("'idx' out of range for disassociation")
    if not isinstance(expr.operands[idx], expr.__class__):
        raise ValueError(
            "Expecting %d index of %s to be grouped (i.e., a nested expression of the same type)"
            % (idx, str(expr)))
    l, m, n, AA, BB, CC = thm.allInstanceVars()
    length = len(expr.operands[idx].operands)
    return thm.specialize(
        {
            l: num(idx),
            m: num(length),
            n: num(len(expr.operands) - idx - 1),
            AA: expr.operands[:idx],
            BB: expr.operands[idx].operands,
            CC: expr.operands[idx + 1:]
        },
        assumptions=assumptions)
Exemple #29
0
    def equivalence(self, assumptions=USE_DEFAULTS):
        '''
        Deduce and return and [element in {x, y, ..}] = [(element=x) or (element=y) or ...] 
        where self = {y}.
        '''
        from ._axioms_ import enumSetDef
        from ._theorems_ import singletonDef
        enum_elements = self.domain.elements

        if len(enum_elements) == 1:
            return singletonDef.specialize({x:self.element, y:enum_elements[0]}, assumptions=assumptions)
        else:
            return enumSetDef.specialize({l:num(len(enum_elements)), x:self.element, yy:enum_elements}, assumptions=assumptions)
Exemple #30
0
 def oneElimination(self, idx, assumptions=USE_DEFAULTS):
     '''
     Equivalence method that derives a simplification in which
     a single factor of one, at the given index, is eliminated.  
     For example:
         x*y*1*z = x*y*z
     '''
     from proveit.number import one, num
     from ._theorems_ import elimOneLeft, elimOneRight, elimOneAny
     
     if self.operands[idx] != one:
         raise ValueError("Operand at the index %d expected to be zero for %s"%(idx, str(self)))
     
     if len(self.operands)==2:
         if idx==0:
             return elimOneLeft.specialize({x:self.operands[1]}, assumptions=assumptions)
         else:
             return elimOneRight.specialize({x:self.operands[0]}, assumptions=assumptions)
     aVal = self.operands[:idx]
     bVal = self.operands[idx+1:]
     mVal = num(len(aVal))
     nVal = num(len(bVal))
     return elimOneAny.specialize({m:mVal, n:nVal, AA:aVal, BB:bVal}, assumptions=assumptions)