Ejemplo n.º 1
0
def test_merge_operations_respects_tags_to_ignore():
    q = cirq.LineQubit.range(2)
    c = cirq.Circuit(
        cirq.CZ(*q),
        cirq.Moment(cirq.X(q[0]), cirq.Y(q[1]).with_tags("ignore")),
        cirq.Moment(cirq.X(q[0]).with_tags("ignore"), cirq.Y(q[1])),
        cirq.CZ(*q),
        [cirq.CNOT(*q), cirq.CNOT(*q).with_tags("ignore"), cirq.CNOT(*q)],
        cirq.CZ(*q),
    )
    c_merged = cirq.Circuit(
        cirq.Moment(cirq.CZ(*q)),
        cirq.Moment(cirq.Y(q[1]).with_tags("ignore")),
        cirq.Moment(cirq.X(q[0]).with_tags("ignore")),
        cirq.Moment(cirq.CZ(*q)),
        cirq.Moment(),
        cirq.Moment(cirq.CNOT(*q).with_tags("ignore")),
        cirq.Moment(cirq.CZ(*q)),
        cirq.Moment(),
    )

    def merge_func(op1, op2):
        """Artificial example where a CZ will absorb any merge-able operation."""
        return op1 if op1.gate == cirq.CZ else (op2 if op2.gate == cirq.CZ else None)

    cirq.testing.assert_same_circuits(
        cirq.merge_operations(c, merge_func, tags_to_ignore=["ignore"]), c_merged
    )
Ejemplo n.º 2
0
def test_merge_operations_deep():
    q = cirq.LineQubit.range(2)
    h_cz_y = [cirq.H(q[0]), cirq.CZ(*q), cirq.Y(q[1])]
    m_cz_m = [cirq.Moment(), cirq.Moment(cirq.CZ(*q)), cirq.Moment()]
    c_orig = cirq.Circuit(
        h_cz_y,
        cirq.Moment(cirq.X(q[0]).with_tags("ignore"), cirq.Y(q[1])),
        cirq.CircuitOperation(cirq.FrozenCircuit(h_cz_y)).repeat(6).with_tags("ignore"),
        [cirq.CNOT(*q), cirq.CNOT(*q)],
        cirq.CircuitOperation(cirq.FrozenCircuit(h_cz_y)).repeat(4),
        [cirq.CNOT(*q), cirq.CZ(*q), cirq.CNOT(*q)],
        cirq.CircuitOperation(cirq.FrozenCircuit(h_cz_y)).repeat(5).with_tags("preserve_tag"),
    )
    c_expected = cirq.Circuit(
        m_cz_m,
        cirq.Moment(cirq.X(q[0]).with_tags("ignore")),
        cirq.CircuitOperation(cirq.FrozenCircuit(h_cz_y)).repeat(6).with_tags("ignore"),
        [cirq.CNOT(*q), cirq.CNOT(*q)],
        cirq.CircuitOperation(cirq.FrozenCircuit(m_cz_m)).repeat(4),
        [cirq.CZ(*q), cirq.Moment(), cirq.Moment()],
        cirq.CircuitOperation(cirq.FrozenCircuit(m_cz_m)).repeat(5).with_tags("preserve_tag"),
        strategy=cirq.InsertStrategy.NEW,
    )

    def merge_func(op1, op2):
        """Artificial example where a CZ will absorb any merge-able operation."""
        for op in [op1, op2]:
            if op.gate == cirq.CZ:
                return op
        return None

    cirq.testing.assert_same_circuits(
        cirq.merge_operations(c_orig, merge_func, tags_to_ignore=["ignore"], deep=True), c_expected
    )
Ejemplo n.º 3
0
def test_merge_operations_merges_connected_component():
    c_orig = _create_circuit_to_merge()
    cirq.testing.assert_has_diagram(
        c_orig,
        '''
0: ───H───@───@───H───@───X───────@───────X───X['ignore']───@───
          │   │       │           │                         │
1: ───H───┼───X───────@───────Y───X───@───────Y─────────────X───
          │                           │
2: ───H───X───────────────────────────X─────────────────────────
''',
    )

    def merge_func(op1, op2):
        """Artificial example where a CZ will absorb any merge-able operation."""
        for op in [op1, op2]:
            if op.gate == cirq.CZ:
                return op
        return None

    c_new = cirq.merge_operations(c_orig, merge_func)
    cirq.testing.assert_has_diagram(
        c_new,
        '''
0: ───H───@───────────@───────────────────────────@───
          │           │                           │
1: ───────┼───────────@───────────────@───────Y───X───
          │                           │
2: ───H───X───────────────────────────X───────────────''',
    )
Ejemplo n.º 4
0
def test_merge_operations_nothing_to_merge():
    def fail_if_called_func(*_):
        assert False

    # Empty Circuit.
    c = cirq.Circuit()
    assert cirq.merge_operations(c, fail_if_called_func) == c
    # Single moment
    q = cirq.LineQubit.range(3)
    c += cirq.Moment(cirq.CZ(*q[:2]))
    assert cirq.merge_operations(c, fail_if_called_func) == c
    # Multi moment with disjoint operations + global phase operation.
    c += cirq.Moment(cirq.X(q[2]), cirq.global_phase_operation(1j))
    assert cirq.merge_operations(c, fail_if_called_func) == c
    # Tagged operations to be ignored.
    c += cirq.Moment(cirq.CNOT(*q[:2]).with_tags("ignore"))
    assert cirq.merge_operations(c, fail_if_called_func, tags_to_ignore=["ignore"]) == c
Ejemplo n.º 5
0
def test_merge_operations_does_not_merge_measurements_behind_ccos():
    q = cirq.LineQubit.range(2)
    measure_op = cirq.measure(q[0], key="a")
    cco_op = cirq.X(q[1]).with_classical_controls("a")

    def merge_func(op1, op2):
        return cirq.I(
            *op1.qubits) if op1 == measure_op and op2 == measure_op else None

    circuit = cirq.Circuit([cirq.H(q[0]), measure_op, cco_op] * 2)
    cirq.testing.assert_same_circuits(
        cirq.merge_operations(circuit, merge_func), circuit)

    circuit = cirq.Circuit(
        [cirq.H(q[0]), measure_op, cco_op, measure_op, measure_op] * 2)
    expected_circuit = cirq.Circuit(
        [cirq.H(q[0]), measure_op, cco_op,
         cirq.I(q[0])] * 2)
    cirq.testing.assert_same_circuits(
        cirq.align_left(cirq.merge_operations(circuit, merge_func)),
        expected_circuit)
Ejemplo n.º 6
0
def test_merge_operations_complexity(op_density):
    prng = cirq.value.parse_random_state(11011)
    circuit = cirq.testing.random_circuit(20, 500, op_density, random_state=prng)
    for merge_func in [
        lambda _, __: None,
        lambda op1, _: op1,
        lambda _, op2: op2,
        lambda op1, op2: (op1, op2, None)[prng.choice(3)],
    ]:

        def wrapped_merge_func(op1, op2):
            wrapped_merge_func.num_function_calls += 1
            return merge_func(op1, op2)

        wrapped_merge_func.num_function_calls = 0
        _ = cirq.merge_operations(circuit, wrapped_merge_func)
        total_operations = len([*circuit.all_operations()])
        assert wrapped_merge_func.num_function_calls <= 2 * total_operations
Ejemplo n.º 7
0
def test_merge_operations_deterministic_order(qubit_order):
    q = cirq.LineQubit.range(2)
    c_orig = cirq.Circuit(cirq.identity_each(*q), cirq.H.on_each(q[i] for i in qubit_order))
    cirq.testing.assert_has_diagram(
        c_orig,
        '''
0: ───I───H───
      │
1: ───I───H───''',
    )
    c_new = cirq.merge_operations(
        c_orig, lambda op1, op2: op2 if isinstance(op1.gate, cirq.IdentityGate) else None
    )
    cirq.testing.assert_has_diagram(
        c_new,
        '''
0: ───H───────

1: ───────H───''',
    )
Ejemplo n.º 8
0
def test_merge_operations_raises():
    q = cirq.LineQubit.range(3)
    c = cirq.Circuit(cirq.CZ(*q[:2]), cirq.X(q[0]))
    with pytest.raises(ValueError, match='must act on a subset of qubits'):
        cirq.merge_operations(c, lambda *_: cirq.X(q[2]))