Exemple #1
0
    def _replaced(self, repl_map, allow_relabeling, assumptions, requirements,
                  equality_repl_requirements):
        '''
        Returns this expression with sub-expressions substituted
        according to the replacement map (repl_map) dictionary.

        When an operater of an Operation is substituted by a Lambda map,
        the operation itself will be substituted with the Lambda map
        applied to the operands.  For example, substituting
        f : (x,y) -> x+y
        on f(a, b) will result in a+b.  When performing operation
        substitution with a range of parameters, the Lambda map
        application will require the number of these parameters
        to equal with the number of corresponding operand elements.
        For example,
        f : (a, b_1, ..., b_n) -> a*b_1 + ... + a*b_n
        n : 3
        applied to f(w, x, y, z) will result in w*x + w*y + w*z provided
        that |(b_1, ..., b_3)| = |(x, y, z)| is proven.
        Assumptions may be needed to prove such requirements.
        Requirements will be appended to the 'requirements' list if one
        is provided.

        There are limitations with respect the Lambda map application involving
        iterated parameters when perfoming operation substitution in order to
        keep derivation rules (i.e., instantiation) simple.  For details,
        see the ExprRange.substituted documentation.
        '''
        from proveit import Lambda, ExprRange

        if len(repl_map) > 0 and (self in repl_map):
            # The full expression is to be substituted.
            return repl_map[self]

        # Perform substitutions for the operator(s) and operand(s).
        subbed_operator = \
            self.operator.replaced(repl_map, allow_relabeling,
                                   assumptions, requirements,
                                   equality_repl_requirements)
        subbed_operands = \
            self.operands.replaced(repl_map, allow_relabeling,
                                   assumptions, requirements,
                                   equality_repl_requirements)

        # Check if the operator is being substituted by a Lambda map in
        # which case we should perform full operation substitution.
        if isinstance(subbed_operator, Lambda):
            # Substitute the entire operation via a Lambda map
            # application.  For example, f(x, y) -> x + y,
            # or g(a, b_1, ..., b_n) -> a * b_1 + ... + a * b_n.

            if isinstance(subbed_operator.body, ExprRange):
                raise ImproperReplacement(
                    self, repl_map,
                    "The function %s cannot be defined using this "
                    "lambda, %s, that has an ExprRange for its body; "
                    "that could lead to tuple length contradictions." %
                    (self.operator, subbed_operator))
            return Lambda._apply(
                subbed_operator.parameters,
                subbed_operator.body,
                *subbed_operands.entries,
                assumptions=assumptions,
                requirements=requirements,
                equality_repl_requirements=equality_repl_requirements)

        # If the operator is a literal operator of
        # an Operation class defined via an "_operator_" class
        # attribute, then create the Operation of that class.
        if subbed_operator in Operation.operation_class_of_operator:
            op_class = Operation.operation_class_of_operator[subbed_operator]
            if op_class != self.__class__:
                # Don't transfer the styles; they may not apply in
                # the same manner in the setting of the new
                # operation.
                subbed_sub_exprs = (subbed_operator, subbed_operands)
                substituted = op_class._checked_make(
                    ['Operation'], sub_expressions=subbed_sub_exprs)
                return substituted._auto_reduced(assumptions, requirements,
                                                 equality_repl_requirements)

        subbed_sub_exprs = (subbed_operator, subbed_operands)
        substituted = self.__class__._checked_make(self._core_info,
                                                   subbed_sub_exprs)
        return substituted._auto_reduced(assumptions, requirements,
                                         equality_repl_requirements)
Exemple #2
0
    def _replaced(self, repl_map, allow_relabeling, assumptions, requirements,
                  equality_repl_requirements):
        '''
        Returns this expression with sub-expressions substituted 
        according to the replacement map (repl_map) dictionary.
        
        When an operater of an Operation is substituted by a Lambda map, 
        the operation itself will be substituted with the Lambda map 
        applied to the operands.  For example, substituting 
        f : (x,y) -> x+y
        on f(a, b) will result in a+b.  When performing operation
        substitution with a range of parameters, the Lambda map 
        application will require the number of these parameters 
        to equal with the number of corresponding operand elements.  
        For example,
        f : (a, b_1, ..., b_n) -> a*b_1 + ... + a*b_n
        n : 3
        applied to f(w, x, y, z) will result in w*x + w*y + w*z provided
        that |(b_1, ..., b_3)| = |(x, y, z)| is proven.
        Assumptions may be needed to prove such requirements.  
        Requirements will be appended to the 'requirements' list if one 
        is provided.
        
        There are limitations with respect the Lambda map application involving
        iterated parameters when perfoming operation substitution in order to
        keep derivation rules (i.e., instantiation) simple.  For details,
        see the ExprRange.substituted documentation.
        '''
        from proveit import (Lambda, singleOrCompositeExpression,
                             compositeExpression, ExprTuple, ExprRange)

        if len(repl_map) > 0 and (self in repl_map):
            # The full expression is to be substituted.
            return repl_map[self]

        # Perform substitutions for the operator(s) and operand(s).
        subbed_operator_or_operators = \
            self.operator_or_operators.replaced(repl_map, allow_relabeling,
                                                assumptions, requirements,
                                                equality_repl_requirements)
        subbed_operand_or_operands = \
            self.operand_or_operands.replaced(repl_map, allow_relabeling,
                                              assumptions, requirements,
                                              equality_repl_requirements)
        subbed_operators = compositeExpression(subbed_operator_or_operators)

        # Check if the operator is being substituted by a Lambda map in
        # which case we should perform full operation substitution.
        if len(subbed_operators) == 1:
            subbed_operator = subbed_operators[0]
            if isinstance(subbed_operator, Lambda):
                # Substitute the entire operation via a Lambda map
                # application.  For example, f(x, y) -> x + y,
                # or g(a, b_1, ..., b_n) -> a * b_1 + ... + a * b_n.

                if isinstance(subbed_operator.body, ExprRange):
                    raise ImproperReplacement(
                        self, repl_map,
                        "The function %s cannot be defined using this "
                        "lambda, %s, that has an ExprRange for its body; "
                        "that could lead to tuple length contradictions." %
                        (self.operator, subbed_operator))
                if len(self.operands)==1 and \
                        not isinstance(self.operands[0], ExprRange):
                    # A single operand case (even if that operand
                    # happens to be a tuple).
                    subbed_operands = [subbed_operand_or_operands]
                else:
                    subbed_operands = subbed_operand_or_operands
                return Lambda._apply(
                    subbed_operator.parameters,
                    subbed_operator.body,
                    *subbed_operands,
                    assumptions=assumptions,
                    requirements=requirements,
                    equality_repl_requirements=equality_repl_requirements)

        had_singular_operand = hasattr(self, 'operand')
        if (had_singular_operand
                and isinstance(subbed_operand_or_operands, ExprTuple)
                and not isinstance(self.operand_or_operands, ExprTuple)):
            # If a singular operand is replaced with an ExprTuple,
            # we must wrap an extra ExprTuple around it to indicate
            # that it is still a singular operand with the operand
            # as the ExprTuple (rather than expanding to multiple
            # operands).
            subbed_operand_or_operands = ExprTuple(subbed_operand_or_operands)
        else:
            # Possibly collapse multiple operands to a single operand
            # via "do_singular_reduction=True".
            subbed_operand_or_operands = singleOrCompositeExpression(
                subbed_operand_or_operands, do_singular_reduction=True)

        # Remake the Expression with substituted operator and/or
        # operands
        if len(subbed_operators) == 1:
            # If it is a single operator that is a literal operator of
            # an Operation class defined via an "_operator_" class
            # attribute, then create the Operation of that class.
            operator = subbed_operators[0]
            if operator in Operation.operationClassOfOperator:
                op_class = Operation.operationClassOfOperator[operator]
                if op_class != self.__class__:
                    # Don't transfer the styles; they may not apply in
                    # the same manner in the setting of the new
                    # operation.
                    subbed_sub_exprs = (operator, subbed_operand_or_operands)
                    substituted = op_class._checked_make(
                        ['Operation'],
                        styles=None,
                        subExpressions=subbed_sub_exprs)
                    return substituted._auto_reduced(
                        assumptions, requirements, equality_repl_requirements)

        subbed_sub_exprs = (subbed_operator_or_operators,
                            subbed_operand_or_operands)
        substituted = self.__class__._checked_make(self._coreInfo,
                                                   self.getStyles(),
                                                   subbed_sub_exprs)
        return substituted._auto_reduced(assumptions, requirements,
                                         equality_repl_requirements)