Exemple #1
0
 def relabel(self, relabelMap):
     '''
     Performs a relabeling derivation step, deriving another KnownTruth
     from this KnownTruth, under the same assumptions, with relabeled
     Variables.  A Variable may only be relabeled to a Variable.
     Returns the proven relabeled KnownTruth, or throws an exception if the proof fails.
     '''
     from proveit._core_.proof import Specialization
     return self._checkedTruth(Specialization(self, numForallEliminations=0, relabelMap=relabelMap, assumptions=self.assumptions))
Exemple #2
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))