Esempio n. 1
0
def test_unitary(n):
    diagonal_angles = _candidate_angles[: 2 ** n]
    assert cirq.has_unitary(cirq.DiagonalGate(diagonal_angles))
    np.testing.assert_allclose(
        cirq.unitary(cirq.DiagonalGate(diagonal_angles)).diagonal(),
        [np.exp(1j * angle) for angle in diagonal_angles],
        atol=1e-8,
    )
Esempio n. 2
0
def test_diagonal_exponent(n):
    diagonal_angles = _candidate_angles[: 2 ** n]
    diagonal_gate = cirq.DiagonalGate(diagonal_angles)

    sqrt_diagonal_gate = diagonal_gate ** 0.5

    expected_angles = [prime / 2 for prime in diagonal_angles]
    np.testing.assert_allclose(expected_angles, sqrt_diagonal_gate._diag_angles_radians, atol=1e-8)

    assert cirq.pow(cirq.DiagonalGate(diagonal_angles), "test", None) is None
Esempio n. 3
0
def test_resolve(resolve_fn):
    diagonal_angles = [2, 3, 5, 7, 11, 13, 17, 19]
    diagonal_gate = cirq.DiagonalGate(diagonal_angles[:6] + [sympy.Symbol('a'), sympy.Symbol('b')])
    assert cirq.is_parameterized(diagonal_gate)

    diagonal_gate = resolve_fn(diagonal_gate, {'a': 17})
    assert diagonal_gate == cirq.DiagonalGate(diagonal_angles[:7] + [sympy.Symbol('b')])
    assert cirq.is_parameterized(diagonal_gate)

    diagonal_gate = resolve_fn(diagonal_gate, {'b': 19})
    assert diagonal_gate == cirq.DiagonalGate(diagonal_angles)
    assert not cirq.is_parameterized(diagonal_gate)
Esempio n. 4
0
def test_decomposition_with_parameterization():
    diagonal_gate = cirq.DiagonalGate([2, 3, 5, sympy.Symbol('a')])
    op = diagonal_gate(*cirq.LineQubit.range(2))

    # We do not support the decomposition of parameterized case yet.
    # So cirq.decompose should do nothing.
    assert cirq.decompose(op) == [op]
Esempio n. 5
0
def random_diagonal_gates(
    num_qubits: int, acquaintance_size: int
) -> Dict[Tuple[cirq.Qid, ...], cirq.Gate]:

    return {
        Q: cirq.DiagonalGate(np.random.random(2 ** acquaintance_size))
        for Q in combinations(cirq.LineQubit.range(num_qubits), acquaintance_size)
    }
Esempio n. 6
0
def test_decomposition_unitary(n):
    diagonal_angles = np.random.randn(2 ** n)
    diagonal_gate = cirq.DiagonalGate(diagonal_angles)
    decomposed_circ = cirq.Circuit(cirq.decompose(diagonal_gate(*cirq.LineQubit.range(n))))

    expected_f = [np.exp(1j * angle) for angle in diagonal_angles]
    decomposed_f = cirq.unitary(decomposed_circ).diagonal()

    np.testing.assert_allclose(decomposed_f, expected_f)
Esempio n. 7
0
def test_diagram():
    a, b, c, d = cirq.LineQubit.range(4)

    diagonal_circuit = cirq.Circuit(
        cirq.DiagonalGate(_candidate_angles[:16])(a, b, c, d))
    cirq.testing.assert_has_diagram(
        diagonal_circuit,
        """
0: ───diag(2, 3, ..., 47, 53)───
      │
1: ───#2────────────────────────
      │
2: ───#3────────────────────────
      │
3: ───#4────────────────────────
""",
    )

    diagonal_circuit = cirq.Circuit(
        cirq.DiagonalGate(_candidate_angles[:8])(a, b, c))
    cirq.testing.assert_has_diagram(
        diagonal_circuit,
        """
0: ───diag(2, 3, ..., 17, 19)───
      │
1: ───#2────────────────────────
      │
2: ───#3────────────────────────
""",
    )

    diagonal_circuit = cirq.Circuit(
        cirq.DiagonalGate(_candidate_angles[:4])(a, b))
    cirq.testing.assert_has_diagram(
        diagonal_circuit,
        """
0: ───diag(2, 3, 5, 7)───
      │
1: ───#2─────────────────
""",
    )
Esempio n. 8
0
def test_decomposition_unitary(n):
    diagonal_angles = np.random.randn(2**n)
    diagonal_gate = cirq.DiagonalGate(diagonal_angles)
    decomposed_circ = cirq.Circuit(
        cirq.decompose(diagonal_gate(*cirq.LineQubit.range(n))))

    expected_f = [np.exp(1j * angle) for angle in diagonal_angles]
    decomposed_f = cirq.unitary(decomposed_circ).diagonal()

    # For large qubit counts, the decomposed circuit is rather large, so we lose a lot of
    # precision.
    np.testing.assert_allclose(decomposed_f, expected_f)
Esempio n. 9
0
def test_decomposition_with_parameterization(n):
    angles = sympy.symbols([f'x_{i}' for i in range(2 ** n)])
    exponent = sympy.Symbol('e')
    diagonal_gate = cirq.DiagonalGate(angles) ** exponent
    parameterized_op = diagonal_gate(*cirq.LineQubit.range(n))
    decomposed_circuit = cirq.Circuit(cirq.decompose(parameterized_op))
    for exponent_value in [-0.5, 0.5, 1]:
        for i in range(len(_candidate_angles) - 2 ** n + 1):
            resolver = {exponent: exponent_value}
            resolver.update(
                {angles[j]: x_j for j, x_j in enumerate(_candidate_angles[i : i + 2 ** n])}
            )
            resolved_op = cirq.resolve_parameters(parameterized_op, resolver)
            resolved_circuit = cirq.resolve_parameters(decomposed_circuit, resolver)
            cirq.testing.assert_allclose_up_to_global_phase(
                cirq.unitary(resolved_op), cirq.unitary(resolved_circuit), atol=1e-8
            )
Esempio n. 10
0
from typing import List
import numpy as np
import pytest
import sympy

import cirq

_candidate_angles: List[float] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53]


@pytest.mark.parametrize(
    'gate',
    (
        (
            cirq.DiagonalGate([2, 3, 5, 7]),
            cirq.DiagonalGate([0, 0, 0, 0]),
            cirq.DiagonalGate([2, 3, 5, sympy.Symbol('a')]),
            cirq.DiagonalGate([0.34, 0.12, 0, 0.96]),
            cirq.DiagonalGate(_candidate_angles[:8]),
            cirq.DiagonalGate(_candidate_angles[:16]),
        )
    ),
)
def test_consistent_protocols(gate):
    cirq.testing.assert_implements_consistent_protocols(gate)


@pytest.mark.parametrize('n', [1, 2, 3, 4, 5, 6, 7, 8, 9])
def test_decomposition_unitary(n):
    diagonal_angles = np.random.randn(2 ** n)
Esempio n. 11
0
def matrix_to_sycamore_operations(
        target_qubits: List[cirq.GridQubit],
        matrix: np.ndarray) -> Tuple[cirq.OP_TREE, List[cirq.GridQubit]]:
    """A method to convert a unitary matrix to a list of Sycamore operations.

    This method will return a list of `cirq.Operation`s using the qubits and (optionally) ancilla
    qubits to implement the unitary matrix `matrix` on the target qubits `qubits`.
    The operations are also supported by `cirq.google.gate_sets.SYC_GATESET`.

    Args:
        target_qubits: list of qubits the returned operations will act on. The qubit order defined by the list
            is assumed to be used by the operations to implement `matrix`.
        matrix: a matrix that is guaranteed to be unitary and of size (2**len(qs), 2**len(qs)).
    Returns:
        A tuple of operations and ancilla qubits allocated.
            Operations: In case the matrix is supported, a list of operations `ops` is returned.
                `ops` acts on `qs` qubits and for which `cirq.unitary(ops)` is equal to `matrix` up
                 to certain tolerance. In case the matrix is not supported, it might return NotImplemented to
                 reduce the noise in the judge output.
            Ancilla qubits: In case ancilla qubits are allocated a list of ancilla qubits. Otherwise
                an empty list.
        .
    """
    converter = cirq.google.ConvertToSycamoreGates()
    xmon_converter = cirq.google.ConvertToXmonGates()

    increment_unitaries = []
    for i in range(1, 10):
        inp = np.empty((2**i, 2**i))
        inp[1:] = np.eye(2**i)[:-1]
        inp[:1] = np.eye(2**i)[-1:]
        increment_unitaries.append(inp)

    oneQ_unitaries = [(cirq.unitary(cirq.X), cirq.X),
                      (cirq.unitary(cirq.Y), cirq.Y),
                      (cirq.unitary(cirq.Z), cirq.Z),
                      (cirq.unitary(cirq.H), cirq.H),
                      (cirq.unitary(cirq.S), cirq.S),
                      (cirq.unitary(cirq.T), cirq.T)]

    twoQ_sycamore_unitaries = [(cirq.unitary(cirq.google.SycamoreGate()),
                                cirq.google.SycamoreGate()),
                               (cirq.unitary(cirq.IdentityGate(num_qubits=2)),
                                cirq.IdentityGate(num_qubits=2)),
                               (cirq.unitary(cirq.XX), cirq.XX),
                               (cirq.unitary(cirq.YY), cirq.YY)]

    twoQ_xmon_unitaries = [(cirq.unitary(cirq.ZZ), cirq.ZZ),
                           (cirq.unitary(cirq.CX), cirq.CX)]

    threeQ_sycamore_unitaries = [
        (cirq.unitary(cirq.CCX), cirq.CCX),
        (cirq.unitary(cirq.CSWAP), cirq.CSWAP),
        # (cirq.unitary(cirq.ControlledGate(cirq.ISWAP ** 0.5)), cirq.ControlledGate(cirq.ISWAP ** 0.5)),
        (cirq.unitary(cirq.CCZ), cirq.CCZ),
        (cirq.unitary(cirq.IdentityGate(num_qubits=3)),
         cirq.IdentityGate(num_qubits=3))
    ]

    fourQ_sycamore_unitaries = [(cirq.unitary(cirq.IdentityGate(num_qubits=4)),
                                 cirq.IdentityGate(num_qubits=4))]

    def controlled_sqrt_iswap(qs):
        c = cirq.Circuit()
        c.append(cirq.ControlledGate(cirq.Y**-0.5).on(qs[0], qs[2]))
        c.append(cirq.CCZ.on(qs[0], qs[1], qs[2]))
        c.append(cirq.ControlledGate(cirq.Y**0.5).on(qs[0], qs[2]))
        c.append(cirq.ControlledGate(cirq.Y**0.5).on(qs[0], qs[1]))
        c.append(cirq.CX.on(qs[0], qs[1]))
        c.append(cirq.ControlledGate(cirq.Y**-0.5).on(qs[0], qs[1]))
        c.append(cirq.CCZ(qs[0], qs[1], qs[2]))
        c.append(cirq.ControlledGate(cirq.Y**0.5).on(qs[0], qs[1]))
        c.append(cirq.ControlledGate(cirq.T).on(qs[0], qs[1]))
        c.append(cirq.ControlledGate(cirq.Y**-0.5).on(qs[0], qs[1]))
        c.append(cirq.CCZ(qs[0], qs[1], qs[2]))
        c.append(cirq.ControlledGate(cirq.Y**-0.5).on(qs[0], qs[2]))
        c.append(cirq.ControlledGate(cirq.Y**0.5).on(qs[0], qs[1]))
        c.append(cirq.ControlledGate(cirq.Z**-0.25).on(qs[0], qs[1]))
        c.append(cirq.ControlledGate(cirq.Y**0.5).on(qs[0], qs[1]))
        c.append(cirq.CX.on(qs[0], qs[1]))
        c.append(cirq.CCZ.on(qs[0], qs[1], qs[2]))
        c.append(cirq.ControlledGate(cirq.Y**0.5).on(qs[0], qs[2]))
        return c

    def keep_func(gate):
        if cirq.unitary(gate).shape[0] < 5:
            return True
        else:
            return False

    def twoQ_sycamore_optimize(target_qubits, gate):
        g = gate.on(target_qubits[0], target_qubits[1])
        g = converter.convert(g)
        c = cirq.Circuit(g)
        c = cirq.google.optimized_for_sycamore(c, optimizer_type="sycamore")
        return c, []

    def twoQ_xmon_optimize(target_qubits, gate):
        g = gate.on(target_qubits[0], target_qubits[1])
        g = converter.convert(g)
        c = cirq.Circuit(g)
        c = cirq.google.optimized_for_sycamore(c, optimizer_type="xmon")
        return c, []

    # TODO: Fix up the CISWAP
    def threeQ_sycamore_optimize(target_qubits, gate):
        g = gate.on(*target_qubits)
        g = converter.convert(g)
        c = cirq.Circuit(g)
        c = cirq.google.optimized_for_sycamore(c, optimizer_type="xmon")
        return c, []

    def sycamore_optimize(target_qubits, gate):
        g = gate.on(*target_qubits)
        g = cirq.decompose(g, keep=keep_func)
        c = cirq.Circuit(g)
        c = cirq.google.optimized_for_sycamore(c, optimizer_type="sycamore")
        return c, []

    if matrix.shape[0] == 4:
        for twoQ_sycamore_unitary in twoQ_sycamore_unitaries:
            if np.isclose(matrix, twoQ_sycamore_unitary[0]).all():
                return twoQ_sycamore_optimize(target_qubits,
                                              twoQ_sycamore_unitary[1])

        for twoQ_xmon_unitary in twoQ_xmon_unitaries:
            if np.isclose(matrix, twoQ_xmon_unitary[0]).all():
                return twoQ_xmon_optimize(target_qubits, twoQ_xmon_unitary[1])

    if matrix.shape[0] == 8:
        #         if np.isclose(matrix, cirq.unitary(cirq.ControlledGate(cirq.ISWAP ** 0.5))).all():
        # #             g = cirq.ControlledGate(cirq.ISWAP ** 0.5).on(*target_qubits)
        # #             g = cirq.decompose(g)
        # #             c = controlled_sqrt_iswap(target_qubits)
        #             g = cirq.FSimGate(-np.pi/4, 0)
        #             g = cirq.decompose(g.on(*target_qubits))
        #             c = cirq.Circuit(g)
        #             return cirq.decompose(c, keep=keep_func), []
        for threeQ_sycamore_unitary in threeQ_sycamore_unitaries:
            if np.isclose(matrix, threeQ_sycamore_unitary[0]).all():
                return threeQ_sycamore_optimize(target_qubits,
                                                threeQ_sycamore_unitary[1])

    if len(target_qubits) == 1:
        for g in oneQ_unitaries:
            if np.isclose(matrix, g[0]).all():
                gate = converter.convert(g[1].on(*target_qubits))
                return gate, []

    def CNOT_toffoli_decomp(bitset, garbage, t, d):
        target = t
        gates = []
        for i in range(1, len(bitset) - 1):
            gates.append(cirq.CCX(garbage[-i - d], bitset[-i], target))
            target = garbage[-i - d]
        for gate in gates:
            yield gate
        gates.reverse()
        yield cirq.CCX(bitset[0], bitset[1], target)
        for gate in gates[:-1]:
            yield gate

    def CNOT_toffoli_decomp(bitset, garbage, t, d):
        target = t
        gates = []
        for i in range(1, len(bitset) - 1):
            gates.append(cirq.CCX(garbage[-i - d], bitset[-i], target))
            target = garbage[-i - d]
        gates.append(cirq.CCX(bitset[0], bitset[1], target))
        for gate in gates:
            yield gate
        gates.reverse()
        for gate in gates[1:]:
            yield gate
        gates.reverse()
        for gate in gates[1:]:
            yield gate
        gates.reverse()
        for gate in gates[1:-1]:
            yield gate

    def decompose_large_CNOT(control_qubits, target, ancilla):
        if len(control_qubits) == 0:
            return cirq.X(target)

        if len(control_qubits) == 1:
            return cirq.CX(control_qubits[0], target)

        if len(control_qubits) == 2:
            return cirq.CCX(control_qubits[0], control_qubits[1], target)

        bitset1 = [tq for i, tq in enumerate(control_qubits) if i % 2 == 0]
        bitset2 = [tq for i, tq in enumerate(control_qubits) if i % 2 == 1]
        bitset2.append(ancilla)
        gate1 = CNOT_toffoli_decomp(bitset1, bitset2, ancilla, 1)
        gate2 = CNOT_toffoli_decomp(bitset2, bitset1, target, 0)
        gate3 = CNOT_toffoli_decomp(bitset1, bitset2, ancilla, 1)
        gate4 = CNOT_toffoli_decomp(bitset2, bitset1, target, 0)
        return cirq.Circuit([gate1, gate2, gate3, gate4])

    if len(target_qubits) == 4:
        for fourQ_sycamore_unitary in fourQ_sycamore_unitaries:
            if np.isclose(matrix, fourQ_sycamore_unitary[0]).all():
                return sycamore_optimize(target_qubits,
                                         fourQ_sycamore_unitary[1])

        if np.isclose(matrix,
                      cirq.unitary(cirq.ControlledGate(cirq.CCX))).all():
            control_qubits = target_qubits[:-1]
            target = target_qubits[-1]
            ancilla = cirq.GridQubit(2, 3)
            c = decompose_large_CNOT(control_qubits, target, ancilla)
            return cirq.decompose(c), [ancilla]

    def increment(qubits):
        n_qubits = len(qubits)
        ancilla = cirq.GridQubit(2, 3)
        c = cirq.Circuit()
        for i in range(n_qubits):
            control_qubits = qubits[i + 1:]
            target = qubits[i]
            c.append(decompose_large_CNOT(control_qubits, target, ancilla))
        if n_qubits < 3:
            return c, []
        return c, [ancilla]

    def is_adjacent(q1, q2):
        return (q1.row == q2.row and np.abs(q1.col - q2.col)
                == 1) or (np.abs(q1.row - q2.row) == 1 and q1.col == q2.col)

    def swap_path(qs, q1, q2):
        path = []
        if q1 == q2:
            return path
        q = q1
        while not is_adjacent(q, q2):
            if not q2.row - q.row == 0:
                row_dir = int((q2.row - q.row) / np.abs(q2.row - q.row))
                if cirq.GridQubit(q.row + row_dir, q.col) in qs:
                    q = cirq.GridQubit(q.row + row_dir, q.col)
                    path.append(q)
                    continue
            if not q2.col - q.col == 0:
                col_dir = int((q2.col - q.col) / np.abs(q2.col - q.col))
                q = cirq.GridQubit(q.row, q.col + col_dir)
                path.append(q)
        return path

    def two_q_sycamore(g, q1, q2, qs):
        sp = swap_path(qs, q1, q2)
        if len(sp) == 0:
            yield g
            return
        q = q1
        for i in range(len(sp)):
            yield cirq.SWAP(q, sp[i])
            q = sp[i]
        yield g.gate(q, q2)
        sp.reverse()
        for i in range(1, len(sp)):
            yield cirq.SWAP(q, sp[i])
            q = sp[i]
        yield cirq.SWAP(q, q1)

    for U in increment_unitaries:
        if U.shape == matrix.shape:
            if np.isclose(U, matrix).all():
                if len(target_qubits) >= 7:
                    c, a = increment(target_qubits)
                    c = cirq.decompose(c)
                    # return c, a
                    cn = cirq.Circuit()
                    for g in c:
                        if len(g.qubits) == 1:
                            cn.append(g)
                        else:
                            q1 = g.qubits[0]
                            q2 = g.qubits[1]
                            cn.append(
                                cirq.Circuit(
                                    two_q_sycamore(g, q1, q2, target_qubits)))
                    return converter.convert(cn), a
                else:
                    c, a = increment(target_qubits)
                    c = cirq.decompose(c)
                    return c, a

    def isDiag(M):
        i, j = np.nonzero(M)
        return np.all(i == j)

    if isDiag(matrix):
        if np.isclose(matrix.diagonal(), 1).all():
            return cirq.Circuit(), []

    if isDiag(matrix):
        diagonal = matrix.diagonal()
        diagangles = (-1j * np.log(diagonal)).real

        diag_gate = cirq.DiagonalGate(diagangles)
        gate = diag_gate(*target_qubits)._decompose_()[1:]
        gate = converter.convert(gate)
        diag_circuit = cirq.Circuit(gate)
        return diag_circuit, []

    def pulverize_matrix(m):
        # N = 2^n
        N = len(m)

        L, CS, R = scipy.linalg.cossin(m, p=N / 2, q=N / 2)

        if len(m) == 2:
            stacked_matrices = np.stack([L, CS, R])
            return stacked_matrices

        # BREAK DOWN L MATRIX
        L1 = L[:round(N / 2), :round(N / 2)]
        L2 = L[round(N / 2):, round(N / 2):]

        L1_decomp = pulverize_matrix(L1)
        L2_decomp = pulverize_matrix(L2)

        left_matrices = 1j * np.zeros([
            L1_decomp.shape[0], L1_decomp.shape[1] * 2, L1_decomp.shape[2] * 2
        ])
        left_matrices[:, :round(N / 2), :round(N / 2)] += L1_decomp
        left_matrices[:, round(N / 2):, round(N / 2):] += L2_decomp

        # BREAK DOWN R MATRIX
        R1 = R[:round(N / 2), :round(N / 2)]
        R2 = R[round(N / 2):, round(N / 2):]

        R1_decomp = pulverize_matrix(R1)
        R2_decomp = pulverize_matrix(R2)

        right_matrices = 1j * np.zeros([
            R1_decomp.shape[0], R1_decomp.shape[1] * 2, R1_decomp.shape[2] * 2
        ])
        right_matrices[:, :round(N / 2), :round(N / 2)] += R1_decomp
        right_matrices[:, round(N / 2):, round(N / 2):] += R2_decomp

        all_matrices = np.concatenate(
            [left_matrices, CS[None], right_matrices])
        return all_matrices

    def get_S_matrix(m):
        S = np.zeros([round(2**int(m)), round(2**int(m))]) + 1

        cols = [
            np.sign(
                np.cos(2**(m - 1 - i) * np.pi * np.arange(0, 2**int(m), 1) /
                       2**int(m) + 10**-6)) for i in range(int(m))
        ]

        for bit in range(len(cols)):
            for i in range(len(S)):
                if round(2**bit) & i:
                    S[:, i] *= cols[bit]

        return S

    def gray_code_changes(m):
        return gray_code_changes_r(m) + [m]

    def gray_code_changes_r(m):
        if m < 0:
            return []
        return gray_code_changes_r(m - 1) + [m] + gray_code_changes_r(m - 1)

    def UCRy(ctrls, target, alphas, S_T_inv, seq):

        thetas = np.matmul(S_T_inv, alphas)

        gates = []
        for i in range(len(seq)):
            theta_i = thetas[i]
            q_i = ctrls[int(seq[i])]
            gates += [cirq.Ry(rads=theta_i)(target)]
            gates += [cirq.CNOT(q_i, target)]

        return gates

    def ry_angle(u):
        u_log = 1j * scipy.linalg.logm(u)
        return ((2j * u_log[0][1]).real)

    def extract_ry_angles(matrix, target_bit, n):
        alphas = []
        for i in range(len(matrix)):
            if not int(2**(n - 1 - target_bit)) & i:
                ry_gate = matrix[(i, i + int(2**(n - 1 - target_bit))), :][:, (
                    i, i + int(2**(n - 1 - target_bit)))]
                alphas += [ry_angle(ry_gate)]
        alphas = np.array(alphas)
        return alphas

    def UCRy_gates_from_matrix(matrix, target_bit, qs, n, S_T_inv):
        alphas = extract_ry_angles(matrix, target_bit, n)
        ctrl_qs = qs[0:int(target_bit)] + qs[int(target_bit) + 1:]
        gates = UCRy(ctrl_qs[::-1], qs[int(target_bit)], alphas, S_T_inv,
                     gray_code_changes(n - 2))
        return gates

    def arbitrary_diagonal_gate_from_matrix(matrix, qs):
        diagonal = matrix.diagonal()
        diagangles = (-1j * np.log(diagonal)).real
        diag_gate = cirq.DiagonalGate(diagangles)
        gates = diag_gate(*qs)._decompose_()[0:]
        return (gates)

    def arbitrary_operation_from_matrix(U, qs):
        n = round(np.log2(len(U)))
        S = get_S_matrix(n - 1)
        S_T_inv = np.linalg.inv(S.transpose())

        matrices = pulverize_matrix(U)
        ucry_target_bits = [n - 1 - i for i in gray_code_changes(n - 1)[:-1]]

        gates = []

        for m_i in range(len(matrices)):
            # print(m_i, "/", len(matrices))
            if m_i % 2 == 0:
                gates = arbitrary_diagonal_gate_from_matrix(matrices[m_i],
                                                            qs) + gates
                # print(np.sum(np.abs(cirq.unitary(cirq.Circuit(arbitrary_diagonal_gate_from_matrix(matrices[m_i], qs))) - matrices[m_i])))
                # print(matrices[m_i])
            else:
                target_bit = ucry_target_bits[int(m_i / 2)]
                gates = UCRy_gates_from_matrix(matrices[m_i], target_bit, qs,
                                               n, S_T_inv) + gates
                # print(np.sum(np.abs(cirq.unitary(cirq.Circuit(UCRy_gates_from_matrix(matrices[m_i], target_bit, qs, n, S_T_inv))) - matrices[m_i])))

        return gates

    gates = arbitrary_operation_from_matrix(matrix, target_qubits)

    c = cirq.Circuit()
    if len(target_qubits) < 8:
        for g in gates:
            if len(g.qubits) == 1:
                c.append(g)
            elif len(g.qubits) == 2:
                q1 = g.qubits[0]
                q2 = g.qubits[1]
                c.append(cirq.Circuit(two_q_sycamore(g, q1, q2,
                                                     target_qubits)))
        return converter.convert(c), []

    else:
        c.append(gates)
        return c, []

    return NotImplemented, []
Esempio n. 12
0
 def arbitrary_diagonal_gate_from_matrix(matrix, qs):
     diagonal = matrix.diagonal()
     diagangles = (-1j * np.log(diagonal)).real
     diag_gate = cirq.DiagonalGate(diagangles)
     gates = diag_gate(*qs)._decompose_()[0:]
     return (gates)
Esempio n. 13
0
def test_property():
    assert cirq.DiagonalGate([2, 3, 5, 7]).diag_angles_radians == (2, 3, 5, 7)
        (GateUsingWorkspaceForApplyUnitary()(cirq.NamedQubit('q1')), True),
        (GateAllocatingNewSpaceForResult()(cirq.NamedQubit('q1')), True),
        (
            cirq.MatrixGate(np.kron(*(cirq.unitary(cirq.H),) * 2), qid_shape=(4,)).on(
                cirq.NamedQid("q", 4)
            ),
            False,
        ),
        (
            cirq.MatrixGate(cirq.testing.random_unitary(4, random_state=1234)).on(
                cirq.NamedQubit('q1'), cirq.NamedQubit('q2')
            ),
            False,
        ),
        (cirq.XX(cirq.NamedQubit('q1'), cirq.NamedQubit('q2')) ** sympy.Symbol("s"), True),
        (cirq.DiagonalGate(sympy.symbols("s1, s2")).on(cirq.NamedQubit("q")), False),
    ],
)
def test_controlled_operation_is_consistent(
    gate: cirq.GateOperation, should_decompose_to_target: bool
):
    cb = cirq.NamedQubit('ctr')
    cgate = cirq.ControlledOperation([cb], gate)
    cirq.testing.assert_implements_consistent_protocols(cgate)
    cirq.testing.assert_decompose_ends_at_default_gateset(
        cgate, ignore_known_gates=not should_decompose_to_target
    )

    cgate = cirq.ControlledOperation([cb], gate, control_values=[0])
    cirq.testing.assert_implements_consistent_protocols(cgate)
    cirq.testing.assert_decompose_ends_at_default_gateset(