Exemple #1
0
    def derive_quantification(self, instance_param=None, **defaults_config):
        '''
        From P(i) and ... and P(j), represented as a single ExprRange
        in a conjunction, prove 
        forall_{k in {i .. j}} P(k).
        If 'instance_param' is provided, use it as the 'k' parameter.
        Otherwise, use the parameter of the ExprRange.
        '''
        from proveit import ExprRange
        from proveit.logic import InSet
        from proveit.numbers import Interval
        from . import quantification_from_conjunction
        if (self.operands.num_entries() != 1
                or not isinstance(self.operands[0], ExprRange)):
            raise ValueError("'derive_quantification' may only be used "
                             "on a conjunction with a single ExprRange "
                             "operand entry.")
        expr_range = self.operands[0]
        _i = expr_range.true_start_index
        _j = expr_range.true_end_index
        _k = expr_range.parameter if instance_param is None else instance_param
        _P = expr_range.lambda_map
        proven_quantification = quantification_from_conjunction.instantiate(
            {
                i: _i,
                j: _j,
                k: _k,
                P: _P
            }, preserve_expr=self).derive_consequent()

        if defaults.automation:
            # While we are at it, as an "unofficial" side-effect,
            # let's instantatiate forall_{k in {i .. j}} P(k) to derive
            # {k in {i .. j}} |- P(k)
            # and induce side-effects for P(k).
            assumptions = defaults.assumptions + (InSet(_k, Interval(_i,
                                                                     _j)), )
            proven_quantification.instantiate(assumptions=assumptions)
            # We'll do it with the canonical variable as well for good
            # measure, if it is any different.
            canonical_version = proven_quantification.canonical_version()
            if canonical_version._style_id != proven_quantification._style_id:
                _k = canonical_version.instance_var
                assumptions = defaults.assumptions + (InSet(
                    _k, Interval(_i, _j)), )
                canonical_version.instantiate(assumptions=assumptions)

        return proven_quantification
Exemple #2
0
 def shallow_simplification(self, *, must_evaluate=False,
                            **defaults_config):
     '''
     Returns a proven simplification equation for this Mod
     expression assuming the operands have been simplified.
     
     Specifically, performs reductions of the form
     (x mod L) = x where applicable and
     [(a mod L + b) mod L] = [(a + b) mod L].
     '''
     from . import (int_mod_elimination, real_mod_elimination,
                    redundant_mod_elimination, 
                    redundant_mod_elimination_in_sum)
     from proveit.numbers import (
         NaturalPos, RealPos, Interval, IntervalCO, subtract, zero, one)
     deduce_number_set(self.dividend)
     divisor_ns = deduce_number_set(self.divisor).domain
     if (NaturalPos.includes(divisor_ns) and 
             InSet(self.dividend, 
                   Interval(zero, 
                            subtract(self.divisor, one))).proven()):
         # (x mod L) = x if L in N+ and x in {0 .. L-1}
         return int_mod_elimination.instantiate(
             {x:self.dividend, L:self.divisor})
     if (RealPos.includes(divisor_ns) and 
             InSet(self.dividend, 
                   IntervalCO(zero, self.divisor)).proven()):
         # (x mod L) = x if L in R+ and x in [0, L)
         return real_mod_elimination.instantiate(
             {x:self.dividend, L:self.divisor})
     return Mod._redundant_mod_elimination(
             self, redundant_mod_elimination, 
             redundant_mod_elimination_in_sum)
def multi_elem_entries(element_from_part,
                       start_qubit_idx,
                       end_qubit_idx,
                       *part_start_and_ends,
                       check_part_index_span=True):
    '''
    Yield consecutive vertical entries for MultiQubitElem to 
    represent all parts of a multi-qubit operation in a quantum circuit
    involving all qubits from 'start_qubit_idx' to 'end_qubit_idx.
    There will be an entry for each "part" start/end pair of indices.
    In total, these must start from one, be consecutive, and cover the 
    range from the 'start_qubit_idx' to the 'end_qubit_idx.
    The element_from_part function must return an element corresponding
    to a given 'part'.
    '''
    targets = Interval(start_qubit_idx, end_qubit_idx)
    multi_qubit_gate_from_part = (
        lambda part: MultiQubitElem(element_from_part(part), targets))
    part = one
    if len(part_start_and_ends) == 0:
        raise ValueError("Must specify one or more 'part' start and end "
                         "indices, starting from one and covering the range "
                         "from %s to %s" % (start_qubit_idx, end_qubit_idx))
    for part_start, part_end in part_start_and_ends:
        #try:
        #    Equals(part, part_start).prove()
        #except ProofFailure:
        if part != part_start:
            raise ValueError("Part indices must be provably consecutive "
                             "starting from 1: %s ≠ %s" % (part_start, part))
        if part_start == part_end:  # just a single element
            yield multi_qubit_gate_from_part(part)
        else:
            param = safe_dummy_var()
            yield ExprRange(param, multi_qubit_gate_from_part(param),
                            part_start, part_end)
        part = Add(part_end, one).quick_simplified()
    if not check_part_index_span:
        lhs = Add(part_end, num(-1)).quick_simplified()
        rhs = Add(end_qubit_idx, Neg(start_qubit_idx)).quick_simplified()
        try:
            try:
                lhs = lhs.simplified()
            except:
                pass
            try:
                rhs = rhs.simplified()
            except:
                pass
            Equals(lhs, rhs).prove()
        except ProofFailure:
            raise ValueError("Part indices must span the range of the "
                             "multi qubit operation: %s ≠ %s" % (lhs, rhs))
Exemple #4
0
    def known_vec_spaces(vecs, *, field=None):
        '''
        Return the known vector spaces of the given vecs under the
        specified field (or the default field).
        '''
        # Effort to appropriately handle an ExprRange operand added
        # here by wdc and ww on 1/3/2022.
        vec_spaces = []
        for vec in vecs:
            if isinstance(vec, ExprRange):
                # create our expr range
                with defaults.temporary() as tmp_defaults:
                    assumption = InSet(vec.parameter,
                            Interval(vec.true_start_index, vec.true_end_index))
                    tmp_defaults.assumptions = (
                            defaults.assumptions + (assumption ,))
                    body = VecSpaces.known_vec_space(vec.body, field=field)
                vec_spaces.append(
                    ExprRange(vec.parameter, body,
                              vec.true_start_index, vec.true_end_index))
            else:
                vec_spaces.append(VecSpaces.known_vec_space(vec, field=field))

        return vec_spaces
int_within_complex

in_natural_if_non_neg = Forall(a,
                               InSet(a, Natural),
                               domain=Integer,
                               conditions=[GreaterThanEquals(a, zero)])
in_natural_if_non_neg

in_natural_pos_if_pos = Forall(a,
                               InSet(a, NaturalPos),
                               domain=Integer,
                               conditions=[GreaterThan(a, zero)])
in_natural_pos_if_pos

interval_is_int = Forall((a, b),
                         Forall(n, InSet(n, Integer), domain=Interval(a, b)),
                         domain=Integer)
interval_is_int

interval_is_nat = Forall((a, b),
                         Forall(n, InSet(n, Natural), domain=Interval(a, b)),
                         domain=Natural)
interval_is_nat

interval_in_nat_pos = Forall((a, b),
                             Forall(n,
                                    InSet(n, NaturalPos),
                                    domain=Interval(a, b)),
                             domain=Integer,
                             conditions=[GreaterThan(a, zero)])
interval_in_nat_pos
Exemple #6
0
from proveit.logic import Forall, InSet, Equals, NotEquals, Iff, And, SetOfAll
from proveit.numbers import Integer, Interval, Real, RealPos, Complex
from proveit.numbers import Abs, Mod, ModAbs, GreaterThanEquals, LessThanEquals, Add, Sub, Neg, Mult, frac, IntervalCO
from proveit.common import a, b, c, x, y, N, x_etc, x_multi
from proveit.numbers.common import zero, one
from proveit import begin_theorems, end_theorems

begin_theorems(locals())

# transferred by wdc 3/11/2020
mod_int_closure = Forall((a, b), InSet(Mod(a, b), Integer), domain=Integer)
mod_int_closure

# transferred by wdc 3/11/2020
mod_in_interval = Forall((a, b), InSet(
    Mod(a, b), Interval(zero, Sub(b, one))), domain=Integer)
mod_in_interval

# transferred by wdc 3/11/2020
mod_real_closure = Forall((a, b), InSet(Mod(a, b), Real), domain=Real)
mod_real_closure

# transferred by wdc 3/11/2020
mod_abs_real_closure = Forall((a, b), InSet(ModAbs(a, b), Real), domain=Real)
mod_abs_real_closure

# transferred by wdc 3/11/2020
abs_complex_closure = Forall([a], InSet(Abs(a), Real), domain=Complex)
abs_complex_closure

# transferred by wdc 3/11/2020
Exemple #7
0
m_ = Literal(pkg, 'm')

# phase_m: Random variable for the phase result of the quantum phase estimation.
#          phase_m = m / 2^t
phase_m_ = Literal(pkg, 'phase_m', {LATEX: r'\varphi_m'})

# b: The "best" outcome of m such that phase_m is as close as possible to
# phase.
b_ = Literal(pkg, 'b')

# 2^t
two_pow_t = Exp(two, t_)

# 2^{t-1}
two_pow_t_minus_one = Exp(two, Sub(t_, one))

# amplitude of output register as indexted
alpha_ = Literal(pkg, 'alpha', {STRING: 'alpha', LATEX: r'\alpha'})
alpha_l = SubIndexed(alpha_, l)
abs_alpha_l = Abs(alpha_l)
alpha_l_sqrd = Exp(Abs(alpha_l), two)

# delta: difference between the phase and the best phase_m
delta_ = Literal(pkg, 'delta', {LATEX: r'\delta'})

full_domain = Interval(Add(Neg(Exp(two, Sub(t_, one))), one),
                       Exp(two, Sub(t_, one)))
neg_domain = Interval(Add(Neg(two_pow_t_minus_one), one), Neg(Add(eps, one)))
pos_domain = Interval(Add(eps, one), two_pow_t_minus_one)
eps_domain = Interval(one, Sub(two_pow_t_minus_one, two))
from proveit.logic import Forall, Equals
from proveit.numbers import Sum, Integer, Interval, LessThan, Add, Sub
from proveit.common import a, b, f, x, fa, fb, fx
from proveit.numbers.common import one
from proveit import begin_axioms, end_axioms

begin_axioms(locals())

sum_single = Forall(f, Forall(a,
                              Equals(Sum(x, fx, Interval(a, a)),
                                     fa),
                              domain=Integer))
sum_single

sum_split_last = Forall(f,
                        Forall([a, b],
                               Equals(Sum(x, fx, Interval(a, b)),
                                      Add(Sum(x, fx, Interval(a, Sub(b, one))),
                                          fb)),
                               domain=Integer, conditions=[LessThan(a, b)]))
sum_split_last


end_axioms(locals(), __package__)