예제 #1
0
파일: magics.py 프로젝트: rmmilewi/Prove-It
 def __init__(self, names, rightSides, beginningProof=False):
     self.beginningProof = beginningProof
     from proveit import singleOrCompositeExpression
     processedRightSides = []
     for rightSide in rightSides:
         if not isinstance(rightSide, KnownTruth):
             try:
                 # try to combine a composite expression if the right side is a
                 # list or dictionary that should convert to an expression.
                 rightSide = singleOrCompositeExpression(rightSide)
             except:
                 pass
         if proveItMagic.kind in ('axioms', 'theorems', 'common'):
             if not isinstance(rightSide, Expression) and (rightSide
                                                           is not None):
                 raise ValueError(
                     "Right hand side of end-of-cell assignment(s) is expected to be Expression(s)"
                 )
         processedRightSides.append(rightSide)
     self.names = list(names)
     self.rightSides = processedRightSides
     for name, rightSide in zip(names, self.rightSides):
         if name in proveItMagic.definitions:
             prev_def = proveItMagic.definitions[name]
             if rightSide != prev_def and isinstance(prev_def, Expression):
                 proveItMagic.expr_names[prev_def].remove(name)
                 if len(proveItMagic.expr_names[prev_def]) == 0:
                     proveItMagic.expr_names.pop(prev_def)
         if rightSide is None:
             # unsetting a defintion
             proveItMagic.lowerCaseNames.remove(name.lower())
             prev_def = proveItMagic.definitions[name]
             proveItMagic.definitions.pop(name)
             proveItMagic.keys.remove(name)
             continue
         if proveItMagic.kind == 'axioms' or proveItMagic.kind == 'theorems':
             if len(rightSide.freeVars()) > 0:
                 raise ValueError(
                     '%s should not have free variables; variables must all be bound (e.g. universally quantified).  Free variables: %s'
                     % (proveItMagic.kind, rightSide.freeVars()))
             if name in proveItMagic.definitions:
                 if proveItMagic.definitions[name] != rightSide:
                     print('WARNING: Redefining', name)
                 proveItMagic.keys.remove(name)
             elif name.lower() in proveItMagic.lowerCaseNames:
                 if not (
                         proveItMagic.ranFinish
                         and name in proveItMagic.definitions
                 ):  # allowed to come back around after it finished once
                     raise ProveItMagicFailure(
                         "%s names must be unique regardless of capitalization"
                         % proveItMagic.kind[:-1])
         proveItMagic.lowerCaseNames.add(name.lower())
         proveItMagic.definitions[name] = rightSide
         if isinstance(rightSide, Expression):
             proveItMagic.expr_names.setdefault(rightSide, []).append(name)
         proveItMagic.keys.append(name)
예제 #2
0
 def __init__(self, operand):
     '''
     Len takes a single operand which should properly be an
     ExprTuple or an expression (such as a variable) that
     represents a tuple.
     '''
     operand = singleOrCompositeExpression(operand)
     if isinstance(operand, ExprTuple):
         # Nest an ExprTuple operand in an extra ExprTuple as
         # a clear indication that Len has a single operand
         # that is an ExprTuple rather than multiple operands.
         operand = ExprTuple(operand)
     # In order to always recognize that Len only takes a single
     # operand, we must wrap it as an ExprTuple with one entry.
     Operation.__init__(self, Len._operator_, operand)
예제 #3
0
    def specialize(self,
                   specializeMap=None,
                   relabelMap=None,
                   assumptions=USE_DEFAULTS):
        '''
        Performs a specialize derivation step to be proven under the given
        assumptions, in addition to the assumptions of the KnownTruth.
        This will eliminate one or more nested Forall operations, specializing
        the instance variables according to specializeMap.  Eliminates
        the number of Forall operations required to utilize all of the
        specializeMap keys.  The default mapping of all instance variables
        is a mapping to itself (e.g., {x:x, y:y}).  Simultaneously, variables 
        may be relabeled via relabelMap (see the relabel method).  Note, there 
        is a difference between  making substitutons simultaneously versus 
        in-series.  For example, the {x:y, y:x} mapping will swap x and y 
        variables, but mapping {x:y} then {y:x} in series would set both 
        variables to x.
        Returns the proven specialized KnownTruth, or throws an exception if the
        proof fails.        
        '''
        from proveit import Operation, Variable, Lambda, singleOrCompositeExpression
        from proveit.logic import Forall
        from .proof import Specialization, SpecializationFailure, ProofFailure

        if not self.isUsable():
            # If this KnownTruth is not usable, see if there is an alternate under the
            # set of assumptions that is usable.
            try:
                alternate = self.expr.prove(assumptions, automation=False)
            except ProofFailure:
                self.raiseUnusableProof()
            return alternate.specialize(specializeMap, relabelMap, assumptions)

        # if no specializeMap is provided, specialize the "explicitInstanceVars" of the Forall with default mappings
        # (mapping instance variables to themselves)
        if specializeMap is None:
            specializeMap = {
                ivar: ivar
                for ivar in self.explicitInstanceVars()
            }
        if relabelMap is None: relabelMap = dict()

        # Include the KnownTruth assumptions along with any provided assumptions
        assumptions = defaults.checkedAssumptions(assumptions)
        assumptions += self.assumptions

        # For any entrys in the subMap with Operation keys, convert
        # them to corresponding operator keys with Lambda substitutions.
        # For example f(x,y):g(x,y) would become f:[(x,y) -> g(x,y)].
        # Convert to composite expressions as needed (via singleOrCompositeExpression).
        processedSubMap = dict()
        for key, sub in specializeMap.items():
            sub = singleOrCompositeExpression(sub)
            if isinstance(key, Operation):
                operation = key
                subVar = operation.operator
                sub = Lambda(operation.operands, sub)
                processedSubMap[subVar] = sub
            elif isinstance(key, Variable):
                processedSubMap[key] = sub
            else:
                raise SpecializationFailure(
                    self, specializeMap, relabelMap, assumptions,
                    'Expecting specializeMap keys to be Variables, MultiVariables, or Operations with Variable/MultiVariable operators; not %s'
                    % str(key.__class__))
        remainingSubVars = set(processedSubMap.keys())

        # Determine the number of Forall eliminations.  There must be at least
        # one (if zero is desired, relabel should be called instead).
        # The number is determined by the instance variables that occur as keys
        # in the subMap.
        expr = self.expr
        numForallEliminations = 0
        while numForallEliminations == 0 or len(remainingSubVars) > 0:
            numForallEliminations += 1
            if not isinstance(expr, Forall):
                raise SpecializationFailure(
                    self, specializeMap, relabelMap, assumptions,
                    'May only specialize instance variables of directly nested Forall operations'
                )
            lambdaExpr = expr.operand
            assert isinstance(
                lambdaExpr,
                Lambda), "Forall Operation operand must be a Lambda function"
            instanceVars, expr, conditions = lambdaExpr.parameterVars, lambdaExpr.body, lambdaExpr.conditions
            for iVar in instanceVars:
                if iVar in remainingSubVars:
                    # remove this instance variable from the remaining substitution variables
                    remainingSubVars.remove(iVar)
                elif iVar not in processedSubMap:
                    # default is to map instance variables to themselves
                    processedSubMap[iVar] = iVar

        return self._checkedTruth(
            Specialization(self,
                           numForallEliminations=numForallEliminations,
                           specializeMap=processedSubMap,
                           relabelMap=relabelMap,
                           assumptions=assumptions))
예제 #4
0
 def __init__(self, names, rightSides, beginningProof=False):
     self.beginningProof = beginningProof
     from proveit import singleOrCompositeExpression
     processedRightSides = []
     for rightSide in rightSides:
         if not isinstance(rightSide, KnownTruth):
             try:
                 # try to combine a composite expression if the right side is a
                 # list or dictionary that should convert to an expression.
                 rightSide = singleOrCompositeExpression(
                         rightSide, wrap_expr_range_in_tuple=False)
             except:
                 pass
         if proveItMagic.kind in ('axioms', 'theorems', 'common'):
             if not isinstance(rightSide, Expression) and (rightSide is not None):
                 # raise ValueError("Right hand side of end-of-cell "
                 #                  "assignment(s) is expected to be "
                 #                  "Expression(s).")
                 raise ValueError("Right hand side of end-of-cell "
                                  "assignment(s) is {}, but is expected to "
                                  "be Expression(s).".format(rightSide))
         processedRightSides.append(rightSide)
     self.names = list(names)
     self.rightSides = processedRightSides
     for name, rightSide in zip(names, self.rightSides):
         if name in proveItMagic.definitions:
             prev_def = proveItMagic.definitions[name]
             if rightSide != prev_def and isinstance(prev_def, Expression):
                 proveItMagic.expr_names[prev_def].remove(name)
                 if len(proveItMagic.expr_names[prev_def]) == 0:
                     proveItMagic.expr_names.pop(prev_def)
         if rightSide is None:
             # unsetting a defintion
             proveItMagic.lowerCaseNames.remove(name.lower())
             prev_def = proveItMagic.definitions[name]
             proveItMagic.definitions.pop(name)
             proveItMagic.keys.remove(name)
             continue
         if proveItMagic.kind == 'axioms' or proveItMagic.kind == 'theorems':
             # Axiom and theorem variables should all be bound
             # though we will only check for variables that are
             # entirely unbound because it would be challenging
             # to consider partially bound instances and it isn't
             # so critical -- it's just a good convention.
             if len(free_vars(rightSide, err_inclusively=False)) > 0:
                 raise ValueError(
                         '%s should not have free variables; variables '
                         'must all be bound (e.g. universally quantified). '
                         ' Free variables: %s'
                         %(proveItMagic.kind, 
                           free_vars(rightSide, err_inclusively=False)))
             if name in proveItMagic.definitions:
                 if proveItMagic.definitions[name] != rightSide:
                     print('WARNING: Redefining', name)
                 proveItMagic.keys.remove(name)
             elif name.lower() in proveItMagic.lowerCaseNames:
                 if not(proveItMagic.ranFinish and name in proveItMagic.definitions): # allowed to come back around after it finished once
                     raise ProveItMagicFailure("%s names must be unique regardless of capitalization"%proveItMagic.kind[:-1])
         proveItMagic.lowerCaseNames.add(name.lower())
         proveItMagic.definitions[name] = rightSide
         if isinstance(rightSide, Expression):
             proveItMagic.expr_names.setdefault(rightSide, []).append(name)
         proveItMagic.keys.append(name)