Exemple #1
0
    def __init__(self, expression, assumptions):
        '''
        Create a KnownTruth with the given Expression, set of assumptions.  These
        should not be created manually but rather through the creation of Proofs which should
        be done indirectly via Expression/KnownTruth derivation-step methods.
        '''
        from proveit._core_.proof import Proof
        # do some type checking
        if not isinstance(expression, Expression):
            raise ValueError(
                'The expression (expr) of a KnownTruth should be an Expression'
            )
        for assumption in assumptions:
            if not isinstance(assumption, Expression):
                raise ValueError('Each assumption should be an Expression')

        # note: these contained expressions are subject to style changes on a KnownTruth instance basis
        self.expr = expression
        # store the assumptions as an ordered list (with the desired order for display)
        # and an unordered set (for convenience when checking whether one set subsumes another).
        self.assumptions = tuple(assumptions)
        self.assumptionsSet = frozenset(assumptions)

        # The meaning data is shared among KnownTruths with the same structure disregarding style
        self._meaningData = meaningData(
            self._generate_unique_rep(lambda expr: hex(expr._meaning_id)))
        if not hasattr(self._meaningData, '_exprProofs'):
            # create or assign the _ExprProofs object for storing all proofs
            # for this KnownTruth's expr (under any set of assumptions).
            if self.expr in _ExprProofs.all_expr_proofs:
                exprProofs = _ExprProofs.all_expr_proofs[self.expr]
            else:
                exprProofs = _ExprProofs(self.expr)
            self._meaningData._exprProofs = exprProofs
            # Initially, _proof is None but will be assigned and updated via _addProof()
            self._meaningData._proof = None

        # The style data is shared among KnownTruths with the same structure and style.
        self._styleData = styleData(
            self._generate_unique_rep(lambda expr: hex(expr._style_id)))

        # establish some parent-child relationships (important in case styles are updated)
        self._styleData.addChild(self, self.expr)
        for assumption in self.assumptions:
            self._styleData.addChild(self, assumption)

        # reference this unchanging data of the unique 'meaning' data
        self._meaning_id = self._meaningData._unique_id
        self._exprProofs = self._meaningData._exprProofs

        self._style_id = self._styleData._unique_id
Exemple #2
0
    def __init__(self,
                 coreInfo,
                 subExpressions=tuple(),
                 styles=dict(),
                 requirements=tuple()):
        '''
        Initialize an expression with the given coreInfo (information relevant at the core Expression-type
        level) which should be a list (or tuple) of strings, and a list (or tuple) of subExpressions.
        "styles" is a dictionary used to indicate how the Expression should be formatted
        when there are different possibilities (e.g. division with '/' or as a fraction).  The meaning
        of the expression is independent of its styles signature.
        The "requirements" are expressions that must be proven to be true in order for the Expression
        to make sense.
        '''
        for coreInfoElem in coreInfo:
            if not isinstance(coreInfoElem, str):
                raise TypeError(
                    'Expecting coreInfo elements to be of string type')
        for subExpression in subExpressions:
            if not isinstance(subExpression, Expression):
                raise TypeError(
                    'Expecting subExpression elements to be of Expression type'
                )

        # note: these contained expressions are subject to style changes on an Expression instance basis
        self._subExpressions = subExpressions

        # The meaning data is shared among Expressions with the same structure disregarding style
        self._meaningData = meaningData(
            self._generate_unique_rep(lambda expr: hex(expr._meaning_id),
                                      coreInfo))
        if not hasattr(self._meaningData, '_coreInfo'):
            # initialize the data of self._meaningData
            self._meaningData._coreInfo = tuple(coreInfo)
            # combine requirements from all sub-expressions
            requirements = sum([
                subExpression.getRequirements()
                for subExpression in subExpressions
            ], tuple()) + requirements
            # Expression requirements are essentially assumptions that need to be proven for the expression to
            # be valid.  Calling "checkAssumptions" will remove repeats and generate proof by assumption for each
            # (which may not be necessary, but does not hurt).
            self._meaningData._requirements = defaults.checkedAssumptions(
                requirements)

        # The style data is shared among Expressions with the same structure and style -- this will contain the 'png' generated on demand.
        self._styleData = styleData(
            self._generate_unique_rep(lambda expr: hex(expr._style_id),
                                      coreInfo, styles))
        if not hasattr(self._meaningData, 'styles'):
            # initialize the data of self._styleData
            self._styleData.styles = dict(
                styles
            )  # formatting style options that don't affect the meaning of the expression

        # reference this unchanging data of the unique 'meaning' data
        self._meaning_id = self._meaningData._unique_id
        self._coreInfo = self._meaningData._coreInfo
        self._requirements = self._meaningData._requirements

        self._style_id = self._styleData._unique_id
        """
        self._styles = dict(styles) # formatting style options that don't affect the meaning of the expression
        # meaning representations and unique ids are independent of style
        self._meaning_rep = 
        self._meaning_id = makeUniqueId(self._meaning_rep)
        # style representations and style ids are dependent of style
        self._style_rep = self._generate_unique_rep(lambda expr : hex(expr._style_id), includeStyle=True)
        self._style_id = makeUniqueId(self._style_rep)
        """
        for subExpression in subExpressions:  # update Expression.parent_expr_map
            self._styleData.addChild(self, subExpression)
Exemple #3
0
    def __init__(self,
                 coreInfo,
                 subExpressions=tuple(),
                 styles=None,
                 requirements=tuple()):
        '''
        Initialize an expression with the given coreInfo (information relevant at the core Expression-type
        level) which should be a list (or tuple) of strings, and a list (or tuple) of subExpressions.
        "styles" is a dictionary used to indicate how the Expression should be formatted
        when there are different possibilities (e.g. division with '/' or as a fraction).  The meaning
        of the expression is independent of its styles signature.
        The "requirements" are expressions that must be proven to be true in order for the Expression
        to make sense.
        '''
        if styles is None: styles = dict()
        for coreInfoElem in coreInfo:
            if not isinstance(coreInfoElem, str):
                raise TypeError(
                    'Expecting coreInfo elements to be of string type')
        for subExpression in subExpressions:
            if not isinstance(subExpression, Expression):
                raise TypeError(
                    'Expecting subExpression elements to be of Expression type'
                )

        # note: these contained expressions are subject to style changes on an Expression instance basis
        self._subExpressions = tuple(subExpressions)

        # check for illegal characters in core-info or styles
        if any(',' in info for info in coreInfo):
            raise ValueError("coreInfo is not allowed to contain a comma.")
        if styles is not None:
            for style in styles.values():
                if not {',', ':', ';'}.isdisjoint(style):
                    raise ValueError(
                        "Styles are not allowed to contain a ',', ':', or ';'.  Just use spaces."
                    )

        # Set and initialize the "meaning data".
        # The meaning data is shared among Expressions with the same
        # structure disregarding style or chosen lambda paramterization.
        if hasattr(self, '_genericExpr') and self._genericExpr is not self:
            # The _genericExpr attribute was already set
            # -- must be a Lambda Expression.
            self._meaningData = self._genericExpr._meaningData
        else:
            object_rep_fn = lambda expr: hex(expr._meaning_id)
            self._meaningData = meaningData(
                self._generate_unique_rep(object_rep_fn, coreInfo))
            if not hasattr(self._meaningData, '_coreInfo'):
                # initialize the data of self._meaningData
                self._meaningData._coreInfo = tuple(coreInfo)
                # combine requirements from all sub-expressions
                requirements = sum([
                    subExpression.getRequirements()
                    for subExpression in subExpressions
                ], tuple()) + requirements
                # Expression requirements are essentially assumptions that need
                # to be proven for the expression to be valid.  Calling
                # "checkAssumptions" will remove repeats and generate proof by
                # assumption for each (which may not be necessary, but does not
                # hurt).
                self._meaningData._requirements = \
                    defaults.checkedAssumptions(requirements)

        # The style data is shared among Expressions with the same structure and style -- this will contain the 'png' generated on demand.
        self._styleData = styleData(
            self._generate_unique_rep(lambda expr: hex(expr._style_id),
                                      coreInfo, styles))
        # initialize the style options
        self._styleData.styles = dict(
            styles
        )  # formatting style options that don't affect the meaning of the expression

        # reference this unchanging data of the unique 'meaning' data
        self._meaning_id = self._meaningData._unique_id
        self._coreInfo = self._meaningData._coreInfo
        self._requirements = self._meaningData._requirements

        self._style_id = self._styleData._unique_id
        """
        self._styles = dict(styles) # formatting style options that don't affect the meaning of the expression
        # meaning representations and unique ids are independent of style
        self._meaning_rep = 
        self._meaning_id = makeUniqueId(self._meaning_rep)
        # style representations and style ids are dependent of style
        self._style_rep = self._generate_unique_rep(lambda expr : hex(expr._style_id), includeStyle=True)
        self._style_id = makeUniqueId(self._style_rep)
        """
        for subExpression in subExpressions:  # update Expression.parent_expr_map
            self._styleData.addChild(self, subExpression)
Exemple #4
0
    def __init__(self, provenTruth, requiredTruths):
        
        '''
        # Uncomment to print useful debugging information when tracking side-effects.
        if not isinstance(self, Theorem) and not isinstance(self, Axiom):
            print "prove", provenTruth.expr
        '''
        
        assert isinstance(provenTruth, KnownTruth)
        for requiredTruth in requiredTruths:
            assert isinstance(requiredTruth, KnownTruth)
        # note: the contained KnownTruth and Proofs are subject to style changes on a Proof instance basis.       
        self.provenTruth = provenTruth 
        self.requiredTruths = tuple(requiredTruths)
                   
        # The meaning data is shared among Proofs with the same structure disregarding style
        self._meaningData = meaningData(self._generate_unique_rep(lambda obj : hex(obj._meaning_id)))
        if not hasattr(self._meaningData, 'requiredProofs'):
            self._meaningData.requiredProofs = [requiredTruth.proof() for requiredTruth in requiredTruths]
            self._meaningData._dependents = set() # meanng data of proofs that directly require this one

            # Is this a usable Proof?  An unusable proof occurs when trying to prove a Theorem
            # that must explicitly presume Theorems that are not fully known in order to
            # avoid circular logic.  They can also be manually introduced via Proof.disable().
            self._meaningData._unusableProof = None # When unusable, this will point to the unusable theorem
                                           # being applied directly or indirectly.
                            
        # The style data is shared among Proofs with the same structure and style.
        self._styleData = styleData(self._generate_unique_rep(lambda obj : hex(obj._style_id)))
        
        # reference this unchanging data of the unique 'meaning' data
        self._meaning_id = self._meaningData._unique_id
                
        # reference this data of the unique 'meaning' data, but note that these
        # are subject to change (as proofs are disabled and as new dependencies are added).
        self.requiredProofs = self._meaningData.requiredProofs
        self._dependents = self._meaningData._dependents
        
        all_required_proofs = self.allRequiredProofs()
        all_required_truths = {required_proof.provenTruth for required_proof in all_required_proofs if required_proof is not self}
        original_proof = self.provenTruth not in all_required_truths
        
        if original_proof:        
            # As long as this is not a useless self-dependent proof (a proof that depends upon
            # a different proof of the same truth which should never actually get used),
            # track the dependencies of required proofs so they can be updated appropriated if there are
            # changes due to proof disabling.
            for requiredProof in self.requiredProofs:
                requiredProof._dependents.add(self)
        
        if not hasattr(self._meaningData, 'numSteps'):
            # determine the number of unique steps required for this proof
            self._meaningData.numSteps = len(all_required_proofs)

        # establish some parent-child relationships (important in case styles are updated)
        self._styleData.addChild(self, self.provenTruth)
        for requiredTruth in self.requiredTruths:
            self._styleData.addChild(self, requiredTruth)
                                
        self._style_id = self._styleData._unique_id
        
        if not original_proof:
            self._meaningData._unusableProof = self # not usable because it is not useful
            assert provenTruth.proof() is not None, "There should have been an 'original' proof"
            return
                                     
        requiringUnusableProof = False
        for requiredProof in self.requiredProofs:
            if not requiredProof.isUsable():
                # Mark proofs as unusable when using an "unusable" theorem 
                # directly or indirectly.  Theorems are marked as unusable 
                # when a proof for some Theorem is being generated as a
                # means to avoid circular logic.
                self._meaningData._unusableProof = requiredProof._meaningData._unusableProof
                # Raise an UnusableProof expection below (after calling _recordBestProof
                # to indicate the proof is unusable).
                requiringUnusableProof = True
                break # it only take one
             
        # if it is a Theorem, set its "usability", avoiding circular logic
        if self.isUsable():
            self._setUsability()
        # this new proof may be the first proof, make an old one obselete, or be born obsolete itself.
        hadPreviousProof = (provenTruth.proof() is not None and provenTruth.isUsable())
        provenTruth._addProof(self)
        if requiringUnusableProof:
            # Raise an UnusableProof exception when an attempt is made 
            # to use an "unusable" theorem directly or indirectly.
            raise UnusableProof(KnownTruth.theoremBeingProven, self._meaningData._unusableProof)
        if provenTruth.proof() is self and self.isUsable(): # don't bother with side effects if this proof was born obsolete or unusable
            # don't bother with side-effects if they have already been processed
            if provenTruth not in KnownTruth.sideeffect_processed: 
                # may derive any side-effects that are obvious consequences arising from this truth:
                provenTruth.deriveSideEffects()