Ejemplo n.º 1
0
def three_qubit_matrix_to_operations(
    q0: ops.Qid, q1: ops.Qid, q2: ops.Qid, u: np.ndarray, atol: float = 1e-8
) -> Sequence[ops.Operation]:
    """Returns operations for a 3 qubit unitary.

    The algorithm is described in Shende et al.:
    Synthesis of Quantum Logic Circuits. Tech. rep. 2006,
    https://arxiv.org/abs/quant-ph/0406176

    Args:
        q0: first qubit
        q1: second qubit
        q2: third qubit
        u: unitary matrix
        atol: A limit on the amount of absolute error introduced by the
            construction.

    Returns:
        The resulting operations will have only known two-qubit and one-qubit
        gates based operations, namely CZ, CNOT and rx, ry, PhasedXPow gates.

    Raises:
        ValueError: If the u matrix is non-unitary or not of shape (8,8).
    """
    if np.shape(u) != (8, 8):
        raise ValueError(f"Expected unitary matrix with shape (8,8) got {np.shape(u)}")
    if not cirq.is_unitary(u, atol=atol):
        raise ValueError(f"Matrix is not unitary: {u}")

    try:
        from scipy.linalg import cossin
    except ImportError:  # coverage: ignore
        # coverage: ignore
        raise ImportError(
            "cirq.three_qubit_unitary_to_operations requires "
            "SciPy 1.5.0+, as it uses the cossin function. Please"
            " upgrade scipy in your environment to use this "
            "function!"
        )
    (u1, u2), theta, (v1h, v2h) = cossin(u, 4, 4, separate=True)

    cs_ops = _cs_to_ops(q0, q1, q2, theta)
    if len(cs_ops) > 0 and cs_ops[-1] == cirq.CZ(q2, q0):
        # optimization A.1 - merging the last CZ from the end of CS into UD
        # cz = cirq.Circuit([cs_ops[-1]]).unitary()
        # CZ(c,a) = CZ(a,c) as CZ is symmetric
        # for the u1⊕u2 multiplexor operator:
        # as u1(b,c) is the operator in case a = \0>,
        # and u2(b,c) is the operator for (b,c) in case a = |1>
        # we can represent the merge by phasing u2 with I ⊗ Z
        u2 = u2 @ np.diag([1, -1, 1, -1])
        cs_ops = cs_ops[:-1]

    d_ud, ud_ops = _two_qubit_multiplexor_to_ops(q0, q1, q2, u1, u2, shift_left=True, atol=atol)

    _, vdh_ops = _two_qubit_multiplexor_to_ops(
        q0, q1, q2, v1h, v2h, shift_left=False, diagonal=d_ud, atol=atol
    )

    return list(cirq.Circuit(vdh_ops + cs_ops + ud_ops).all_operations())
Ejemplo n.º 2
0
def test_cossin_error_empty_subblocks():
    with pytest.raises(ValueError, match="x11.*empty"):
        cossin(([], [], [], []))
    with pytest.raises(ValueError, match="x12.*empty"):
        cossin(([1, 2], [], [6, 7], [8, 9, 10]))
    with pytest.raises(ValueError, match="x21.*empty"):
        cossin(([1, 2], [3, 4, 5], [], [8, 9, 10]))
    with pytest.raises(ValueError, match="x22.*empty"):
        cossin(([1, 2], [3, 4, 5], [2], []))
Ejemplo n.º 3
0
def test_cossin_error_partitioning():
    x = np.array(ortho_group.rvs(4), dtype=np.float)
    with pytest.raises(ValueError, match="invalid p=0.*0<p<4.*"):
        cossin(x, 0, 1)
    with pytest.raises(ValueError, match="invalid p=4.*0<p<4.*"):
        cossin(x, 4, 1)
    with pytest.raises(ValueError, match="invalid q=-2.*0<q<4.*"):
        cossin(x, 1, -2)
    with pytest.raises(ValueError, match="invalid q=5.*0<q<4.*"):
        cossin(x, 1, 5)
Ejemplo n.º 4
0
def test_cossin(dtype_, m, p, q, swap_sign):
    seed(1234)
    if dtype_ in COMPLEX_DTYPES:
        x = np.array(unitary_group.rvs(m), dtype=dtype_)
    else:
        x = np.array(ortho_group.rvs(m), dtype=dtype_)

    u, cs, vh = cossin(x, p, q, swap_sign=swap_sign)
    assert_allclose(x,
                    u @ cs @ vh,
                    rtol=0.,
                    atol=m * 1e3 * np.finfo(dtype_).eps)
    assert u.dtype == dtype_
    # Test for float32 or float 64
    assert cs.dtype == np.real(u).dtype
    assert vh.dtype == dtype_

    u, cs, vh = cossin([x[:p, :q], x[:p, q:], x[p:, :q], x[p:, q:]],
                       swap_sign=swap_sign)
    assert_allclose(x,
                    u @ cs @ vh,
                    rtol=0.,
                    atol=m * 1e3 * np.finfo(dtype_).eps)
    assert u.dtype == dtype_
    assert cs.dtype == np.real(u).dtype
    assert vh.dtype == dtype_

    _, cs2, vh2 = cossin(x, p, q, compute_u=False, swap_sign=swap_sign)
    assert_allclose(cs, cs2, rtol=0., atol=10 * np.finfo(dtype_).eps)
    assert_allclose(vh, vh2, rtol=0., atol=10 * np.finfo(dtype_).eps)

    u2, cs2, _ = cossin(x, p, q, compute_vh=False, swap_sign=swap_sign)
    assert_allclose(u, u2, rtol=0., atol=10 * np.finfo(dtype_).eps)
    assert_allclose(cs, cs2, rtol=0., atol=10 * np.finfo(dtype_).eps)

    _, cs2, _ = cossin(x,
                       p,
                       q,
                       compute_u=False,
                       compute_vh=False,
                       swap_sign=swap_sign)
    assert_allclose(cs, cs2, rtol=0., atol=10 * np.finfo(dtype_).eps)
Ejemplo n.º 5
0
def test_cossin_mixed_types():
    seed(1234)
    x = np.array(ortho_group.rvs(4), dtype=np.float)
    u, cs, vh = cossin([
        x[:2, :2],
        np.array(x[:2, 2:], dtype=np.complex128), x[2:, :2], x[2:, 2:]
    ])

    assert u.dtype == np.complex128
    assert cs.dtype == np.float64
    assert vh.dtype == np.complex128
    assert_allclose(x,
                    u @ cs @ vh,
                    rtol=0.,
                    atol=1e4 * np.finfo(np.complex128).eps)
Ejemplo n.º 6
0
def test_cossin_separate(dtype_):
    m, p, q = 250, 80, 170

    pfx = 'or' if dtype_ in REAL_DTYPES else 'un'
    X = ortho_group.rvs(m) if pfx == 'or' else unitary_group.rvs(m)
    X = np.array(X, dtype=dtype_)

    drv, dlw = get_lapack_funcs((pfx + 'csd', pfx + 'csd_lwork'), [X])
    lwval = _compute_lwork(dlw, m, p, q)
    lwvals = {
        'lwork': lwval
    } if pfx == 'or' else dict(zip(['lwork', 'lrwork'], lwval))

    *_, theta, u1, u2, v1t, v2t, _ = \
        drv(X[:p, :q], X[:p, q:], X[p:, :q], X[p:, q:], **lwvals)

    (u1_2, u2_2), theta2, (v1t_2, v2t_2) = cossin(X, p, q, separate=True)

    assert_allclose(u1_2, u1, rtol=0., atol=10 * np.finfo(dtype_).eps)
    assert_allclose(u2_2, u2, rtol=0., atol=10 * np.finfo(dtype_).eps)
    assert_allclose(v1t_2, v1t, rtol=0., atol=10 * np.finfo(dtype_).eps)
    assert_allclose(v2t_2, v2t, rtol=0., atol=10 * np.finfo(dtype_).eps)
    assert_allclose(theta2, theta, rtol=0., atol=10 * np.finfo(dtype_).eps)
Ejemplo n.º 7
0
def test_cossin_error_incorrect_subblocks():
    with pytest.raises(ValueError, match="be due to missing p, q arguments."):
        cossin(([1, 2], [3, 4, 5], [6, 7], [8, 9, 10]))
Ejemplo n.º 8
0
def test_cossin_error_non_square():
    with pytest.raises(ValueError, match="only supports square"):
        cossin(np.array([[1, 2]]), 1, 1)
Ejemplo n.º 9
0
def test_cossin_error_non_iterable():
    with pytest.raises(ValueError, match="containing the subblocks of X"):
        cossin(12j)
Ejemplo n.º 10
0
def test_cossin_error_missing_partitioning():
    with pytest.raises(ValueError, match=".*exactly four arrays.* got 2"):
        cossin(unitary_group.rvs(2))

    with pytest.raises(ValueError, match=".*might be due to missing p, q"):
        cossin(unitary_group.rvs(4))
Ejemplo n.º 11
0
Archivo: sc.py Proyecto: polyzer/qbyq
def make_cs_decompose(operator, p=None, q=None):
    if not p and not q:
        return cossin(operator)
    else:
        return cossin(operator, p=p, q=q)