Example #1
0
 def from_matrix(mat: np.array) -> 'QasmUGate':
     pre_phase, rotation, post_phase = linalg.deconstruct_single_qubit_matrix_into_angles(mat)
     return QasmUGate(
         rotation / np.pi,
         post_phase / np.pi,
         pre_phase / np.pi,
     )
Example #2
0
def _deconstruct_single_qubit_matrix_into_gate_turns(
        mat: np.ndarray) -> Tuple[float, float, float]:
    """Breaks down a 2x2 unitary into gate parameters.

    Args:
        mat: The 2x2 unitary matrix to break down.

    Returns:
       A tuple containing the amount to rotate around an XY axis, the phase of
       that axis, and the amount to phase around Z. All results will be in
       fractions of a whole turn, with values canonicalized into the range
       [-0.5, 0.5).
    """
    pre_phase, rotation, post_phase = (
        linalg.deconstruct_single_qubit_matrix_into_angles(mat))

    # Figure out parameters of the actual gates we will do.
    tau = 2 * np.pi
    xy_turn = rotation / tau
    xy_phase_turn = 0.25 - pre_phase / tau
    total_z_turn = (post_phase + pre_phase) / tau

    # Normalize turns into the range [-0.5, 0.5).
    return (_signed_mod_1(xy_turn), _signed_mod_1(xy_phase_turn),
            _signed_mod_1(total_z_turn))
Example #3
0
def _deconstruct_single_qubit_matrix_into_gate_turns(
        mat: np.ndarray) -> Tuple[float, float, float]:
    """Breaks down a 2x2 unitary into gate parameters.

    Args:
        mat: The 2x2 unitary matrix to break down.

    Returns:
       A tuple containing the amount to rotate around an XY axis, the phase of
       that axis, and the amount to phase around Z. All results will be in
       fractions of a whole turn, with values canonicalized into the range
       [-0.5, 0.5).
    """
    pre_phase, rotation, post_phase = (
        linalg.deconstruct_single_qubit_matrix_into_angles(mat))

    # Figure out parameters of the actual gates we will do.
    tau = 2 * np.pi
    xy_turn = rotation / tau
    xy_phase_turn = 0.25 - pre_phase / tau
    total_z_turn = (post_phase + pre_phase) / tau

    # Normalize turns into the range [-0.5, 0.5).
    return (_signed_mod_1(xy_turn), _signed_mod_1(xy_phase_turn),
            _signed_mod_1(total_z_turn))
def single_qubit_matrix_to_pauli_rotations(
    mat: np.ndarray, atol: float = 0
) -> List[Tuple[ops.Pauli, float]]:
    """Implements a single-qubit operation with few rotations.

    Args:
        mat: The 2x2 unitary matrix of the operation to implement.
        atol: A limit on the amount of absolute error introduced by the
            construction.

    Returns:
        A list of (Pauli, half_turns) tuples that, when applied in order,
        perform the desired operation.
    """

    def is_clifford_rotation(half_turns):
        return near_zero_mod(half_turns, 0.5, atol=atol)

    def to_quarter_turns(half_turns):
        return round(2 * half_turns) % 4

    def is_quarter_turn(half_turns):
        return is_clifford_rotation(half_turns) and to_quarter_turns(half_turns) % 2 == 1

    def is_half_turn(half_turns):
        return is_clifford_rotation(half_turns) and to_quarter_turns(half_turns) == 2

    def is_no_turn(half_turns):
        return is_clifford_rotation(half_turns) and to_quarter_turns(half_turns) == 0

    # Decompose matrix
    z_rad_before, y_rad, z_rad_after = linalg.deconstruct_single_qubit_matrix_into_angles(mat)
    z_ht_before = z_rad_before / np.pi - 0.5
    m_ht = y_rad / np.pi
    m_pauli: ops.Pauli = ops.X
    z_ht_after = z_rad_after / np.pi + 0.5

    # Clean up angles
    if is_clifford_rotation(z_ht_before):
        if (is_quarter_turn(z_ht_before) or is_quarter_turn(z_ht_after)) ^ (
            is_half_turn(m_ht) and is_no_turn(z_ht_before - z_ht_after)
        ):
            z_ht_before += 0.5
            z_ht_after -= 0.5
            m_pauli = ops.Y
        if is_half_turn(z_ht_before) or is_half_turn(z_ht_after):
            z_ht_before -= 1
            z_ht_after += 1
            m_ht = -m_ht
    if is_no_turn(m_ht):
        z_ht_before += z_ht_after
        z_ht_after = 0
    elif is_half_turn(m_ht):
        z_ht_after -= z_ht_before
        z_ht_before = 0

    # Generate operations
    rotation_list = [(ops.Z, z_ht_before), (m_pauli, m_ht), (ops.Z, z_ht_after)]
    return [(pauli, ht) for pauli, ht in rotation_list if not is_no_turn(ht)]
Example #5
0
 def from_matrix(mat: np.ndarray) -> 'cirq.PhasedXZGate':
     pre_phase, rotation, post_phase = linalg.deconstruct_single_qubit_matrix_into_angles(
         mat)
     pre_phase /= np.pi
     post_phase /= np.pi
     rotation /= np.pi
     pre_phase -= 0.5
     post_phase += 0.5
     return PhasedXZGate(x_exponent=rotation,
                         axis_phase_exponent=-pre_phase,
                         z_exponent=post_phase + pre_phase)._canonical()
Example #6
0
    def single_qubit_matrix_to_ops(mat, qubit):
        # Decompose matrix
        z_rad_before, y_rad, z_rad_after = (
            linalg.deconstruct_single_qubit_matrix_into_angles(mat))
        z_ht_before = z_rad_before / np.pi - 0.5
        m_ht = y_rad / np.pi
        m_pauli = ops.Pauli.X
        z_ht_after = z_rad_after / np.pi + 0.5

        # Clean up angles
        if is_clifford_rotation(z_ht_before):
            if is_quarter_turn(z_ht_before) or is_quarter_turn(z_ht_after):
                z_ht_before += 0.5
                z_ht_after -= 0.5
                m_pauli = ops.Pauli.Y
            if is_half_turn(z_ht_before) or is_half_turn(z_ht_after):
                z_ht_before -= 1
                z_ht_after += 1
                m_ht = -m_ht
        if is_no_turn(m_ht):
            z_ht_before += z_ht_after
            z_ht_after = 0
        elif is_half_turn(m_ht):
            z_ht_after -= z_ht_before
            z_ht_before = 0

        # Generate operations
        rotation_list = [(ops.Pauli.Z, z_ht_before), (m_pauli, m_ht),
                         (ops.Pauli.Z, z_ht_after)]
        is_clifford_list = [
            is_clifford_rotation(ht) for pauli, ht in rotation_list
        ]
        op_list = [
            rotation_to_clifford_op(pauli, qubit, ht)
            if is_clifford else rotation_to_non_clifford_op(pauli, qubit, ht)
            for is_clifford, (pauli,
                              ht) in zip(is_clifford_list, rotation_list)
        ]

        # Merge adjacent Clifford gates
        for i in reversed(range(len(op_list) - 1)):
            if is_clifford_list[i] and is_clifford_list[i + 1]:
                op_list[i] = op_list[i].gate.merged_with(
                    op_list[i + 1].gate)(qubit)
                is_clifford_list.pop(i + 1)
                op_list.pop(i + 1)

        # Yield non-identity ops
        for is_clifford, op in zip(is_clifford_list, op_list):
            if is_clifford and op.gate == ops.CliffordGate.I:
                continue
            yield op
Example #7
0
    def single_qubit_matrix_to_ops(mat, qubit):
        # Decompose matrix
        z_rad_before, y_rad, z_rad_after = (
            linalg.deconstruct_single_qubit_matrix_into_angles(mat))
        z_ht_before = z_rad_before / np.pi - 0.5
        m_ht = y_rad / np.pi
        m_pauli = ops.Pauli.X
        z_ht_after = z_rad_after / np.pi + 0.5

        # Clean up angles
        if is_clifford_rotation(z_ht_before):
            if is_quarter_turn(z_ht_before) or is_quarter_turn(z_ht_after):
                z_ht_before += 0.5
                z_ht_after -= 0.5
                m_pauli = ops.Pauli.Y
            if is_half_turn(z_ht_before) or is_half_turn(z_ht_after):
                z_ht_before -= 1
                z_ht_after += 1
                m_ht = -m_ht
        if is_no_turn(m_ht):
            z_ht_before += z_ht_after
            z_ht_after = 0
        elif is_half_turn(m_ht):
            z_ht_after -= z_ht_before
            z_ht_before = 0

        # Generate operations
        rotation_list = [
            (ops.Pauli.Z, z_ht_before),
            (m_pauli, m_ht),
            (ops.Pauli.Z, z_ht_after)]
        is_clifford_list = [is_clifford_rotation(ht)
                            for pauli, ht in rotation_list]
        op_list = [rotation_to_clifford_op(pauli, qubit, ht) if is_clifford
                   else rotation_to_non_clifford_op(pauli, qubit, ht)
                   for is_clifford, (pauli, ht) in
                        zip(is_clifford_list, rotation_list)]

        # Merge adjacent Clifford gates
        for i in reversed(range(len(op_list) - 1)):
            if is_clifford_list[i] and is_clifford_list[i+1]:
                op_list[i] = op_list[i].gate.merged_with(op_list[i+1].gate
                                                         )(qubit)
                is_clifford_list.pop(i+1)
                op_list.pop(i+1)

        # Yield non-identity ops
        for is_clifford, op in zip(is_clifford_list, op_list):
            if is_clifford and op.gate == ops.CliffordGate.I:
                continue
            yield op
Example #8
0
 def from_matrix(mat: np.array) -> 'QasmUGate':
     pre_phase, rotation, post_phase = (
         linalg.deconstruct_single_qubit_matrix_into_angles(mat))
     return QasmUGate(pre_phase/np.pi, rotation/np.pi, post_phase/np.pi)
Example #9
0
def single_qubit_matrix_to_pauli_rotations(
        mat: np.ndarray, tolerance: float = 0
) -> List[Tuple[ops.Pauli, float]]:
    """Implements a single-qubit operation with few rotations.

    Args:
        mat: The 2x2 unitary matrix of the operation to implement.
        tolerance: A limit on the amount of error introduced by the
            construction.

    Returns:
        A list of (Pauli, half_turns) tuples that, when applied in order,
        perform the desired operation.
    """

    tol = linalg.Tolerance(atol=tolerance)
    def is_clifford_rotation(half_turns):
        return tol.all_near_zero_mod(half_turns, 0.5)

    def to_quarter_turns(half_turns):
        return round(2 * half_turns) % 4

    def is_quarter_turn(half_turns):
        return (is_clifford_rotation(half_turns) and
                to_quarter_turns(half_turns) % 2 == 1)

    def is_half_turn(half_turns):
        return (is_clifford_rotation(half_turns) and
                to_quarter_turns(half_turns) == 2)

    def is_no_turn(half_turns):
        return (is_clifford_rotation(half_turns) and
                to_quarter_turns(half_turns) == 0)

    # Decompose matrix
    z_rad_before, y_rad, z_rad_after = (
        linalg.deconstruct_single_qubit_matrix_into_angles(mat))
    z_ht_before = z_rad_before / np.pi - 0.5
    m_ht = y_rad / np.pi
    m_pauli = ops.Pauli.X
    z_ht_after = z_rad_after / np.pi + 0.5

    # Clean up angles
    if is_clifford_rotation(z_ht_before):
        if ((is_quarter_turn(z_ht_before) or is_quarter_turn(z_ht_after)) ^
            (is_half_turn(m_ht) and is_no_turn(z_ht_before-z_ht_after))):
            z_ht_before += 0.5
            z_ht_after -= 0.5
            m_pauli = ops.Pauli.Y
        if is_half_turn(z_ht_before) or is_half_turn(z_ht_after):
            z_ht_before -= 1
            z_ht_after += 1
            m_ht = -m_ht
    if is_no_turn(m_ht):
        z_ht_before += z_ht_after
        z_ht_after = 0
    elif is_half_turn(m_ht):
        z_ht_after -= z_ht_before
        z_ht_before = 0

    # Generate operations
    rotation_list = [
        (ops.Pauli.Z, z_ht_before),
        (m_pauli, m_ht),
        (ops.Pauli.Z, z_ht_after)]
    return [(pauli, ht) for pauli, ht in rotation_list if not is_no_turn(ht)]
Example #10
0
def single_qubit_matrix_to_gates(mat: np.ndarray,
                                 tolerance: float = 0
                                 ) -> List[ops.SingleQubitGate]:
    """Implements a single-qubit operation with few gates.

    Args:
        mat: The 2x2 unitary matrix of the operation to implement.
        tolerance: A limit on the amount of error introduced by the
            construction.

    Returns:
        A list of gates that, when applied in order, perform the desired
            operation.
    """

    tol = linalg.Tolerance(atol=tolerance)

    def is_clifford_rotation(half_turns):
        return tol.all_near_zero_mod(half_turns, 0.5)

    def to_quarter_turns(half_turns):
        return round(2 * half_turns) % 4

    def is_quarter_turn(half_turns):
        return (is_clifford_rotation(half_turns)
                and to_quarter_turns(half_turns) % 2 == 1)

    def is_half_turn(half_turns):
        return (is_clifford_rotation(half_turns)
                and to_quarter_turns(half_turns) == 2)

    def is_no_turn(half_turns):
        return (is_clifford_rotation(half_turns)
                and to_quarter_turns(half_turns) == 0)

    # Decompose matrix
    z_rad_before, y_rad, z_rad_after = (
        linalg.deconstruct_single_qubit_matrix_into_angles(mat))
    z_ht_before = z_rad_before / np.pi - 0.5
    m_ht = y_rad / np.pi
    m_gate = ops.X  # type: ops.Gate
    z_ht_after = z_rad_after / np.pi + 0.5

    # Clean up angles
    if is_clifford_rotation(z_ht_before):
        if ((is_quarter_turn(z_ht_before) or is_quarter_turn(z_ht_after)) ^
            (is_half_turn(m_ht) and is_no_turn(z_ht_before - z_ht_after))):
            z_ht_before += 0.5
            z_ht_after -= 0.5
            m_gate = ops.Y
        if is_half_turn(z_ht_before) or is_half_turn(z_ht_after):
            z_ht_before -= 1
            z_ht_after += 1
            m_ht = -m_ht
    if is_no_turn(m_ht):
        z_ht_before += z_ht_after
        z_ht_after = 0
    elif is_half_turn(m_ht):
        z_ht_after -= z_ht_before
        z_ht_before = 0

    # Generate operations
    rotation_list = [(ops.Z, z_ht_before), (m_gate, m_ht), (ops.Z, z_ht_after)]
    return [gate**ht for gate, ht in rotation_list if not is_no_turn(ht)]