Ejemplo n.º 1
0
def test_map_operations_respects_tags_to_ignore():
    q = cirq.LineQubit.range(2)
    c = cirq.Circuit(cirq.CNOT(*q), cirq.CNOT(*q).with_tags("ignore"), cirq.CNOT(*q))
    cirq.testing.assert_same_circuits(
        cirq.Circuit(cirq.Z.on_each(*q), cirq.CNOT(*q).with_tags("ignore"), cirq.Z.on_each(*q)),
        cirq.map_operations(c, lambda op, i: cirq.Z.on_each(*op.qubits), tags_to_ignore=["ignore"]),
    )
Ejemplo n.º 2
0
def test_map_operations_can_drop_operations():
    q = cirq.LineQubit.range(2)
    c = cirq.Circuit(cirq.X(q[0]), cirq.Y(q[1]), cirq.X(q[1]), cirq.Y(q[0]))
    c_mapped = cirq.map_operations(
        c, lambda op, _: op if op.gate == cirq.X else [])
    c_expected = cirq.Circuit(cirq.Moment(cirq.X(q[0])),
                              cirq.Moment(cirq.X(q[1])))
    cirq.testing.assert_same_circuits(c_mapped, c_expected)
Ejemplo n.º 3
0
def test_map_operations_can_add_qubits_if_flag_false():
    q = cirq.LineQubit.range(2)
    c = cirq.Circuit(cirq.H(q[0]))
    c_mapped = cirq.map_operations(c,
                                   lambda *_: cirq.CNOT(q[0], q[1]),
                                   raise_if_add_qubits=False)
    cirq.testing.assert_same_circuits(c_mapped,
                                      cirq.Circuit(cirq.CNOT(q[0], q[1])))
Ejemplo n.º 4
0
def test_map_operations_does_not_insert_too_many_moments():
    q = cirq.LineQubit.range(5)
    c_orig = cirq.Circuit(
        cirq.CX(q[0], q[1]),
        cirq.CX(q[3], q[2]),
        cirq.CX(q[3], q[4]),
    )

    def map_func(op: cirq.Operation, _: int) -> cirq.OP_TREE:
        if op.gate == cirq.CX:
            yield cirq.Z.on_each(*op.qubits)
            yield cirq.CX(*op.qubits)
            yield cirq.Z.on_each(*op.qubits)
        return op

    cirq.testing.assert_has_diagram(
        c_orig,
        '''
0: ───@───────
      │
1: ───X───────

2: ───X───────
      │
3: ───@───@───
          │
4: ───────X───
''',
    )

    c_mapped = cirq.map_operations(c_orig, map_func)
    circuit_op = cirq.CircuitOperation(
        cirq.FrozenCircuit(cirq.Z.on_each(q[0], q[1]), cirq.CNOT(q[0], q[1]),
                           cirq.Z.on_each(q[0], q[1])))
    c_expected = cirq.Circuit(
        circuit_op.with_qubits(
            q[0], q[1]).mapped_op().with_tags('<mapped_circuit_op>'),
        circuit_op.with_qubits(
            q[3], q[2]).mapped_op().with_tags('<mapped_circuit_op>'),
        circuit_op.with_qubits(
            q[3], q[4]).mapped_op().with_tags('<mapped_circuit_op>'),
    )
    cirq.testing.assert_same_circuits(c_mapped, c_expected)

    cirq.testing.assert_has_diagram(
        cirq.map_operations_and_unroll(c_orig, map_func),
        '''
0: ───Z───@───Z───────────────
          │
1: ───Z───X───Z───────────────

2: ───Z───X───Z───────────────
          │
3: ───Z───@───Z───Z───@───Z───
                      │
4: ───────────────Z───X───Z───
''',
    )
Ejemplo n.º 5
0
def test_unroll_circuit_op_and_variants():
    q = cirq.LineQubit.range(2)
    c = cirq.Circuit(cirq.X(q[0]), cirq.CNOT(q[0], q[1]), cirq.X(q[0]))
    cirq.testing.assert_has_diagram(
        c,
        '''
0: ───X───@───X───
          │
1: ───────X───────
''',
    )
    mapped_circuit = cirq.map_operations(
        c, lambda op, i: [cirq.Z(q[1])] * 2 if op.gate == cirq.CNOT else op)
    mapped_circuit_deep = cirq.Circuit(
        [
            cirq.Moment(cirq.CircuitOperation(cirq.FrozenCircuit(m)))
            for m in mapped_circuit[:-1]
        ],
        mapped_circuit[-1],
    )
    for unroller in [
            cirq.unroll_circuit_op_greedy_earliest,
            cirq.unroll_circuit_op_greedy_frontier,
            cirq.unroll_circuit_op,
    ]:
        cirq.testing.assert_same_circuits(
            unroller(mapped_circuit),
            unroller(mapped_circuit_deep, tags_to_check=None, deep=True))

    cirq.testing.assert_has_diagram(
        cirq.unroll_circuit_op(mapped_circuit),
        '''
0: ───X───────────X───

1: ───────Z───Z───────
''',
    )
    cirq.testing.assert_has_diagram(
        cirq.unroll_circuit_op_greedy_earliest(mapped_circuit),
        '''
0: ───X───────X───

1: ───Z───Z───────
''',
    )
    cirq.testing.assert_has_diagram(
        cirq.unroll_circuit_op_greedy_frontier(mapped_circuit),
        '''
0: ───X───────X───

1: ───────Z───Z───
''',
    )
Ejemplo n.º 6
0
def test_map_operations_deep_respects_tags_to_ignore():
    q = cirq.LineQubit.range(2)
    c_nested = cirq.FrozenCircuit(cirq.CX(*q),
                                  cirq.CX(*q).with_tags("ignore"), cirq.CX(*q))
    c_nested_mapped = cirq.FrozenCircuit(cirq.CZ(*q),
                                         cirq.CX(*q).with_tags("ignore"),
                                         cirq.CZ(*q))
    c_orig = cirq.Circuit(
        c_nested,
        cirq.CircuitOperation(c_nested).repeat(4).with_tags("ignore"),
        c_nested,
        cirq.CircuitOperation(
            cirq.FrozenCircuit(
                cirq.CircuitOperation(c_nested).repeat(5).with_tags(
                    "preserve_tag"),
                cirq.CircuitOperation(c_nested).repeat(6).with_tags("ignore"),
                cirq.CircuitOperation(c_nested).repeat(7),
            )),
        c_nested,
    )
    c_expected = cirq.Circuit(
        c_nested_mapped,
        cirq.CircuitOperation(c_nested).repeat(4).with_tags("ignore"),
        c_nested_mapped,
        cirq.CircuitOperation(
            cirq.FrozenCircuit(
                cirq.CircuitOperation(c_nested_mapped).repeat(5).with_tags(
                    "preserve_tag"),
                cirq.CircuitOperation(c_nested).repeat(6).with_tags("ignore"),
                cirq.CircuitOperation(c_nested_mapped).repeat(7),
            )),
        c_nested_mapped,
    )
    cirq.testing.assert_same_circuits(
        cirq.map_operations(
            c_orig,
            lambda op, _: cirq.CZ(*op.qubits) if op.gate == cirq.CX else op,
            tags_to_ignore=["ignore"],
            deep=True,
        ),
        c_expected,
    )
Ejemplo n.º 7
0
def test_map_operations_can_write_new_gates_inline():
    x = cirq.NamedQubit('x')
    y = cirq.NamedQubit('y')
    z = cirq.NamedQubit('z')
    c = cirq.Circuit(
        cirq.CZ(x, y),
        cirq.Y(x),
        cirq.Z(x),
        cirq.X(y),
        cirq.CNOT(y, z),
        cirq.Z(y),
        cirq.Z(x),
        cirq.CNOT(y, z),
        cirq.CNOT(z, y),
    )
    cirq.testing.assert_has_diagram(
        c,
        '''
x: ───@───Y───Z───Z───────────
      │
y: ───@───X───@───Z───@───X───
              │       │   │
z: ───────────X───────X───@───
''',
    )
    expected_diagram = '''
x: ───X───X───X───X───────────

y: ───X───X───X───X───X───X───

z: ───────────X───────X───X───
'''
    cirq.testing.assert_has_diagram(
        cirq.map_operations(c, lambda op, _: cirq.X.on_each(*op.qubits)),
        expected_diagram)
    cirq.testing.assert_has_diagram(
        cirq.map_operations_and_unroll(
            c, lambda op, _: cirq.X.on_each(*op.qubits)),
        expected_diagram,
    )
Ejemplo n.º 8
0
def _convert_to_circuit_with_drift(
        simulator: PhasedFSimEngineSimulator,
        circuit: cirq.AbstractCircuit) -> cirq.Circuit:
    def map_func(op: cirq.Operation, _) -> cirq.Operation:

        if op.gate is None:
            raise IncompatibleMomentError(f'Operation {op} has a missing gate')

        if (isinstance(op.gate, (cirq.MeasurementGate, cirq.WaitGate))
                or cirq.num_qubits(op.gate) == 1):
            return op

        translated = simulator.gates_translator(op.gate)
        if translated is None:
            raise IncompatibleMomentError(
                f'Moment contains non-single qubit operation '
                f'{op} with unsupported gate')

        a, b = op.qubits
        return simulator.create_gate_with_drift(a, b, translated).on(a, b)

    return cirq.map_operations(circuit, map_func).unfreeze(copy=False)
Ejemplo n.º 9
0
def test_map_operations_deep_subcircuits():
    q = cirq.LineQubit.range(5)
    c_orig = cirq.Circuit(
        cirq.CX(q[0], q[1]),
        cirq.CX(q[3], q[2]),
        cirq.CX(q[3], q[4]),
    )
    c_orig_with_circuit_ops = cirq.Circuit(
        cirq.CircuitOperation(
            cirq.FrozenCircuit([
                cirq.CircuitOperation(cirq.FrozenCircuit(op))
                for op in c_orig.all_operations()
            ])))

    def map_func(op: cirq.Operation, _: int) -> cirq.OP_TREE:
        yield [
            cirq.Z.on_each(*op.qubits),
            cirq.CX(*op.qubits),
            cirq.Z.on_each(*op.qubits),
        ] if op.gate == cirq.CX else op

    c_mapped = cirq.map_operations(c_orig_with_circuit_ops,
                                   map_func,
                                   deep=True)
    c_mapped = cirq.unroll_circuit_op(c_mapped, deep=True, tags_to_check=None)
    cirq.testing.assert_has_diagram(
        c_mapped,
        '''
0: ───Z───@───Z───────────────
          │
1: ───Z───X───Z───────────────

2: ───Z───X───Z───────────────
          │
3: ───Z───@───Z───Z───@───Z───
                      │
4: ───────────────Z───X───Z───
''',
    )
Ejemplo n.º 10
0
def test_unroll_circuit_op_and_variants():
    q = cirq.LineQubit.range(2)
    c = cirq.Circuit(cirq.X(q[0]), cirq.CNOT(q[0], q[1]), cirq.X(q[0]))
    cirq.testing.assert_has_diagram(
        c,
        '''
0: ───X───@───X───
          │
1: ───────X───────
''',
    )
    mapped_circuit = cirq.map_operations(
        c, lambda op, i: [cirq.Z(q[1])] * 2 if op.gate == cirq.CNOT else op)
    cirq.testing.assert_has_diagram(
        cirq.unroll_circuit_op(mapped_circuit),
        '''
0: ───X───────────X───

1: ───────Z───Z───────
''',
    )
    cirq.testing.assert_has_diagram(
        cirq.unroll_circuit_op_greedy_earliest(mapped_circuit),
        '''
0: ───X───────X───

1: ───Z───Z───────
''',
    )
    cirq.testing.assert_has_diagram(
        cirq.unroll_circuit_op_greedy_frontier(mapped_circuit),
        '''
0: ───X───────X───

1: ───────Z───Z───
''',
    )
Ejemplo n.º 11
0
def merge_swap_rzz_and_2q_unitaries(
    circuit: 'cirq.AbstractCircuit',
    *,
    context: Optional['cirq.TransformerContext'] = None,
    merged_swap_rzz_tag: str = "_merged_swap_rzz",
    merged_2q_component_tag: str = "_merged_2q_unitaries",
    intermediate_result_tag: Optional[str] = None,
) -> 'cirq.Circuit':
    """Merges 2-qubit connected components and adjacent `cirq.SWAP` and `cirq.ZZPowGate` gates.

    Does the following two transformations, in that order:
    1. Merges adjacent occurrences of `cirq.SWAP` and `cirq.ZZPowGate` into a
    `cirq.CircuitOperation` tagged with `merged_swap_rzz_tag`.
    2. Merges connected components of 1 and 2 qubit unitaries in the circuit into a
    `cirq.CircuitOperation` tagged with `merged_2q_component_tag`, ignoring the newly
    introduced tagged circuit operations added in Step-1.

    Args:
        circuit: Input circuit to transform. It will not be modified.
        context: `cirq.TransformerContext` storing common configurable options for transformers.
        merged_swap_rzz_tag: Tag to apply on newly introduced circuit operations wrapping adjacent
            `cirq.SWAP` and `cirq.ZZPowGate`s.
        merged_2q_component_tag: Tag to apply on newly introduced circuit operations wrapping
            connected components of 1 and 2 qubit unitaries.
        intermediate_result_tag: If specified, the tag is added to newly introduced both the newly
            introduced circuit operations encapsulating swap_rzz or 2q connected component.

    Returns:
        Copy of the transformed input circuit.

    Raises:
          ValueError: If merged_2q_component_tag and merged_swap_rzz_tag are equal.
    """
    if merged_2q_component_tag == merged_swap_rzz_tag:
        raise ValueError(
            "merged_swap_rzz_tag and merged_2q_component_tag should be different."
        )

    def merge_func_swap_rzz(ops1: Sequence['cirq.Operation'],
                            ops2: Sequence['cirq.Operation']) -> bool:
        if not (len(ops1) == 1 and len(ops2) == 1):
            return False
        for op1, op2 in itertools.permutations([ops1[0], ops2[0]]):
            if op1.gate == cirq.SWAP and isinstance(op2.gate, cirq.ZZPowGate):
                return True
        return False

    tags_to_ignore = context.tags_to_ignore if context else ()
    deep = context.deep if context else False
    circuit = cirq.merge_operations_to_circuit_op(
        circuit,
        merge_func_swap_rzz,
        tags_to_ignore=tags_to_ignore,
        merged_circuit_op_tag=merged_swap_rzz_tag,
        deep=deep,
    )

    circuit = cirq.merge_k_qubit_unitaries_to_circuit_op(
        circuit,
        k=2,
        tags_to_ignore=tuple(tags_to_ignore) + (merged_swap_rzz_tag, ),
        merged_circuit_op_tag=merged_2q_component_tag,
        deep=deep,
    )

    if intermediate_result_tag is not None:
        merged_cop_tags = {merged_swap_rzz_tag, merged_2q_component_tag}
        circuit = cirq.map_operations(
            circuit,
            map_func=lambda op, _: op
            if merged_cop_tags.isdisjoint(op.tags) else op.with_tags(
                cast(str, intermediate_result_tag)),
            tags_to_ignore=tags_to_ignore,
            deep=True,
        )
    return circuit.unfreeze(copy=False)
Ejemplo n.º 12
0
def test_map_operations_raises_qubits_not_subset():
    q = cirq.LineQubit.range(3)
    with pytest.raises(ValueError, match='should act on a subset'):
        _ = cirq.map_operations(
            cirq.Circuit(cirq.CNOT(q[0], q[1])), lambda op, i: cirq.CNOT(q[1], q[2])
        )
Ejemplo n.º 13
0
def test_map_operations_deep_subcircuits():
    q = cirq.LineQubit.range(5)
    c_orig = cirq.Circuit(cirq.CX(q[0], q[1]), cirq.CX(q[3], q[2]), cirq.CX(q[3], q[4]))
    c_orig_with_circuit_ops = cirq.Circuit(
        cirq.CircuitOperation(
            cirq.FrozenCircuit(
                [
                    cirq.CircuitOperation(cirq.FrozenCircuit(op)).repeat(2).with_tags("internal")
                    for op in c_orig.all_operations()
                ]
            )
        )
        .repeat(6)
        .with_tags("external")
    )

    def map_func(op: cirq.Operation, _: int) -> cirq.OP_TREE:
        yield [
            cirq.Z.on_each(*op.qubits),
            cirq.CX(*op.qubits),
            cirq.Z.on_each(*op.qubits),
        ] if op.gate == cirq.CX else op

    cirq.testing.assert_has_diagram(
        c_orig_with_circuit_ops,
        '''
      [       [ 0: ───@─── ]                                                               ]
      [ 0: ───[       │    ]────────────────────────────────────────────────────────────── ]
      [       [ 1: ───X─── ](loops=2)['internal']                                          ]
      [       │                                                                            ]
      [ 1: ───#2────────────────────────────────────────────────────────────────────────── ]
      [                                                                                    ]
      [       [ 2: ───X─── ]                                                               ]
0: ───[ 2: ───[       │    ]────────────────────────────────────────────────────────────── ]────────────────────────
      [       [ 3: ───@─── ](loops=2)['internal']                                          ]
      [       │                                                                            ]
      [       │                                     [ 3: ───@─── ]                         ]
      [ 3: ───#2────────────────────────────────────[       │    ]──────────────────────── ]
      [                                             [ 4: ───X─── ](loops=2)['internal']    ]
      [                                             │                                      ]
      [ 4: ─────────────────────────────────────────#2──────────────────────────────────── ](loops=6)['external']
      │
1: ───#2────────────────────────────────────────────────────────────────────────────────────────────────────────────
      │
2: ───#3────────────────────────────────────────────────────────────────────────────────────────────────────────────
      │
3: ───#4────────────────────────────────────────────────────────────────────────────────────────────────────────────
      │
4: ───#5────────────────────────────────────────────────────────────────────────────────────────────────────────────
''',
    )

    c_mapped = cirq.map_operations(c_orig_with_circuit_ops, map_func, deep=True)
    for unroller in [
        cirq.unroll_circuit_op,
        cirq.unroll_circuit_op_greedy_earliest,
        cirq.unroll_circuit_op_greedy_frontier,
    ]:
        cirq.testing.assert_has_diagram(
            unroller(c_mapped, deep=True),
            '''
      [       [ 0: ───Z───@───Z─── ]                                                                       ]
      [ 0: ───[           │        ]────────────────────────────────────────────────────────────────────── ]
      [       [ 1: ───Z───X───Z─── ](loops=2)['internal']                                                  ]
      [       │                                                                                            ]
      [ 1: ───#2────────────────────────────────────────────────────────────────────────────────────────── ]
      [                                                                                                    ]
      [       [ 2: ───Z───X───Z─── ]                                                                       ]
0: ───[ 2: ───[           │        ]────────────────────────────────────────────────────────────────────── ]────────────────────────
      [       [ 3: ───Z───@───Z─── ](loops=2)['internal']                                                  ]
      [       │                                                                                            ]
      [       │                                             [ 3: ───Z───@───Z─── ]                         ]
      [ 3: ───#2────────────────────────────────────────────[           │        ]──────────────────────── ]
      [                                                     [ 4: ───Z───X───Z─── ](loops=2)['internal']    ]
      [                                                     │                                              ]
      [ 4: ─────────────────────────────────────────────────#2──────────────────────────────────────────── ](loops=6)['external']
      │
1: ───#2────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
      │
2: ───#3────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
      │
3: ───#4────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
      │
4: ───#5────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
''',
        )