コード例 #1
0
 def deduceInNumberSet(self, numberSet, assumptions=USE_DEFAULTS):
     from ._theorems_ import summationNatsClosure, summationIntsClosure, summationRealsClosure, summationComplexesClosure
     P_op, P_op_sub = Operation(P, self.instanceVars), self.instanceExpr
     Q_op, Q_op_sub = Operation(Qmulti, self.instanceVars), self.conditions
     Operation(P, self.instanceVars)
     self.summand
     if numberSet == Naturals:
         thm = summationNatsClosure
     elif numberSet == Integers:
         thm = summationIntsClosure
     elif numberSet == Reals:
         thm = summationRealsClosure
     elif numberSet == Complexes:
         thm = summationComplexesClosure
     else:
         raise ProofFailure(
             InSet(self, numberSet), assumptions,
             "'deduceInNumberSet' not implemented for the %s set" %
             str(numberSet))
     return thm.specialize(
         {
             P_op: P_op_sub,
             S: self.domain,
             Q_op: Q_op_sub
         },
         relabelMap={
             xMulti: self.instanceVars
         },
         assumptions=assumptions).deriveConsequent(assumptions=assumptions)
コード例 #2
0
 def deriveBundled(self, assumptions=USE_DEFAULTS):
     '''
     From a nested forall statement, derive the bundled forall statement.  For example,
     forall_{x | Q(x)} forall_{y | R(y)} P(x, y) becomes forall_{x, y | Q(x), R(y)} P(x, y).
     '''
     raise NotImplementedError("Need to update")
     from ._theorems_ import bundling
     assert isinstance(self.instanceExpr,
                       Forall), "Can only bundle nested forall statements"
     innerForall = self.instanceExpr
     composedInstanceVars = ExprList(
         [self.instanceVars, innerForall.instanceVars])
     P_op, P_op_sub = Operation(
         P, composedInstanceVars), innerForall.instanceExpr
     Q_op, Q_op_sub = Operation(Qmulti, self.instanceVars), self.conditions
     R_op, R_op_sub = Operation(
         Rmulti, innerForall.instanceVars), innerForall.conditions
     return bundling.specialize({
         xMulti: self.instanceVars,
         yMulti: innerForall.instanceVars,
         P_op: P_op_sub,
         Q_op: Q_op_sub,
         R_op: R_op_sub,
         S: self.domain
     }).deriveConclusion(assumptions)
コード例 #3
0
 def deriveNegatedForall(self, assumptions=USE_DEFAULTS):
     '''
     From [exists_{x | Q(x)} Not(P(x))], derive and return Not(forall_{x | Q(x)} P(x)).
     From [exists_{x | Q(x)} P(x)], derive and return Not(forall_{x | Q(x)} (P(x) != TRUE)).
     '''
     raise NotImplementedError("Need to update")
     from ._axioms_ import existsDef
     from ._theorems_ import existsNotImpliesNotForall
     from proveit.logic import Not
     Q_op, Q_op_sub = Operation(Qmulti, self.instanceVars), self.conditions
     if isinstance(self.instanceExpr, Not):
         P_op, P_op_sub = Operation(
             P, self.instanceVars), self.instanceExpr.operand
         return existsNotImpliesNotForall.specialize(
             {
                 P_op: P_op_sub,
                 Q_op: Q_op_sub,
                 S: self.domain
             },
             assumptions=assumptions,
             relabelMap={
                 xMulti: self.instanceVars
             }).deriveConsequent(assumptions)
     else:
         P_op, P_op_sub = Operation(P, self.instanceVars), self.instanceExpr
         return existsDef.specialize(
             {
                 P_op: P_op_sub,
                 Q_op: Q_op_sub,
                 S: self.domain
             },
             assumptions=assumptions,
             relabelMap={
                 xMulti: self.instanceVars
             }).deriveRightViaEquivalence(assumptions)
コード例 #4
0
 def foldAsForall(self, forallStmt, assumptions=USE_DEFAULTS):
     '''
     Given forall_{A in Booleans} P(A), conclude and return it from [P(TRUE) and P(FALSE)].
     '''
     from proveit.logic import Forall
     from ._theorems_ import foldForallOverBool, foldConditionedForallOverBool
     from ._common_ import Booleans
     assert (
         isinstance(forallStmt, Forall)
     ), "May only apply foldAsForall method of Booleans to a forall statement"
     assert (
         forallStmt.domain == Booleans
     ), "May only apply foldAsForall method of Booleans to a forall statement with the Booleans domain"
     assert (
         len(forallStmt.conditions) <= 2
     ), "May only apply foldAsForall method of Booleans to a forall statement with the Booleans domain but no other conditions"
     assert (
         not hasattr(forallStmt, 'instanceVars')
     ), "May only apply foldAsForall method of Booleans to a forall statement with 1 instance variable"
     if (len(forallStmt.conditions) == 2):
         Q_op, Q_op_sub = Operation(
             Q, forallStmt.instanceVar), forallStmt.conditions[1]
         P_op, P_op_sub = Operation(
             P, forallStmt.instanceVar), forallStmt.instanceExpr
         return foldConditionedForallOverBool.specialize(
             {
                 Q_op: Q_op_sub,
                 P_op: P_op_sub
             }, {A: forallStmt.instanceVar})
     else:
         # forall_{A in Booleans} P(A), assuming P(TRUE) and P(FALSE)
         P_op, P_op_sub = Operation(
             P, forallStmt.instanceVar), forallStmt.instanceExpr
         return foldForallOverBool.specialize({P_op: P_op_sub},
                                              {A: forallStmt.instanceVar})
コード例 #5
0
 def deduceInBool(self, assumptions=USE_DEFAULTS):
     '''
     Attempt to deduce, then return, that this forall expression is in the set of BOOLEANS,
     as all forall expressions are (they are taken to be false when not true).
     '''
     raise NotImplementedError("Need to update")
     from _axioms_ import forallInBool
     P_op, P_op_sub = Operation(P, self.instanceVars), self.instanceExpr
     Q_op, Q_op_sub = Operation(Qmulti, self.instanceVars), self.conditions
     return forallInBool.specialize({P_op:P_op_sub, Q_op:Q_op_sub, xMulti:self.instanceVars, S:self.domain})
コード例 #6
0
 def conclude_as_folded(self, assumptions=USE_DEFAULTS):
     '''
     Prove and return some NotExists_{x | Q(x)} P(x) assuming Not(Exists_{x | Q(x)} P(x)).
     This is automatically derived; see Not.derive_side_effects(..) and Not.derive_not_exists(..).
     '''
     from . import not_exists_folding
     P_op, P_op_sub = Operation(P, self.instance_vars), self.instance_expr
     Q_op, Q_op_sub = Etcetera(
         Operation(Q, self.instance_vars)), self.conditions
     folding = not_exists_folding.instantiate(
         {P_op: P_op_sub, Q_op: Q_op_sub, x_multi: self.instance_vars, S: self.domain})
     return folding.derive_conclusion(assumptions)
コード例 #7
0
 def deduceMembership(self, element, assumptions=USE_DEFAULTS):
     '''
     From P(x), derive and return (x in {y | P(y)}), where x is meant as the given element.
     '''   
     from _theorems_ import foldComprehension, foldBasicComprehension
     Q_op, Q_op_sub = Operation(Qmulti, self.instanceVars), self.conditions
     if len(self.instanceVars) == 1 and self.instanceElement == self.instanceVars[0] and len(self.conditions) == 1:
         Pop, Psub = Operation(P, self.instanceVars), self.conditions[0]
         return foldBasicComprehension.specialize({S:self.domain, Q_op:Q_op_sub, x:element}, {y:self.instanceVars[0]}, assumptions=assumptions)
     else:
         f_op, f_sub = Operation(f, self.instanceVars), self.instanceElement
         return foldComprehension.specialize({S:self.domain, Q_op:Q_op_sub, f_op:f_sub, x:element}, {yMulti:self.instanceVars}).deriveConclusion(assumptions)
コード例 #8
0
ファイル: not_exists.py プロジェクト: shoelbling/Prove-It
 def unfold(self, assumptions=USE_DEFAULTS):
     '''
     Derive and return Not(Exists_{x | Q(x)} P(x)) from NotExists_{x | Q(x)} P(x)
     '''
     from ._theorems_ import notExistsUnfolding
     P_op, P_op_sub = Operation(P, self.instanceVars), self.instanceExpr
     Q_op, Q_op_sub = Etcetera(Operation(
         Q, self.instanceVars)), self.conditions
     return notExistsUnfolding.specialize({
         P_op: P_op_sub,
         Q_op: Q_op_sub,
         xMulti: self.instanceVars,
         S: self.domain
     }).deriveConclusion(assumptions)
コード例 #9
0
 def unfold(self, assumptions=USE_DEFAULTS):
     '''
     Derive and return Not(Exists_{x | Q(x)} P(x)) from NotExists_{x | Q(x)} P(x)
     '''
     from . import not_exists_unfolding
     P_op, P_op_sub = Operation(P, self.instance_vars), self.instance_expr
     Q_op, Q_op_sub = Etcetera(
         Operation(Q, self.instance_vars)), self.conditions
     return not_exists_unfolding.instantiate(
         {
             P_op: P_op_sub,
             Q_op: Q_op_sub,
             x_multi: self.instance_vars,
             S: self.domain}).derive_conclusion(assumptions)
コード例 #10
0
ファイル: sum.py プロジェクト: rmmilewi/Prove-It
 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()
コード例 #11
0
 def conclude(self, assumptions):
     from ._theorems_ import subsetEqViaEquality
     from proveit import ProofFailure
     from proveit.logic import SetOfAll
     
     try:
         # first attempt a transitivity search
         return ContainmentRelation.conclude(self, assumptions)
     except ProofFailure:
         pass # transitivity search failed
     
     # Any set contains itself
     if self.operands[0] == self.operands[1]:
         return subsetEqViaEquality.specialize({A:self.operands[0], B:self.operands[1]})
         
     # Check for special case of [{x | Q*(x)}_{x \in S}] \subseteq S
     if isinstance(self.subset, SetOfAll):
         from proveit.logic.set_theory.comprehension._theorems_ import comprehensionIsSubset
         setOfAll = self.subset
         if len(setOfAll.instanceVars)==1 and setOfAll.instanceElement == setOfAll.instanceVars[0] and setOfAll.domain==self.superset:
             Q_op, Q_op_sub = Operation(Qmulti, setOfAll.instanceVars), setOfAll.conditions
             return comprehensionIsSubset.specialize({S:setOfAll.domain, Q_op:Q_op_sub}, relabelMap={x:setOfAll.instanceVars[0]}, assumptions=assumptions)
     
     # Finally, attempt to conclude A subseteq B via forall_{x in A} x in B.
     return self.concludeAsFolded(elemInstanceVar=safeDummyVar(self), assumptions=assumptions)
コード例 #12
0
 def split(self, splitIndex, side='after', assumptions=frozenset()):
     r'''
     Splits summation over one Interval {a ... c} into two summations.
     If side == 'after', it splits into a summation over {a ... splitIndex} plus
     a summation over {splitIndex+1 ... c}.  If side == 'before', it splits into
     a summation over {a ... splitIndex-1} plus a summation over {splitIndex ... c}.
     As special cases, splitIndex==a with side == 'after' splits off the first single
     term.  Also, splitIndex==c with side == 'before' splits off the last single term.
     r'''
     if not isinstance(self.domain, Interval):
         raise Exception(
             'Sum splitting only implemented for Interval domains')
     if side == 'before' and self.domain.upperBound == splitIndex:
         return self.splitOffLast()
     if side == 'after' and self.domain.lowerBound == splitIndex:
         return self.splitOffFirst()
     if isinstance(self.domain, Interval) and len(self.instanceVars) == 1:
         from theorems import sumSplitAfter, sumSplitBefore
         sumSplit = sumSplitAfter if side == 'after' else sumSplitBefore
         deduceInIntegers(self.domain.lowerBound, assumptions)
         deduceInIntegers(self.domain.upperBound, assumptions)
         deduceInIntegers(splitIndex, assumptions)
         # Also needs lowerBound <= splitIndex and splitIndex < upperBound
         return sumSplit.specialize({
             Operation(f, self.instanceVars):
             self.summand
         }).specialize({
             a: self.domain.lowerBound,
             b: splitIndex,
             c: self.domain.upperBound,
             x: self.indices[0]
         })
     raise Exception(
         "splitOffLast only implemented for a summation over a Interval of one instance variable"
     )
コード例 #13
0
ファイル: not_exists.py プロジェクト: shoelbling/Prove-It
 def concludeAsFolded(self, assumptions=USE_DEFAULTS):
     '''
     Prove and return some NotExists_{x | Q(x)} P(x) assuming Not(Exists_{x | Q(x)} P(x)).
     This is automatically derived; see Not.deriveSideEffects(..) and Not.deriveNotExists(..).
     '''
     from ._theorems_ import notExistsFolding
     P_op, P_op_sub = Operation(P, self.instanceVars), self.instanceExpr
     Q_op, Q_op_sub = Etcetera(Operation(
         Q, self.instanceVars)), self.conditions
     folding = notExistsFolding.specialize({
         P_op: P_op_sub,
         Q_op: Q_op_sub,
         xMulti: self.instanceVars,
         S: self.domain
     })
     return folding.deriveConclusion(assumptions)
コード例 #14
0
ファイル: divide.py プロジェクト: rmmilewi/Prove-It
 def distribute(self, assumptions=frozenset()):
     r'''
     Distribute the denominator through the numerate.  
     Returns the equality that equates self to this new version.
     Examples: 
         :math:`(a + b + c) / d = a / d + b / d + c / d`
         :math:`(a - b) / d = a / d - b / d`
         :math:`\left(\sum_x f(x)\right / y = \sum_x [f(x) / y]`
     Give any assumptions necessary to prove that the operands are in Complexes so that
     the associative and commutation theorems are applicable.            
     '''
     from proveit.number import Add, Subtract, Sum
     from ._theorems_ import distributeFractionThroughSum, distributeFractionThroughSubtract, distributeFractionThroughSummation
     if isinstance(self.numerator, Add):
         return distributeFractionThroughSum.specialize({xEtc:self.numerator.operands, y:self.denominator})
     elif isinstance(self.numerator, Subtract):
         return distributeFractionThroughSubtract.specialize({x:self.numerator.operands[0], y:self.numerator.operands[1], z:self.denominator})
     elif isinstance(self.numerator, Sum):
         # Should deduce in Complexes, but distributeThroughSummation doesn't have a domain restriction right now
         # because this is a little tricky.   To do.
         #deduceInComplexes(self.operands, assumptions)
         yEtcSub = self.numerator.indices
         Pop, Pop_sub = Operation(P, self.numerator.indices), self.numerator.summand
         S_sub = self.numerator.domain
         dummyVar = safeDummyVar(self)            
         spec1 = distributeFractionThroughSummation.specialize({Pop:Pop_sub, S:S_sub, yEtc:yEtcSub, z:dummyVar})
         return spec1.deriveConclusion().specialize({dummyVar:self.denominator})
     else:
         raise Exception("Unsupported operand type to distribute over: " + self.numerator.__class__)
コード例 #15
0
ファイル: subset.py プロジェクト: rmmilewi/Prove-It
    def conclude(self, assumptions):
        from ._theorems_ import subsetEqViaEquality
        from proveit import ProofFailure
        from proveit.logic import SetOfAll, Equals
        
        try:
            # first attempt a transitivity search
            return ContainmentRelation.conclude(self, assumptions)
        except ProofFailure:
            pass # transitivity search failed
        
        # Any set contains itself
        try:
            Equals(self.operands[0], self.operands[1]).prove(assumptions, automation=False)
            return subsetEqViaEquality.specialize({A: self.operands[0], B: self.operands[1]})
        except ProofFailure:
            pass

        # Check for special case of [{x | Q*(x)}_{x \in S}] \subseteq S
        if isinstance(self.subset, SetOfAll):
            from proveit.logic.set_theory.comprehension._theorems_ import comprehensionIsSubset
            setOfAll = self.subset
            if len(setOfAll.instanceVars)==1 and setOfAll.instanceElement == setOfAll.instanceVars[0] and setOfAll.domain==self.superset:
                Q_op, Q_op_sub = Operation(Qmulti, setOfAll.instanceVars), setOfAll.conditions
                return comprehensionIsSubset.specialize({S:setOfAll.domain, Q_op:Q_op_sub}, relabelMap={x:setOfAll.instanceVars[0]}, assumptions=assumptions)
        
        # Finally, attempt to conclude A subseteq B via forall_{x in A} x in B.
        # Issue: Variables do not match when using safeDummyVar: _x_ to x.
        # We need to automate this better, right now it is only practical to do concludeAsFolded manually.
        return self.concludeAsFolded(elemInstanceVar=safeDummyVar(self), assumptions=assumptions)
コード例 #16
0
ファイル: sum.py プロジェクト: rmmilewi/Prove-It
 def splitOffFirst(self, assumptions=frozenset()):
     from theorems import sumSplitFirst # only for associative summation
     if isinstance(self.domain, Interval) and len(self.instanceVars) == 1:
         deduceInIntegers(self.domain.lowerBound, assumptions)
         deduceInIntegers(self.domain.upperBound, assumptions)
         # Also needs lowerBound < upperBound
         return sumSplitFirst.specialize({Operation(f, self.instanceVars):self.summand}).specialize({a:self.domain.lowerBound, b:self.domain.upperBound, x:self.indices[0]})
     raise Exception("splitOffLast only implemented for a summation over a Interval of one instance variable")
コード例 #17
0
 def deduceInBool(self, assumptions=USE_DEFAULTS):
     '''
     Deduce, then return, that this exists expression is in the set of BOOLEANS as
     all exists expressions are (they are taken to be false when not true).
     '''
     raise NotImplementedError("Need to update")
     from ._theorems_ import existsInBool
     P_op, P_op_sub = Operation(P, self.instanceVars), self.instanceExpr
     Q_op, Q_op_sub = Operation(Qmulti, self.instanceVars), self.conditions
     return existsInBool.specialize(
         {
             P_op: P_op_sub,
             Q_op: Q_op_sub,
             S: self.domain
         },
         relabelMap={xMulti: self.instanceVars},
         assumptions=assumptions)
コード例 #18
0
 def foldAsForall(self, forallStmt, assumptions=USE_DEFAULTS):
     '''
     Given forall_{A in Booleans} P(A), conclude and return it from 
     [P(TRUE) and P(FALSE)].
     '''
     from proveit.logic import Forall, And
     from ._theorems_ import foldForallOverBool, foldConditionedForallOverBool
     from ._common_ import Booleans
     assert (
         isinstance(forallStmt, Forall)
     ), "May only apply foldAsForall method of Booleans to a forall statement"
     assert (
         forallStmt.domain == Booleans
     ), "May only apply foldAsForall method of Booleans to a forall statement with the Booleans domain"
     if (len(forallStmt.conditions) > 1):
         if len(forallStmt.conditions) == 2:
             condition = forallStmt.conditions[1]
         else:
             condition = And(*forallStmt.conditions[1:])
         Qx = Operation(Q, forallStmt.instanceVar)
         _Qx = condition
         Px = Operation(P, forallStmt.instanceVar)
         _Px = forallStmt.instanceExpr
         _A = forallStmt.instanceVar
         return foldConditionedForallOverBool.instantiate(
             {
                 Qx: _Qx,
                 Px: _Px,
                 A: _A
             },
             num_forall_eliminations=1,
             assumptions=assumptions)
     else:
         # forall_{A in Booleans} P(A), assuming P(TRUE) and P(FALSE)
         Px = Operation(P, forallStmt.instanceVar)
         _Px = forallStmt.instanceExpr
         _A = forallStmt.instanceVar
         return foldForallOverBool.instantiate({
             Px: _Px,
             A: _A
         },
                                               num_forall_eliminations=1,
                                               assumptions=assumptions)
コード例 #19
0
 def fold_as_forall(self, forall_stmt, assumptions=USE_DEFAULTS):
     '''
     Given forall_{A in Boolean} P(A), conclude and return it from
     [P(TRUE) and P(FALSE)].
     '''
     from proveit.logic import Forall, And
     from . import fold_forall_over_bool, fold_conditioned_forall_over_bool
     from . import Boolean
     assert (
         isinstance(forall_stmt, Forall)
     ), "May only apply fold_as_forall method of Boolean to a forall statement"
     assert (
         forall_stmt.domain == Boolean
     ), "May only apply fold_as_forall method of Boolean to a forall statement with the Boolean domain"
     if forall_stmt.conditions.num_entries() > 1:
         if forall_stmt.conditions.is_double():
             condition = forall_stmt.conditions[1]
         else:
             condition = And(*forall_stmt.conditions[1:].entries)
         Qx = Operation(Q, forall_stmt.instance_var)
         _Qx = condition
         Px = Operation(P, forall_stmt.instance_var)
         _Px = forall_stmt.instance_expr
         _A = forall_stmt.instance_var
         return fold_conditioned_forall_over_bool.instantiate(
             {
                 Qx: _Qx,
                 Px: _Px,
                 A: _A
             },
             num_forall_eliminations=1,
             assumptions=assumptions)
     else:
         # forall_{A in Boolean} P(A), assuming P(TRUE) and P(FALSE)
         Px = Operation(P, forall_stmt.instance_param)
         _Px = forall_stmt.instance_expr
         _A = forall_stmt.instance_param
         return fold_forall_over_bool.instantiate({
             Px: _Px,
             A: _A
         },
                                                  num_forall_eliminations=1,
                                                  assumptions=assumptions)
コード例 #20
0
 def unfoldMembership(self, element, assumptions=USE_DEFAULTS):
     '''
     From (x in {y | Q(y)})_{y in S}, derive and return [(x in S) and Q(x)], where x is meant as the given element.
     From (x in {y | ..Q(y)..})_{y in S}, derive and return [(x in S) and ..Q(x)..], where x is meant as the given element.
     From (x in {f(y) | ..Q(y)..})_{y in S}, derive and return exists_{y in S | ..Q(y)..} x = f(y).
     Also derive x in S, but this is not returned.
     '''
     from _theorems_ import unfoldComprehension, unfoldBasicComprehension, unfoldBasic1CondComprehension, inSupersetIfInComprehension
     Q_op, Q_op_sub = Operation(Qmulti, self.instanceVars), self.conditions
     if len(self.instanceVars) == 1 and self.instanceElement == self.instanceVars[0]:
         inSupersetIfInComprehension.specialize({S:self.domain, Q_op:Q_op_sub, x:element}, {y:self.instanceVars[0]}, assumptions=assumptions) # x in S side-effect
         if len(self.conditions) == 1:
             Q_op, Q_op_sub = Operation(Q, self.instanceVars), self.conditions[0]
             return unfoldBasic1CondComprehension.specialize({S:self.domain, Q_op:Q_op_sub, x:element},  {y:self.instanceVars[0]}, assumptions=assumptions)
         else:
             return unfoldBasicComprehension.specialize({S:self.domain, Q_op:Q_op_sub, x:element}, {y:self.instanceVars[0]}, assumptions=assumptions)
     else:
         f_op, f_sub = Operation(f, self.instanceVars), self.instanceElement
         return unfoldComprehension.specialize({S:self.domain,  Q_op:Q_op_sub, f_op:f_sub, x:element}, {yMulti:self.instanceVars}).deriveConclusion(assumptions)
コード例 #21
0
 def elimDomain(self, assumptions=USE_DEFAULTS):
     '''
     From [exists_{x in S | Q(x)} P(x)], derive and return [exists_{x | Q(x)} P(x)],
     eliminating the domain which is a weaker form.
     '''
     raise NotImplementedError("Need to update")
     from ._theorems_ import existsInGeneral
     P_op, P_op_sub = Operation(P, self.instanceVars), self.instanceExpr
     Q_op, Q_op_sub = Operation(Qmulti, self.instanceVars), self.conditions
     return existsInGeneral.specialize(
         {
             P_op: P_op_sub,
             Q_op: Q_op_sub,
             S: self.domain
         },
         assumptions=assumptions,
         relabelMap={
             xMulti: self.instanceVars,
             yMulti: self.instanceVars
         }).deriveConsequent(assumptions)
コード例 #22
0
 def unfoldForall(self, forallStmt, assumptions=USE_DEFAULTS):
     '''
     Given forall_{A in Booleans} P(A), derive and return [P(TRUE) and P(FALSE)].
     '''
     from proveit.logic import Forall
     from ._theorems_ import unfoldForallOverBool
     from ._common_ import Booleans
     assert(isinstance(forallStmt, Forall)), "May only apply unfoldForall method of Booleans to a forall statement"
     assert(forallStmt.domain == Booleans), "May only apply unfoldForall method of Booleans to a forall statement with the Booleans domain"
     assert(len(forallStmt.instanceVars) == 1), "May only apply unfoldForall method of Booleans to a forall statement with 1 instance variable"
     return unfoldForallOverBool.specialize({Operation(P, forallStmt.instanceVars[0]): forallStmt.instanceExpr, A:forallStmt.instanceVars[0]}).deriveConsequent(assumptions)
コード例 #23
0
 def _specializeUnravelingTheorem(self, theorem, *instanceVarLists):
     raise NotImplementedError("Need to update")
     assert len(self.instanceVars) > 1, "Can only unravel a forall statement with multiple instance variables"
     if len(instanceVarLists) == 1:
         raise ValueError("instanceVarLists should be a list of 2 or more Variable lists")
     if len(instanceVarLists) > 2:
         return self.deriveUnraveled(ExprList(instanceVarLists[:-1]), instanceVarLists[-1]).deriveUnraveled(*instanceVarLists[:-1]).checked({self})
     outerVars, innerVars = instanceVarLists
     outerVarSet, innerVarSet = set(outerVars), set(innerVars)
     assert innerVarSet | outerVarSet == set(self.instanceVars), "outerVars and innterVars must combine to the full set of instance variables"
     assert innerVarSet.isdisjoint(outerVarSet), "outerVars and innterVars must be disjoint sets"
     innerConditions = []
     outerConditions = []
     for condition in self.conditions:
         if condition.freeVars().isdisjoint(innerVars):
             outerConditions.append(condition)
         else: innerConditions.append(condition)
     P_op, P_op_sub = Operation(P, self.instanceVars), self.instanceExpr
     Q_op, Q_op_sub = Operation(Qmulti, outerVars), outerConditions
     R_op, R_op_sub = Operation(Rmulti, innerVars), innerConditions
     return theorem.specialize({xMulti:outerVars, yMulti:innerVars, P_op:P_op_sub, Q_op:Q_op_sub, R_op:R_op_sub, S:self.domain}) 
コード例 #24
0
 def concludeViaExample(self, exampleInstance, assumptions=USE_DEFAULTS):
     '''
     Conclude and return this [exists_{..y.. in S | ..Q(..x..)..} P(..y..)] from P(..x..) and Q(..x..) and ..x.. in S, where ..x.. is the given exampleInstance.
     '''
     raise NotImplementedError("Need to update")
     from ._theorems_ import existenceByExample
     from proveit.logic import InSet
     if len(self.instanceVars) > 1 and (
             not isinstance(exampleInstance, ExprList) or
         (len(exampleInstance) != len(self.instanceVars))):
         raise Exception(
             'Number in exampleInstance list must match number of instance variables in the Exists expression'
         )
     P_op, P_op_sub = Operation(P, self.instanceVars), self.instanceExpr
     Q_op, Q_op_sub = Operation(Qmulti, self.instanceVars), self.conditions
     # P(..x..) where ..x.. is the given exampleInstance
     exampleMapping = {
         instanceVar: exampleInstanceElem
         for instanceVar, exampleInstanceElem in zip(
             self.instanceVars, exampleInstance if isinstance(
                 exampleInstance, ExpressionList) else [exampleInstance])
     }
     exampleExpr = self.instanceExpr.substituted(exampleMapping)
     # ..Q(..x..).. where ..x.. is the given exampleInstance
     exampleConditions = self.conditions.substituted(exampleMapping)
     if self.hasDomain():
         for iVar in self.instanceVars:
             exampleConditions.append(InSet(iVar, self.domain))
     # exists_{..y.. | ..Q(..x..)..} P(..y..)]
     return existenceByExample.specialize(
         {
             P_op: P_op_sub,
             Q_op: Q_op_sub,
             S: self.domain
         },
         assumptions=assumptions,
         relabelMap={
             xMulti: exampleInstance,
             yMulti: self.instanceVars
         }).deriveConsequent(assumptions=assumptions)
コード例 #25
0
 def foldAsForall(self, forallStmt, assumptions=USE_DEFAULTS):
     '''
     Given forall_{A in Booleans} P(A), conclude and return it from [P(TRUE) and P(FALSE)].
     '''
     from proveit.logic import Forall
     from ._theorems_ import foldForallOverBool
     from ._common_ import Booleans
     assert(isinstance(forallStmt, Forall)), "May only apply foldAsForall method of Booleans to a forall statement"
     assert(forallStmt.domain == Booleans), "May only apply foldAsForall method of Booleans to a forall statement with the Booleans domain"
     assert(len(forallStmt.explicitConditions())==0), "May only apply foldAsForall method of Booleans to a forall statement with the Booleans domain but no other conditions"
     assert(len(forallStmt.instanceVars) == 1), "May only apply foldAsForall method of Booleans to a forall statement with 1 instance variable"
     # forall_{A in Booleans} P(A), assuming P(TRUE) and P(FALSE)
     return foldForallOverBool.specialize({Operation(P, forallStmt.instanceVars[0]):forallStmt.instanceExpr}, {A:forallStmt.instanceVars[0]})
コード例 #26
0
 def substituteDomain(self, superset, assumptions=USE_DEFAULTS):
     '''
     Substitute the domain with a superset.
     From [exists_{x in A| Q(x)} P(x)], derive and return [exists_{x in B| Q(x)} P(x)]
     given A subseteq B.
     '''
     raise NotImplementedError("Need to update")
     from ._theorems_ import existsInSuperset
     P_op, P_op_sub = Operation(P, self.instanceVars), self.instanceExpr
     Q_op, Q_op_sub = Operation(Qmulti, self.instanceVars), self.conditions
     return existsInSuperset.specialize(
         {
             P_op: P_op_sub,
             Q_op: Q_op_sub,
             A: self.domain,
             B: superset
         },
         assumptions=assumptions,
         relabelMap={
             xMulti: self.instanceVars,
             yMulti: self.instanceVars
         }).deriveConsequent(assumptions)
コード例 #27
0
ファイル: sum.py プロジェクト: rmmilewi/Prove-It
 def shift(self, shiftAmount, assumptions=frozenset()):
     '''
     Shift the summation indices by the shift amount, deducing and returning
     the equivalence of this summation with a index-shifted version.
     '''
     from theorems import indexShift
     if len(self.indices) != 1 or not isinstance(self.domain, Interval):
         raise Exception('Sum shift only implemented for summations with one index over a Interval')
     fOp, fOpSub = Operation(f, self.index), self.summand
     deduceInIntegers(self.domain.lowerBound, assumptions)
     deduceInIntegers(self.domain.upperBound, assumptions)
     deduceInIntegers(shiftAmount, assumptions)
     return indexShift.specialize({fOp:fOpSub, x:self.index}).specialize({a:self.domain.lowerBound, b:self.domain.upperBound, c:shiftAmount})
コード例 #28
0
ファイル: sum.py プロジェクト: rmmilewi/Prove-It
 def factor(self, theFactor, pull="left", groupFactor=False, groupRemainder=None, assumptions=frozenset()):
     '''
     Pull out a common factor from a summation, pulling it either to the "left" or "right".
     If groupFactor is True and theFactor is a product, it will be grouped together as a 
     sub-product.  groupRemainder is not relevant kept for compatibility with other factor
     methods.  Returns the equality that equates self to this new version.
     Give any assumptions necessary to prove that the operands are in Complexes so that
     the associative and commutation theorems are applicable.
     '''
     from proveit.number.multiplication.theorems import distributeThroughSummationRev
     from proveit.number import Mult
     if not theFactor.freeVars().isdisjoint(self.indices):
         raise Exception('Cannot factor anything involving summation indices out of a summation')
     # We may need to factor the summand within the summation
     summand_assumptions = assumptions | {InSet(index, self.domain) for index in self.indices}
     summandFactorEq = self.summand.factor(theFactor, pull, groupFactor=False, groupRemainder=True, assumptions=summand_assumptions)
     summandInstanceEquivalence = summandFactorEq.generalize(self.indices, domain=self.domain).checked(assumptions)
     eq = Equation(self.instanceSubstitution(summandInstanceEquivalence).checked(assumptions))
     factorOperands = theFactor.operands if isinstance(theFactor, Mult) else theFactor
     xDummy, zDummy = self.safeDummyVars(2)
     # Now do the actual factoring by reversing distribution
     if pull == 'left':
         Pop, Pop_sub = Operation(P, self.indices), summandFactorEq.rhs.operands[-1]
         xSub = factorOperands
         zSub = []
     elif pull == 'right':
         Pop, Pop_sub = Operation(P, self.indices), summandFactorEq.rhs.operands[0]
         xSub = []
         zSub = factorOperands
     # We need to deduce that theFactor is in Complexes and that all instances of Pop_sup are in Complexes.
     deduceInComplexes(factorOperands, assumptions=assumptions)
     deduceInComplexes(Pop_sub, assumptions=assumptions | {InSet(idx, self.domain) for idx in self.indices}).generalize(self.indices, domain=self.domain).checked(assumptions)
     # Now we specialize distributThroughSummationRev
     spec1 = distributeThroughSummationRev.specialize({Pop:Pop_sub, S:self.domain, yEtc:self.indices, xEtc:Etcetera(MultiVariable(xDummy)), zEtc:Etcetera(MultiVariable(zDummy))}).checked()
     eq.update(spec1.deriveConclusion().specialize({Etcetera(MultiVariable(xDummy)):xSub, Etcetera(MultiVariable(zDummy)):zSub}))
     if groupFactor and len(factorOperands) > 1:
         eq.update(eq.eqExpr.rhs.group(endIdx=len(factorOperands), assumptions=assumptions))
     return eq.eqExpr #.checked(assumptions)
コード例 #29
0
ファイル: sum.py プロジェクト: rmmilewi/Prove-It
 def simplification(self, assumptions=frozenset()):
     '''
     For the trivial case of summing over only one item (currently implemented just
     for a Interval where the endpoints are equal),
     derive and return this summation expression equated the simplified form of
     the single term.
     Assumptions may be necessary to deduce necessary conditions for the simplification.
     '''
     from axioms import sumSingle
     if isinstance(self.domain, Interval) and self.domain.lowerBound == self.domain.upperBound:
         if len(self.instanceVars) == 1:
             deduceInIntegers(self.domain.lowerBound, assumptions)
             return sumSingle.specialize({Operation(f, self.instanceVars):self.summand}).specialize({a:self.domain.lowerBound})
     raise Exception("Sum simplification only implemented for a summation over a Interval of one instance variable where the upper and lower bound is the same")
コード例 #30
0
 def forallEvaluation(self, forallStmt, assumptions):
     '''
     Given a forall statement over the BOOLEANS domain, evaluate to TRUE or FALSE
     if possible.
     '''        
     from proveit.logic import Forall, Equals, EvaluationError
     from ._theorems_ import falseEqFalse, trueEqTrue 
     from ._theorems_ import forallBoolEvalTrue, forallBoolEvalFalseViaTF, forallBoolEvalFalseViaFF, forallBoolEvalFalseViaFT
     from ._common_ import TRUE, FALSE, Booleans
     from conjunction import compose
     assert(isinstance(forallStmt, Forall)), "May only apply forallEvaluation method of BOOLEANS to a forall statement"
     assert(forallStmt.domain == Booleans), "May only apply forallEvaluation method of BOOLEANS to a forall statement with the BOOLEANS domain"
     assert(len(forallStmt.instanceVars) == 1), "May only apply forallEvaluation method of BOOLEANS to a forall statement with 1 instance variable"
     instanceVar = forallStmt.instanceVars[0]
     instanceExpr = forallStmt.instanceExpr
     P_op = Operation(P, instanceVar)
     trueInstance = instanceExpr.substituted({instanceVar:TRUE})
     falseInstance = instanceExpr.substituted({instanceVar:FALSE})
     if trueInstance == TRUE and falseInstance == FALSE:
         # special case of Forall_{A in BOOLEANS} A
         falseEqFalse # FALSE = FALSE
         trueEqTrue # TRUE = TRUE
         return forallBoolEvalFalseViaTF.specialize({P_op:instanceExpr}).deriveConclusion()
     else:
         # must evaluate for the TRUE and FALSE case separately
         evalTrueInstance = trueInstance.evaluation(assumptions)
         evalFalseInstance = falseInstance.evaluation(assumptions)
         if not isinstance(evalTrueInstance.expr, Equals) or not isinstance(evalFalseInstance.expr, Equals):
             raise EvaluationError('Quantified instances must produce equalities as evaluations')            
         # proper evaluations for both cases (TRUE and FALSE)
         trueCaseVal = evalTrueInstance.rhs
         falseCaseVal = evalFalseInstance.rhs
         if trueCaseVal == TRUE and falseCaseVal == TRUE:
             # both cases are TRUE, so the forall over booleans is TRUE
             compose([evalTrueInstance.deriveViaBooleanEquality(), evalFalseInstance.deriveViaBooleanEquality()], assumptions)
             forallBoolEvalTrue.specialize({P_op:instanceExpr, A:instanceVar})
             return forallBoolEvalTrue.specialize({P_op:instanceExpr, A:instanceVar}, assumptions=assumptions).deriveConclusion(assumptions)
         else:
             # one case is FALSE, so the forall over booleans is FALSE
             compose([evalTrueInstance, evalFalseInstance], assumptions)
             if trueCaseVal == FALSE and falseCaseVal == FALSE:
                 return forallBoolEvalFalseViaFF.specialize({P_op:instanceExpr, A:instanceVar}, assumptions=assumptions).deriveConclusion(assumptions)
             elif trueCaseVal == FALSE and falseCaseVal == TRUE:
                 return forallBoolEvalFalseViaFT.specialize({P_op:instanceExpr, A:instanceVar}, assumptions=assumptions).deriveConclusion(assumptions)
             elif trueCaseVal == TRUE and falseCaseVal == FALSE:
                 return forallBoolEvalFalseViaTF.specialize({P_op:instanceExpr, A:instanceVar}, assumptions=assumptions).deriveConclusion(assumptions)
             else:
                 raise EvaluationError('Quantified instance evaluations must be TRUE or FALSE')