Beispiel #1
0
def assert_circuits_with_terminal_measurements_are_equivalent(
        actual: circuits.Circuit, expected: circuits.Circuit,
        atol: float) -> None:
    """Determines if two circuits have equivalent effects.

    The circuits can contain measurements, but the measurements must be at the
    end of the circuit. Circuits are equivalent if, for all possible inputs,
    their outputs (both classical via measurements and quantum via
    not-measurements) are observationally indistinguishable up to a tolerance.

    For example, applying an extra Z gate to an unmeasured qubit changes the
    effect of a circuit. But inserting a Z gate operation just before a
    measurement does not.

    Args:
        actual: The circuit that was actually computed by some process.
        expected: A circuit with the correct function.
        atol: Absolute error tolerance.
    """
    m1, m2 = _canonicalize_up_to_terminal_measurement_phase(actual, expected)

    similar = linalg.allclose_up_to_global_phase(m1, m2, atol=atol)
    if not similar:
        # coverage: ignore
        print("ACTUAL")
        print(actual)
        print("EXPECTED")
        print(expected)

    assert similar
Beispiel #2
0
def assert_circuits_with_terminal_measurements_are_equivalent(
        actual: circuits.Circuit,
        expected: circuits.Circuit,
        atol: float) -> None:
    """Determines if two circuits have equivalent effects.

    The circuits can contain measurements, but the measurements must be at the
    end of the circuit. Circuits are equivalent if, for all possible inputs,
    their outputs (both classical via measurements and quantum via
    not-measurements) are observationally indistinguishable up to a tolerance.

    For example, applying an extra Z gate to an unmeasured qubit changes the
    effect of a circuit. But inserting a Z gate operation just before a
    measurement does not.

    Args:
        actual: The circuit that was actually computed by some process.
        expected: A circuit with the correct function.
        atol: Absolute error tolerance.
    """
    m1, m2 = _canonicalize_up_to_terminal_measurement_phase(actual, expected)

    similar = linalg.allclose_up_to_global_phase(m1, m2, atol=atol)
    if not similar:
        # coverage: ignore
        print("ACTUAL")
        print(actual)
        print("EXPECTED")
        print(expected)

    assert similar
Beispiel #3
0
def assert_circuits_with_terminal_measurements_are_equivalent(
        actual: circuits.Circuit, reference: circuits.Circuit,
        atol: float) -> None:
    """Determines if two circuits have equivalent effects.

    The circuits can contain measurements, but the measurements must be at the
    end of the circuit. Circuits are equivalent if, for all possible inputs,
    their outputs (both classical via measurements and quantum via
    not-measurements) are observationally indistinguishable up to a tolerance.

    For example, applying an extra Z gate to an unmeasured qubit changes the
    effect of a circuit. But inserting a Z gate operation just before a
    measurement does not.

    Args:
        actual: The circuit that was actually computed by some process.
        reference: A circuit with the correct function.
        atol: Absolute error tolerance.
    """
    m1, m2 = _canonicalize_up_to_terminal_measurement_phase(actual, reference)

    assert linalg.allclose_up_to_global_phase(
        m1, m2,
        atol=atol), ("Circuit's effect differs from the reference circuit.\n"
                     '\n'
                     'Diagram of actual circuit:\n'
                     '{}\n'
                     '\n'
                     'Diagram of reference circuit with desired function:\n'
                     '{}\n'.format(actual, reference))
Beispiel #4
0
def test_controlled_op_to_gates_equivalent_on_known_and_random(mat):
    qc = cirq.QubitId()
    qt = cirq.QubitId()
    operations = decompositions.controlled_op_to_native_gates(
        control=qc, target=qt, operation=mat)
    actual_effect = _operations_to_matrix(operations, (qc, qt))
    intended_effect = linalg.kron_with_controls(linalg.CONTROL_TAG, mat)
    assert linalg.allclose_up_to_global_phase(actual_effect, intended_effect)
Beispiel #5
0
def assert_ops_implement_unitary(q0,
                                 q1,
                                 operations,
                                 intended_effect,
                                 atol=0.01):
    actual_effect = _operations_to_matrix(operations, (q0, q1))
    assert linalg.allclose_up_to_global_phase(actual_effect,
                                              intended_effect,
                                              atol=atol)
Beispiel #6
0
def equal_up_to_global_phase(val: Any,
                             other: Any,
                             *,
                             atol: Union[int, float] = 1e-8) -> bool:
    """Determine whether two objects are equal up to global phase.

    If `val` implements a `_equal_up_to_global_phase_` method then it is
    invoked and takes precedence over all other checks:
     - For complex primitive type the magnitudes of the values are compared.
     - For `val` and `other` both iterable of the same length, consecutive
       elements are compared recursively. Types of `val` and `other` does not
       necessarily needs to match each other. They just need to be iterable and
       have the same structure.
     - For all other types, fall back to `_approx_eq_`

    Args:
        val: Source object for approximate comparison.
        other: Target object for approximate comparison.
        atol: The minimum absolute tolerance. This places an upper bound on
        the differences in *magnitudes* of two compared complex numbers.

    Returns:
        True if objects are approximately equal up to phase, False otherwise.
    """

    # Attempt _equal_up_to_global_phase_ for val.
    eq_up_to_phase_getter = getattr(val, '_equal_up_to_global_phase_', None)
    if eq_up_to_phase_getter is not None:
        result = eq_up_to_phase_getter(other, atol)
        if result is not NotImplemented:
            return result

    # Fall back to _equal_up_to_global_phase_ for other.
    other_eq_up_to_phase_getter = getattr(other, '_equal_up_to_global_phase_',
                                          None)
    if other_eq_up_to_phase_getter is not None:
        result = other_eq_up_to_phase_getter(val, atol)
        if result is not NotImplemented:
            return result

    # Fall back to special check for numeric arrays.
    # Defer to numpy automatic type casting to determine numeric type.
    if isinstance(val, Iterable) and isinstance(other, Iterable):
        a = np.asarray(val)
        b = np.asarray(other)
        if a.dtype.kind in 'uifc' and b.dtype.kind in 'uifc':
            return linalg.allclose_up_to_global_phase(a, b, atol=atol)

    # Fall back to approx_eq for compare the magnitude of two numbers.
    if isinstance(val, numbers.Number) and isinstance(other, numbers.Number):
        result = approx_eq(abs(val), abs(other), atol=atol)  # type: ignore
        if result is not NotImplemented:
            return result

    # Fall back to cirq approx_eq for remaining types.
    return approx_eq(val, other, atol=atol)
Beispiel #7
0
def assert_circuits_with_terminal_measurements_are_equivalent(
        actual: circuits.AbstractCircuit, reference: circuits.AbstractCircuit,
        atol: float) -> None:
    """Determines if two circuits have equivalent effects.

    The circuits can contain measurements, but the measurements must be at the
    end of the circuit. Circuits are equivalent if, for all possible inputs,
    their outputs (classical bits for lines terminated with measurement and
    qubits for lines without measurement) are observationally indistinguishable
    up to a tolerance. Note that under this definition of equivalence circuits
    that differ solely in the overall phase of the post-measurement state of
    measured qubits are considered equivalent.

    For example, applying an extra Z gate to an unmeasured qubit changes the
    effect of a circuit. But inserting a Z gate operation just before a
    measurement does not.

    Args:
        actual: The circuit that was actually computed by some process.
        reference: A circuit with the correct function.
        atol: Absolute error tolerance.
    """
    # pylint: disable=unused-variable
    __tracebackhide__ = True
    # pylint: enable=unused-variable

    measured_qubits_actual = {
        qubit
        for op in actual.all_operations() if protocols.is_measurement(op)
        for qubit in op.qubits
    }
    measured_qubits_reference = {
        qubit
        for op in reference.all_operations() if protocols.is_measurement(op)
        for qubit in op.qubits
    }
    assert actual.are_all_measurements_terminal()
    assert reference.are_all_measurements_terminal()
    assert measured_qubits_actual == measured_qubits_reference

    all_qubits = actual.all_qubits().union(reference.all_qubits())

    matrix_actual = actual.unitary(qubits_that_should_be_present=all_qubits)
    matrix_reference = reference.unitary(
        qubits_that_should_be_present=all_qubits)

    n_qubits = len(all_qubits)
    n = matrix_actual.shape[0]
    assert n == 1 << n_qubits
    assert matrix_actual.shape == matrix_reference.shape == (n, n)

    # Consider the action of the two circuits Ca and Cr on state |x>:
    #
    #     |ya> = Ca|x>
    #     |yr> = Cr|x>
    #
    # Ca and Cr are equivalent according to the definition above iff
    # for each |x>:
    #  - probability of each measurement outcome is the same for |ya>
    #    and |yr> (across measured qubits),
    #  - amplitudes of each post-measurement state are the same for |ya>
    #    and |yr> except perhaps for an overall phase factor.
    #
    # These conditions are satisfied iff the matrices of the two circuits
    # are identical except perhaps for an overall phase factor for each
    # rectangular block spanning rows corresponding to the measurement
    # subspaces and all columns.
    #
    # Note two special cases of the rule above:
    #  - if no qubits are measured then the circuits are equivalent if
    #    their matrices are identical except for the global phase factor,
    #  - if all qubits are measured then the circuits are equivalent if
    #    their matrices differ by a diagonal unitary factor.
    subspaces = _measurement_subspaces(measured_qubits_actual, n_qubits)
    for subspace in subspaces:
        block_actual = matrix_actual[subspace, :]
        block_reference = matrix_reference[subspace, :]
        assert linalg.allclose_up_to_global_phase(
            block_actual, block_reference, atol=atol), (
                "Circuit's effect differs from the reference circuit.\n"
                '\n'
                'Diagram of actual circuit:\n'
                '{}\n'
                '\n'
                'Diagram of reference circuit with desired function:\n'
                '{}\n'.format(actual, reference))
Beispiel #8
0
def assert_gates_implement_unitary(gates, intended_effect):
    actual_effect = _gates_to_matrix(gates)
    assert linalg.allclose_up_to_global_phase(actual_effect, intended_effect)
Beispiel #9
0
def test_single_qubit_op_to_framed_phase_form_output_on_example_case():
    u, t, g = decompositions.single_qubit_op_to_framed_phase_form(
        (ops.Y**0.25).matrix())
    assert linalg.allclose_up_to_global_phase(u, (ops.X**0.5).matrix())
    assert abs(t - (1 + 1j) * math.sqrt(0.5)) < 0.00001
    assert abs(g - 1) < 0.00001