def call_method_with_known_truth_assumptions(*args, **kwargs): if len(args) > assumptionsIndex: args = list(args) assumptions = args[assumptionsIndex] assumptions = defaults.checkedAssumptions(assumptions) assumptions += self.assumptions args[assumptionsIndex] = defaults.checkedAssumptions(assumptions) else: assumptions = kwargs.get('assumptions', USE_DEFAULTS) assumptions = defaults.checkedAssumptions(assumptions) assumptions = tuple(assumptions) + self.assumptions kwargs['assumptions'] = defaults.checkedAssumptions(assumptions) return attr.__call__(*args, **kwargs)
def __init__(self, implicationExpr, assumptions=None): from proveit.logic import Implies assumptions = defaults.checkedAssumptions(assumptions) prev_default_assumptions = defaults.assumptions defaults.assumptions = assumptions # these assumptions will be used for deriving any side-effects try: # obtain the implication and antecedent KnownTruths assert isinstance(implicationExpr, Implies) and len(implicationExpr.operands)==2, 'The implication of a modus ponens proof must refer to an Implies expression with two operands' try: # Must prove the implication under the given assumptions. # (if WILDCARD_ASSUMPTIONS is included, it will be proven by assumption if there isn't an existing proof otherwise) implicationTruth = implicationExpr.prove(assumptions) _appendExtraAssumptions(assumptions, implicationTruth) except: raise ModusPonensFailure(implicationExpr.operands[1], assumptions, 'Implication, %s, is not proven'%str(implicationExpr)) try: # Must prove the antecedent under the given assumptions. # (if WILDCARD_ASSUMPTIONS is included, it will be proven by assumption if there isn't an existing proof otherwise) antecedentTruth = implicationExpr.operands[0].prove(assumptions) _appendExtraAssumptions(assumptions, antecedentTruth) except: raise ModusPonensFailure(implicationExpr.operands[1], assumptions, 'Antecedent of %s is not proven'%str(implicationExpr)) # remove any unnecessary assumptions (but keep the order that was provided) assumptionsSet = implicationTruth.assumptionsSet | antecedentTruth.assumptionsSet assumptions = [assumption for assumption in assumptions if assumption in assumptionsSet] # we have what we need; set up the ModusPonens Proof consequentTruth = KnownTruth(implicationExpr.operands[1], assumptions, self) _checkImplication(implicationTruth.expr, antecedentTruth.expr, consequentTruth.expr) self.implicationTruth = implicationTruth self.antecedentTruth = antecedentTruth Proof.__init__(self, consequentTruth, [self.implicationTruth, self.antecedentTruth]) finally: # restore the original default assumptions defaults.assumptions = prev_default_assumptions
def __init__(self, expr, assumptions=None): assumptions = defaults.checkedAssumptions(assumptions) if expr not in assumptions: # an Assumption proof must assume itself; that's what it does. assumptions = assumptions + (expr,) prev_default_assumptions = defaults.assumptions defaults.assumptions = assumptions # these assumptions will be used for deriving any side-effects try: Proof.__init__(self, KnownTruth(expr, {expr}, self), []) finally: # restore the original default assumptions defaults.assumptions = prev_default_assumptions Assumption.allAssumptions[(expr, assumptions)] = self
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 a single Forall with default mappings (mapping instance variables to themselves) if specializeMap is None: specializeMap = dict() 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.iteritems(): 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(None, 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(None, 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))
def __init__(self, generalTruth, numForallEliminations, specializeMap=None, relabelMap=None, assumptions=USE_DEFAULTS): ''' Create the Specialization proof step that specializes the given general expression using the substitution map (subMap) under the given assumptions. Eliminates the number of nested Forall operations as indicated, substituting their instance variables according to subMap. The default for any unspecified instance variable is to specialize it to itself, or, in the case of a bundled variable (Etcetera-wrapped MultiVariables), the default is to specialize it to an empty list. Substitution of variables that are not instance variables of the Forall operations being eliminated are to be relabeled. Relabeling is limited to substituting a Variable to another Variable or substituting a bundled variable to another bundled variable or list of variables (bundled or not). ''' assumptions = list(defaults.checkedAssumptions(assumptions)) prev_default_assumptions = defaults.assumptions defaults.assumptions = assumptions # these assumptions will be used for deriving any side-effects try: if relabelMap is None: relabelMap = dict() if specializeMap is None: specializeMap = dict() Failure = SpecializationFailure if numForallEliminations>0 else RelabelingFailure if not isinstance(generalTruth, KnownTruth): raise Failure(None, [], 'May only specialize/relabel a KnownTruth') if generalTruth.proof() is None: raise UnusableProof(KnownTruth.theoremBeingProven, generalTruth) if not generalTruth.assumptionsSet.issubset(assumptions): if '*' in assumptions: # if WILDCARD_ASSUMPTIONS is included, add any extra assumptions that are needed _appendExtraAssumptions(assumptions, generalTruth) else: raise Failure(None, [], 'Assumptions do not include the assumptions required by generalTruth') generalExpr = generalTruth.expr # perform the appropriate substitution/relabeling specializedExpr, requirements, mappedVarLists, mappings = Specialization._specialized_expr(generalExpr, numForallEliminations, specializeMap, relabelMap, assumptions) # obtain the KnownTruths for the substituted conditions requirementTruths = [] requirementTruthSet = set() # avoid repeats of requirements for requirementExpr in requirements: try: # each substituted condition must be proven under the assumptions # (if WILDCARD_ASSUMPTIONS is included, it will be proven by assumption if there isn't an existing proof otherwise) requirementTruth = requirementExpr.prove(assumptions) if requirementTruth not in requirementTruthSet: requirementTruths.append(requirementTruth) requirementTruthSet.add(requirementTruth) _appendExtraAssumptions(assumptions, requirementTruth) except: raise Failure(specializedExpr, assumptions, 'Unmet specialization requirement: ' + str(requirementExpr)) # remove any unnecessary assumptions (but keep the order that was provided) assumptionsSet = generalTruth.assumptionsSet for requirementTruth in requirementTruths: assumptionsSet |= requirementTruth.assumptionsSet assumptions = [assumption for assumption in assumptions if assumption in assumptionsSet] # we have what we need; set up the Specialization Proof self.generalTruth = generalTruth self.requirementTruths = requirementTruths self.mappedVarLists = mappedVarLists self.mappings = mappings specializedTruth = KnownTruth(specializedExpr, assumptions, self) Proof.__init__(self, specializedTruth, [generalTruth] + requirementTruths) finally: # restore the original default assumptions defaults.assumptions = prev_default_assumptions