예제 #1
0
def test_single_qubit_matrix_to_gates_tolerance_z():
    z = np.diag([1, np.exp(1j * 0.01)])

    optimized_away = cirq.single_qubit_matrix_to_gates(z, tolerance=0.1)
    assert len(optimized_away) == 0

    kept = cirq.single_qubit_matrix_to_gates(z, tolerance=0.0001)
    assert len(kept) == 1
예제 #2
0
def test_single_qubit_matrix_to_gates_tolerance_z():
    z = np.diag([1, np.exp(1j * 0.01)])

    optimized_away = cirq.single_qubit_matrix_to_gates(
        z, tolerance=0.1)
    assert len(optimized_away) == 0

    kept = cirq.single_qubit_matrix_to_gates(z, tolerance=0.0001)
    assert len(kept) == 1
예제 #3
0
def test_single_qubit_matrix_to_gates_tolerance_xy():
    c, s = np.cos(0.01), np.sin(0.01)
    xy = np.array([[c, -s], [s, c]])

    optimized_away = cirq.single_qubit_matrix_to_gates(xy, tolerance=0.1)
    assert len(optimized_away) == 0

    kept = cirq.single_qubit_matrix_to_gates(xy, tolerance=0.0001)
    assert len(kept) == 1
예제 #4
0
def test_single_qubit_matrix_to_gates_tolerance_xy():
    c, s = np.cos(0.01), np.sin(0.01)
    xy = np.array([[c, -s], [s, c]])

    optimized_away = cirq.single_qubit_matrix_to_gates(
        xy, tolerance=0.1)
    assert len(optimized_away) == 0

    kept = cirq.single_qubit_matrix_to_gates(xy, tolerance=0.0001)
    assert len(kept) == 1
예제 #5
0
def test_single_qubit_matrix_to_gates_tolerance_half_turn_phasing():
    a = np.pi / 2 + 0.01
    c, s = np.cos(a), np.sin(a)
    nearly_x = np.array([[c, -s], [s, c]])
    z1 = np.diag([1, np.exp(1j * 1.2)])
    z2 = np.diag([1, np.exp(1j * 1.6)])
    phased_nearly_x = z1.dot(nearly_x).dot(z2)

    optimized_away = cirq.single_qubit_matrix_to_gates(phased_nearly_x,
                                                       tolerance=0.1)
    assert len(optimized_away) == 2

    kept = cirq.single_qubit_matrix_to_gates(phased_nearly_x, tolerance=0.0001)
    assert len(kept) == 3
예제 #6
0
def test_single_qubit_matrix_to_gates_tolerance_half_turn_phasing():
    a = np.pi / 2 + 0.01
    c, s = np.cos(a), np.sin(a)
    nearly_x = np.array([[c, -s], [s, c]])
    z1 = np.diag([1, np.exp(1j * 1.2)])
    z2 = np.diag([1, np.exp(1j * 1.6)])
    phased_nearly_x = z1.dot(nearly_x).dot(z2)

    optimized_away = cirq.single_qubit_matrix_to_gates(
        phased_nearly_x, tolerance=0.1)
    assert len(optimized_away) == 2

    kept = cirq.single_qubit_matrix_to_gates(
        phased_nearly_x, tolerance=0.0001)
    assert len(kept) == 3
예제 #7
0
def test_single_qubit_matrix_to_gates_cases(intended_effect):
    for atol in [1e-1, 1e-8]:
        gates = cirq.single_qubit_matrix_to_gates(intended_effect,
                                                  tolerance=atol / 10)
        assert len(gates) <= 3
        assert sum(1 for g in gates if not isinstance(g, cirq.ZPowGate)) <= 1
        assert_gates_implement_unitary(gates, intended_effect, atol=atol)
def test_unitary_decomp():
    q = cirq.GridQubit(0, 0)
    random_unitary = random_single_qubit_unitary()
    circuit = cirq.Circuit(
        [term.on(q) for term in cirq.single_qubit_matrix_to_gates(random_unitary)]
    )
    assert np.isclose(abs(np.trace(cirq.unitary(circuit).conj().T @ random_unitary)), 2.0)
예제 #9
0
    def _decompose_two_qubit(self, operation: cirq.Operation) -> cirq.OP_TREE:
        """Decomposes a two qubit gate into XXPow, YYPow, and ZZPow plus single qubit gates."""
        mat = cirq.unitary(operation)
        kak = cirq.kak_decomposition(mat, check_preconditions=False)

        for qubit, mat in zip(operation.qubits, kak.single_qubit_operations_before):
            gates = cirq.single_qubit_matrix_to_gates(mat, self.atol)
            for gate in gates:
                yield gate(qubit)

        two_qubit_gates = [cirq.XX, cirq.YY, cirq.ZZ]
        for two_qubit_gate, coefficient in zip(two_qubit_gates, kak.interaction_coefficients):
            yield (two_qubit_gate ** (-coefficient * 2 / np.pi))(*operation.qubits)

        for qubit, mat in zip(operation.qubits, kak.single_qubit_operations_after):
            for gate in cirq.single_qubit_matrix_to_gates(mat, self.atol):
                yield gate(qubit)
예제 #10
0
def test_single_qubit_matrix_to_gates_fuzz_half_turns_merge_z_gates(
        pre_turns, post_turns):
    intended_effect = cirq.dot(cirq.unitary(cirq.Z**(2 * pre_turns)),
                               cirq.unitary(cirq.X),
                               cirq.unitary(cirq.Z**(2 * post_turns)))

    gates = cirq.single_qubit_matrix_to_gates(intended_effect, tolerance=1e-7)

    assert len(gates) <= 2
    assert_gates_implement_unitary(gates, intended_effect, atol=1e-6)
예제 #11
0
def test_single_qubit_matrix_to_gates_fuzz_half_turns_merge_z_gates(
        pre_turns, post_turns):
    intended_effect = cirq.dot(
        cirq.RotZGate(half_turns=2 * pre_turns).matrix(), cirq.X.matrix(),
        cirq.RotZGate(half_turns=2 * post_turns).matrix())

    gates = cirq.single_qubit_matrix_to_gates(intended_effect,
                                              tolerance=0.0001)

    assert len(gates) <= 2
    assert_gates_implement_unitary(gates, intended_effect)
예제 #12
0
def test_single_qubit_matrix_to_gates_fuzz_half_turns_merge_z_gates(
        pre_turns, post_turns):
    intended_effect = cirq.dot(
        cirq.RotZGate(half_turns=2 * pre_turns).matrix(),
        cirq.X.matrix(),
        cirq.RotZGate(half_turns=2 * post_turns).matrix())

    gates = cirq.single_qubit_matrix_to_gates(
        intended_effect, tolerance=0.0001)

    assert len(gates) <= 2
    assert_gates_implement_unitary(gates, intended_effect)
예제 #13
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.
        .
    """

    ops = NotImplemented

    if len(target_qubits) == 1:
        ops = cirq.single_qubit_matrix_to_gates(matrix)
        for i, x in enumerate(ops):
            ops[i] = cirq.GateOperation(x, [target_qubits[0]])

    elif len(target_qubits) == 2:
        ops = cirq.two_qubit_matrix_to_operations(target_qubits[0],
                                                  target_qubits[1],
                                                  matrix,
                                                  allow_partial_czs=False,
                                                  atol=1e-4)

    elif len(target_qubits) == 3:
        ops = cirq.three_qubit_matrix_to_operations(target_qubits[0],
                                                    target_qubits[1],
                                                    target_qubits[2],
                                                    matrix,
                                                    atol=1e-4)

    return ops, []
예제 #14
0
def test_single_qubit_matrix_to_gates_known_y():
    actual = cirq.single_qubit_matrix_to_gates(np.array([[0, -1j], [1j, 0]]),
                                               tolerance=0.01)

    assert cirq.approx_eq(actual, [cirq.Y], atol=1e-9)
예제 #15
0
def test_single_qubit_matrix_to_gates_known_y():
    actual = cirq.single_qubit_matrix_to_gates(
        np.array([[0, -1j], [1j, 0]]), tolerance=0.01)

    assert actual == [cirq.Y]
예제 #16
0
def test_single_qubit_matrix_to_gates_known_z():
    actual = cirq.single_qubit_matrix_to_gates(
        np.array([[1, 0], [0, -1]]), tolerance=0.01)

    assert actual == [cirq.Z]
예제 #17
0
def test_known_s_dag():
    actual = cirq.single_qubit_matrix_to_gates(
        np.array([[1, 0], [0, -1j]]), tolerance=0.01)

    assert actual == [cirq.Z**-0.5]
예제 #18
0
def test_known_h():
    actual = cirq.single_qubit_matrix_to_gates(
        np.array([[1, 1], [1, -1]]) * np.sqrt(0.5), tolerance=0.001)

    assert actual == [cirq.Y**-0.5, cirq.Z]
예제 #19
0
 def _decompose_single_qubit_operation(self, op: cirq.Operation,
                                       _) -> cirq.OP_TREE:
     qubit = op.qubits[0]
     mat = cirq.unitary(op)
     for gate in cirq.single_qubit_matrix_to_gates(mat, self.atol):
         yield gate(qubit)
예제 #20
0
def test_known_s_dag():
    actual = cirq.single_qubit_matrix_to_gates(
        np.array([[1, 0], [0, -1j]]), tolerance=0.01)

    assert actual == [cirq.Z**-0.5]
예제 #21
0
def test_single_qubit_matrix_to_gates_known_z():
    actual = cirq.single_qubit_matrix_to_gates(
        np.array([[1, 0], [0, -1]]), tolerance=0.01)

    assert actual == [cirq.Z]
예제 #22
0
def test_single_qubit_matrix_to_gates_known_y():
    actual = cirq.single_qubit_matrix_to_gates(
        np.array([[0, -1j], [1j, 0]]), tolerance=0.01)

    assert actual == [cirq.Y]
예제 #23
0
def _decompose_single_qubit(operation: cirq.Operation,
                            atol: float) -> cirq.OP_TREE:
    qubit = operation.qubits[0]
    mat = cirq.unitary(operation)
    for gate in cirq.single_qubit_matrix_to_gates(mat, atol):
        yield gate(qubit)
예제 #24
0
def test_single_qubit_matrix_to_gates_cases(intended_effect):
    gates = cirq.single_qubit_matrix_to_gates(intended_effect,
                                              tolerance=0.0001)
    assert len(gates) <= 3
    assert sum(1 for g in gates if not isinstance(g, cirq.RotZGate)) <= 1
    assert_gates_implement_unitary(gates, intended_effect)
예제 #25
0
def test_single_qubit_matrix_to_gates_cases(intended_effect):
    gates = cirq.single_qubit_matrix_to_gates(
        intended_effect, tolerance=0.0001)
    assert len(gates) <= 3
    assert sum(1 for g in gates if not isinstance(g, cirq.RotZGate)) <= 1
    assert_gates_implement_unitary(gates, intended_effect)
예제 #26
0
def test_known_s_dag():
    actual = cirq.single_qubit_matrix_to_gates(np.array([[1, 0], [0, -1j]]),
                                               tolerance=0.01)

    assert cirq.approx_eq(actual, [cirq.Z**-0.5], atol=1e-9)
예제 #27
0
def test_known_h():
    actual = cirq.single_qubit_matrix_to_gates(np.array([[1, 1], [1, -1]]) *
                                               np.sqrt(0.5),
                                               tolerance=0.001)

    assert cirq.approx_eq(actual, [cirq.Y**-0.5, cirq.Z], atol=1e-9)
예제 #28
0
def test_known_h():
    actual = cirq.single_qubit_matrix_to_gates(
        np.array([[1, 1], [1, -1]]) * np.sqrt(0.5), tolerance=0.001)

    assert actual == [cirq.Y**-0.5, cirq.Z]