Exemple #1
0
 def _lambda_expr(lambda_map,
                  expr_being_replaced,
                  assumptions=USE_DEFAULTS):
     from proveit import ExprRange, InnerExpr
     if isinstance(lambda_map, InnerExpr):
         lambda_map = lambda_map.repl_lambda()
     if not isinstance(lambda_map, Lambda):
         # as a default, do a global replacement
         lambda_map = Lambda.global_repl(lambda_map, expr_being_replaced)
     if lambda_map.parameters.num_entries() != 1:
         raise ValueError("When substituting, expecting a single "
                          "'lambda_map' parameter entry which may "
                          "be a single parameter or a range; got "
                          "%s as 'lambda_map'" % lambda_map)
     if isinstance(lambda_map.parameters[0], ExprRange):
         from proveit.numbers import one
         if lambda_map.parameters[0].start_index != one:
             raise ValueError("When substituting a range, expecting "
                              "the 'lambda_map' parameter range to "
                              "have a starting index of 1; got "
                              "%s as 'lambda_map'" % lambda_map)
     return lambda_map
Exemple #2
0
def reduce_operands(inner_expr,
                    in_place=True,
                    must_evaluate=False,
                    assumptions=USE_DEFAULTS):
    '''
    Attempt to return an InnerExpr object that is provably equivalent to
    the given inner_expr but with simplified operands at the
    inner-expression level.
    If in_place is True, the top-level expression must be a Judgment
    and the simplified Judgment is derived instead of an equivalence
    relation.
    If must_evaluate is True, the simplified
    operands must be irreducible values (see is_irreducible_value).
    '''
    # Any of the operands that can be simplified must be replaced with
    # their simplification.
    from proveit import InnerExpr, ExprRange
    assert isinstance(inner_expr, InnerExpr), \
        "Expecting 'inner_expr' to be of type 'InnerExpr'"
    inner = inner_expr.expr_hierarchy[-1]
    substitutions = []
    while True:
        all_reduced = True
        for operand in inner.operands:
            if (not is_irreducible_value(operand)
                    and not isinstance(operand, ExprRange)):
                # The operand isn't already irreducible, so try to
                # simplify it.
                if must_evaluate:
                    operand_eval = operand.evaluation(assumptions=assumptions)
                else:
                    operand_eval = operand.simplification(
                        assumptions=assumptions)
                if must_evaluate and not is_irreducible_value(
                        operand_eval.rhs):
                    msg = 'Evaluations expected to be irreducible values'
                    raise EvaluationError(msg, assumptions)
                if operand_eval.lhs != operand_eval.rhs:
                    # Compose map to replace all instances of the
                    # operand within the inner expression.
                    global_repl = Lambda.global_repl(inner, operand)
                    lambda_map = inner_expr.repl_lambda().compose(global_repl)
                    # substitute in the evaluated value
                    if in_place:
                        subbed = operand_eval.sub_right_side_into(lambda_map)
                        inner_expr = InnerExpr(subbed,
                                               inner_expr.inner_expr_path)
                    else:
                        sub = operand_eval.substitution(lambda_map)
                        inner_expr = InnerExpr(sub.rhs,
                                               inner_expr.inner_expr_path)
                        substitutions.append(sub)
                    all_reduced = False
                    # Start over since there may have been multiple
                    # substitutions:
                    break
        if all_reduced:
            break  # done!
        inner = inner_expr.expr_hierarchy[-1]

    if not in_place and len(substitutions) > 1:
        # When there have been multiple substitutions, apply
        # transtivity over the chain of substitutions to equate the
        # end-points.
        Equals.apply_transitivities(substitutions, assumptions)
    return inner_expr
Exemple #3
0
    def _sub_one_side_into(self, prob_relation_or_inner_expr, *, which_side,
                           **defaults_config):
        '''
        Helper method for sub_[left/right]_side_into.
        '''
        from . import lhs_prob_via_equiv, rhs_prob_via_equiv
        equiv = self
        if which_side == 'left':
            thm = lhs_prob_via_equiv
            orig_circuit = equiv.rhs
        elif which_side == 'right':
            thm = rhs_prob_via_equiv
            orig_circuit = equiv.lhs
        else:
            raise ValueError("'which_side' must either be 'left' or 'right'")
        if isinstance(prob_relation_or_inner_expr, Judgment):
            prob_relation_or_inner_expr = prob_relation_or_inner_expr.expr
        if isinstance(prob_relation_or_inner_expr, InnerExpr):
            # This should be an inner expresion of a probability
            # over a quantum circuit.
            inner_expr = prob_relation_or_inner_expr
            expr_hierarchy = inner_expr.expr_hierarchy
            for _k, _expr in enumerate(reversed(expr_hierarchy)):
                circuit_or_lambda_map = None
                if isinstance(_expr, Prob) and isinstance(
                        _expr.operand, Qcircuit):
                    if _k == 2:
                        # Just a quantum circuit in a probability
                        circuit_or_lambda_map = _expr.operand
                    else:
                        # A portion of a quantum circuit.
                        circuit_or_lambda_map = InnerExpr(
                            _expr, inner_expr.inner_expr_path[-_k + 2:])
                    prob_relation_lambda = InnerExpr(
                        expr_hierarchy[0],
                        inner_expr.inner_expr_path[:-_k]).repl_lambda()
                    break
            if circuit_or_lambda_map is None:
                raise NotImplementedError(
                    "Qcircuit.sub_[left/right]_side_into only "
                    "implemented to apply to an inner expr within "
                    "a Prob on a Qcircuit")
            if circuit_or_lambda_map != orig_circuit:
                # Not a direct probability substitution.
                if which_side == 'left':
                    equiv = equiv.derive_reversed()
                    thm = rhs_prob_via_equiv
                equiv = equiv.substitution(circuit_or_lambda_map)
        else:
            # prob_relation_or_inner_expr should be a probability
            # relation (it isn't an InnerExpr).
            prob_relation = prob_relation_or_inner_expr
            qcircuit = Qcircuit._extract_circuit_from_prob_relation(
                prob_relation)
            if qcircuit != orig_circuit:
                # Let's see if orig_circuit is a portion of qcircuit:
                if which_side == 'left':
                    equiv = self.derive_reversed().substitution(qcircuit)
                    thm = rhs_prob_via_equiv
                else:
                    equiv = self.substitution(qcircuit)
            prob_relation_lambda = Lambda.global_repl(prob_relation,
                                                      Prob(qcircuit))

        # Prove the probability relation.
        return thm.instantiate({
            Q: prob_relation_lambda,
            A: equiv.lhs,
            B: equiv.rhs
        })