Beispiel #1
0
def _generate_gate_set_for_arc_prob(target, params, cond_probs):
    # Here we deviate slightly from the original paper, by using Gray coding as described in:
    # [arXiv:1306.3991](https://arxiv.org/abs/1306.3991){:.external}
    #
    # The goal is to reduce the total number of gates, but the math is unchanged.

    graycode = GrayCode(len(params))
    previous_binary = '1' * (2**len(params))

    for notted_binary in graycode.generate_gray():
        # We get the NOT of the code because we want to start with 111...1 so that we don't need
        # to have X gates on all qubits from the begining. This does not change the output and is
        # simply an optimization.
        binary = ''.join('1' if bit == '0' else '0' for bit in notted_binary)

        # TODO(tonybruguier): Further reduce the number of gates in case the prob is 0.0. This
        # would mean skipping a Gray code, so the accounting of the X gates must be done
        # carefully.
        for bit, previous_bit, param in zip(binary, previous_binary, params):
            if bit != previous_bit:
                yield pauli_gates.X(param)

        yield common_gates.ry(_prob_to_angle(cond_probs[int(
            binary, 2)])).on(target).controlled_by(*params)

        previous_binary = binary

    for previous_bit, param in zip(previous_binary, params):
        if previous_bit == '0':
            yield pauli_gates.X(param)
Beispiel #2
0
    def _decompose_outside_control(
        self, control: 'cirq.Qid', near_target: 'cirq.Qid', far_target: 'cirq.Qid'
    ) -> 'cirq.OP_TREE':
        """A decomposition assuming one of the targets is in the middle.

        control: ───T──────@────────@───@────────────@────────────────
                           │        │   │            │
           near: ─X─T──────X─@─T^-1─X─@─X────@─X^0.5─X─@─X^0.5────────
                  │          │        │      │         │
            far: ─@─Y^-0.5─T─X─T──────X─T^-1─X─T^-1────X─S─────X^-0.5─
        """
        a, b, c = control, near_target, far_target

        t = common_gates.T
        sweep_abc = [common_gates.CNOT(a, b), common_gates.CNOT(b, c)]

        yield common_gates.CNOT(c, b)
        yield pauli_gates.Y(c) ** -0.5
        yield t(a), t(b), t(c)
        yield sweep_abc
        yield t(b) ** -1, t(c)
        yield sweep_abc
        yield t(c) ** -1
        yield sweep_abc
        yield t(c) ** -1
        yield pauli_gates.X(b) ** 0.5
        yield sweep_abc
        yield common_gates.S(c)
        yield pauli_gates.X(b) ** 0.5
        yield pauli_gates.X(c) ** -0.5
Beispiel #3
0
    def _decompose_(self, qubits: Sequence['cirq.Qid']) -> 'cirq.OP_TREE':
        if len(self.dense_pauli_string) <= 0:
            return
        any_qubit = qubits[0]
        to_z_ops = op_tree.freeze_op_tree(self._to_z_basis_ops(qubits))
        xor_decomp = tuple(xor_nonlocal_decompose(qubits, any_qubit))
        yield to_z_ops
        yield xor_decomp

        if self.exponent_neg:
            yield pauli_gates.Z(any_qubit)**self.exponent_neg
        if self.exponent_pos:
            yield pauli_gates.X(any_qubit)
            yield pauli_gates.Z(any_qubit)**self.exponent_pos
            yield pauli_gates.X(any_qubit)

        yield protocols.inverse(xor_decomp)
        yield protocols.inverse(to_z_ops)
Beispiel #4
0
    def _decompose_(self) -> op_tree.OP_TREE:
        if len(self.pauli_string) <= 0:
            return
        qubits = self.qubits
        any_qubit = qubits[0]
        to_z_ops = op_tree.freeze_op_tree(self.pauli_string.to_z_basis_ops())
        xor_decomp = tuple(xor_nonlocal_decompose(qubits, any_qubit))
        yield to_z_ops
        yield xor_decomp

        if self.exponent_neg:
            yield pauli_gates.Z(any_qubit)**self.exponent_neg
        if self.exponent_pos:
            yield pauli_gates.X(any_qubit)
            yield pauli_gates.Z(any_qubit)**self.exponent_pos
            yield pauli_gates.X(any_qubit)

        yield protocols.inverse(xor_decomp)
        yield protocols.inverse(to_z_ops)
Beispiel #5
0
    def _decompose_inside_control(self,
                                  target1: raw_types.QubitId,
                                  control: raw_types.QubitId,
                                  target2: raw_types.QubitId
                                  ) -> op_tree.OP_TREE:
        """A decomposition assuming the control separates the targets.

        target1: ─@─X───────T──────@────────@─────────X───@─────X^-0.5─
                  │ │              │        │         │   │
        control: ─X─@─X─────@─T^-1─X─@─T────X─@─X^0.5─@─@─X─@──────────
                      │     │        │        │         │   │
        target2: ─────@─H─T─X─T──────X─T^-1───X─T^-1────X───X─H─S^-1───
        """
        a, b, c = target1, control, target2
        yield common_gates.CNOT(a, b)
        yield common_gates.CNOT(b, a)
        yield common_gates.CNOT(c, b)
        yield common_gates.H(c)
        yield common_gates.T(c)
        yield common_gates.CNOT(b, c)
        yield common_gates.T(a)
        yield common_gates.T(b)**-1
        yield common_gates.T(c)
        yield common_gates.CNOT(a, b)
        yield common_gates.CNOT(b, c)
        yield common_gates.T(b)
        yield common_gates.T(c)**-1
        yield common_gates.CNOT(a, b)
        yield common_gates.CNOT(b, c)
        yield pauli_gates.X(b)**0.5
        yield common_gates.T(c)**-1
        yield common_gates.CNOT(b, a)
        yield common_gates.CNOT(b, c)
        yield common_gates.CNOT(a, b)
        yield common_gates.CNOT(b, c)
        yield common_gates.H(c)
        yield common_gates.S(c)**-1
        yield pauli_gates.X(a)**-0.5
Beispiel #6
0
    def _decompose_inside_control(
        self, target1: 'cirq.Qid', control: 'cirq.Qid', target2: 'cirq.Qid'
    ) -> 'cirq.OP_TREE':
        """A decomposition assuming the control separates the targets.

        target1: ─@─X───────T──────@────────@─────────X───@─────X^-0.5─
                  │ │              │        │         │   │
        control: ─X─@─X─────@─T^-1─X─@─T────X─@─X^0.5─@─@─X─@──────────
                      │     │        │        │         │   │
        target2: ─────@─H─T─X─T──────X─T^-1───X─T^-1────X───X─H─S^-1───
        """
        a, b, c = target1, control, target2
        yield common_gates.CNOT(a, b)
        yield common_gates.CNOT(b, a)
        yield common_gates.CNOT(c, b)
        yield common_gates.H(c)
        yield common_gates.T(c)
        yield common_gates.CNOT(b, c)
        yield common_gates.T(a)
        yield common_gates.T(b) ** -1
        yield common_gates.T(c)
        yield common_gates.CNOT(a, b)
        yield common_gates.CNOT(b, c)
        yield common_gates.T(b)
        yield common_gates.T(c) ** -1
        yield common_gates.CNOT(a, b)
        yield common_gates.CNOT(b, c)
        yield pauli_gates.X(b) ** 0.5
        yield common_gates.T(c) ** -1
        yield common_gates.CNOT(b, a)
        yield common_gates.CNOT(b, c)
        yield common_gates.CNOT(a, b)
        yield common_gates.CNOT(b, c)
        yield common_gates.H(c)
        yield common_gates.S(c) ** -1
        yield pauli_gates.X(a) ** -0.5
Beispiel #7
0
    def __pow__(self, exponent: int) -> 'LinearCombinationOfOperations':
        if not isinstance(exponent, int):
            return NotImplemented
        if exponent < 0:
            return NotImplemented
        if len(self.qubits) != 1:
            return NotImplemented
        qubit = self.qubits[0]
        i = identity.I(qubit)
        x = pauli_gates.X(qubit)
        y = pauli_gates.Y(qubit)
        z = pauli_gates.Z(qubit)
        pauli_basis = {i, x, y, z}
        if not set(self.keys()).issubset(pauli_basis):
            return NotImplemented

        ai, ax, ay, az = self[i], self[x], self[y], self[z]
        bi, bx, by, bz = operator_spaces.pow_pauli_combination(ai, ax, ay, az, exponent)
        return LinearCombinationOfOperations({i: bi, x: bx, y: by, z: bz})