def test_swap_permutation_gate(): no_decomp = lambda op: (isinstance(op, cirq.GateOperation) and op.gate == cirq.SWAP) a, b = cirq.NamedQubit('a'), cirq.NamedQubit('b') expander = cirq.ExpandComposite(no_decomp=no_decomp) circuit = cirq.Circuit.from_ops(cca.SwapPermutationGate()(a, b)) expander(circuit) assert tuple(circuit.all_operations()) == (cirq.SWAP(a, b), ) no_decomp = lambda op: (isinstance(op, cirq.GateOperation) and op.gate == cirq.CZ) expander = cirq.ExpandComposite(no_decomp=no_decomp) circuit = cirq.Circuit.from_ops(cca.SwapPermutationGate(cirq.CZ)(a, b)) expander(circuit) assert tuple(circuit.all_operations()) == (cirq.CZ(a, b), )
def test_get_logical_operations(): a, b, c, d = qubits = cirq.LineQubit.range(4) mapping = dict(zip(qubits, qubits)) operations = [ cirq.ZZ(a, b), cca.SwapPermutationGate()(b, c), cirq.SWAP(a, b), cca.SwapPermutationGate()(c, d), cca.SwapPermutationGate()(b, c), cirq.ZZ(a, b) ] assert list(cca.get_logical_operations(operations, mapping)) == [ cirq.ZZ(a, b), cirq.SWAP(a, c), cirq.ZZ(a, d) ]
def test_update_mapping(): gate = cca.SwapPermutationGate() a, b, c = (cirq.NamedQubit(s) for s in 'abc') mapping = {s: i for i, s in enumerate((a, b, c))} ops = [gate(a, b), gate(b, c)] cca.update_mapping(mapping, ops) assert mapping == {a: 1, b: 2, c: 0}
def test_remove_redundant_acquaintance_opportunities(): device = cca.UnconstrainedAcquaintanceDevice a, b, c, d, e = cirq.LineQubit.range(5) swap = cca.SwapPermutationGate() with pytest.raises(TypeError): ops = [cca.acquaint(a, b)] strategy = cirq.Circuit.from_ops(ops) cca.remove_redundant_acquaintance_opportunities(strategy) ops = [cca.acquaint(a, b), cca.acquaint(a, b)] strategy = cirq.Circuit.from_ops(ops, device=device) diagram_before = """ 0: ───█───█─── │ │ 1: ───█───█─── """ ct.assert_has_diagram(strategy, diagram_before) cca.remove_redundant_acquaintance_opportunities(strategy) cca.remove_redundant_acquaintance_opportunities(strategy) diagram_after = """ 0: ───█─────── │ 1: ───█─────── """ ct.assert_has_diagram(strategy, diagram_after) ops = [ cca.acquaint(a, b), cca.acquaint(c, d), swap(d, e), swap(c, d), cca.acquaint(d, e) ] strategy = cirq.Circuit.from_ops(ops, device=device) diagram_before = """ 0: ───█─────────────────── │ 1: ───█─────────────────── 2: ───█─────────0↦1─────── │ │ 3: ───█───0↦1───1↦0───█─── │ │ 4: ───────1↦0─────────█─── """ ct.assert_has_diagram(strategy, diagram_before) cca.remove_redundant_acquaintance_opportunities(strategy) diagram_after = """ 0: ───█─────────────────── │ 1: ───█─────────────────── 2: ───█─────────0↦1─────── │ │ 3: ───█───0↦1───1↦0─────── │ 4: ───────1↦0───────────── """ ct.assert_has_diagram(strategy, diagram_after)
def test_swap_permutation_gate(): no_decomp = lambda op: (isinstance(op, cirq.GateOperation) and op.gate == cirq.SWAP) a, b = cirq.NamedQubit('a'), cirq.NamedQubit('b') gate = cca.SwapPermutationGate() assert gate.num_qubits() == 2 circuit = cirq.Circuit(gate(a, b)) circuit = cirq.expand_composite(circuit, no_decomp=no_decomp) assert tuple(circuit.all_operations()) == (cirq.SWAP(a, b), ) no_decomp = lambda op: (isinstance(op, cirq.GateOperation) and op.gate == cirq.CZ) circuit = cirq.Circuit(cca.SwapPermutationGate(cirq.CZ)(a, b)) circuit = cirq.expand_composite(circuit, no_decomp=no_decomp) assert tuple(circuit.all_operations()) == (cirq.CZ(a, b), ) assert cirq.commutes(gate, cirq.ZZ) with pytest.raises(TypeError): cirq.commutes(gate, cirq.CCZ)
def test_diagram(): gate = cca.SwapPermutationGate() a, b = cirq.NamedQubit('a'), cirq.NamedQubit('b') circuit = cirq.Circuit.from_ops([gate(a, b)]) actual_text_diagram = circuit.to_text_diagram() expected_text_diagram = """ a: ───0↦1─── │ b: ───1↦0─── """.strip() assert actual_text_diagram == expected_text_diagram
def test_remove_redundant_acquaintance_opportunities(): a, b, c, d, e = cirq.LineQubit.range(5) swap = cca.SwapPermutationGate() ops = [cca.acquaint(a, b), cca.acquaint(a, b)] strategy = cirq.Circuit(ops) diagram_before = """ 0: ───█───█─── │ │ 1: ───█───█─── """ ct.assert_has_diagram(strategy, diagram_before) cca.remove_redundant_acquaintance_opportunities(strategy) diagram_after = """ 0: ───█─────── │ 1: ───█─────── """ ct.assert_has_diagram(strategy, diagram_after) ops = [ cca.acquaint(a, b), cca.acquaint(c, d), swap(d, e), swap(c, d), cca.acquaint(d, e) ] strategy = cirq.Circuit(ops) diagram_before = """ 0: ───█─────────────────── │ 1: ───█─────────────────── 2: ───█─────────0↦1─────── │ │ 3: ───█───0↦1───1↦0───█─── │ │ 4: ───────1↦0─────────█─── """ ct.assert_has_diagram(strategy, diagram_before) cca.remove_redundant_acquaintance_opportunities(strategy) diagram_after = """ 0: ───█─────────────────── │ 1: ───█─────────────────── 2: ───█─────────0↦1─────── │ │ 3: ───█───0↦1───1↦0─────── │ 4: ───────1↦0───────────── """ ct.assert_has_diagram(strategy, diagram_after)
def test_final_mapping(): n_qubits = 10 qubits = cirq.LineQubit.range(n_qubits) initial_mapping = dict(zip(qubits, qubits)) expected_final_mapping = dict(zip(qubits, reversed(qubits))) SWAP = cca.SwapPermutationGate() circuit = cirq.Circuit( cirq.Moment( SWAP(*qubits[i:i + 2]) for i in range(l % 2, n_qubits - 1, 2)) for l in range(n_qubits)) swap_network = ccr.SwapNetwork(circuit, initial_mapping) assert swap_network.final_mapping() == expected_final_mapping
def test_validate_permutation_errors(): validate_permutation = cca.PermutationGate.validate_permutation validate_permutation({}) with pytest.raises(IndexError, message='key and value sets must be the same.'): validate_permutation({0: 2, 1: 3}) with pytest.raises(IndexError, message='keys of the permutation must be non-negative.'): validate_permutation({-1: 0, 0: -1}) with pytest.raises(IndexError, message='key is out of bounds.'): validate_permutation({0: 3, 3: 0}, 2) gate = cca.SwapPermutationGate() assert cirq.circuit_diagram_info(gate, default=None) is None
def test_rectification(): qubits = cirq.LineQubit.range(4) with pytest.raises(TypeError): cca.rectify_acquaintance_strategy(cirq.Circuit()) perm_gate = cca.SwapPermutationGate() operations = [ perm_gate(*qubits[:2]), cca.ACQUAINT(*qubits[2:]), cca.ACQUAINT(*qubits[:2]), perm_gate(*qubits[2:]) ] strategy = cirq.Circuit.from_ops( operations, device=cca.UnconstrainedAcquaintanceDevice) cca.rectify_acquaintance_strategy(strategy) actual_text_diagram = strategy.to_text_diagram().strip() expected_text_diagram = """ 0: ───────0↦1─────────█─── │ │ 1: ───────1↦0─────────█─── 2: ───█─────────0↦1─────── │ │ 3: ───█─────────1↦0─────── """.strip() assert actual_text_diagram == expected_text_diagram strategy = cirq.Circuit.from_ops( operations, device=cca.UnconstrainedAcquaintanceDevice) cca.rectify_acquaintance_strategy(strategy, False) actual_text_diagram = strategy.to_text_diagram() expected_text_diagram = """ 0: ───0↦1───────█───────── │ │ 1: ───1↦0───────█───────── 2: ─────────█───────0↦1─── │ │ 3: ─────────█───────1↦0─── """.strip() assert actual_text_diagram == expected_text_diagram
def test_rectification(): qubits = cirq.LineQubit.range(4) perm_gate = cca.SwapPermutationGate() operations = [ perm_gate(*qubits[:2]), cca.acquaint(*qubits[2:]), cca.acquaint(*qubits[:2]), perm_gate(*qubits[2:]), ] strategy = cirq.Circuit(operations) cca.rectify_acquaintance_strategy(strategy) actual_text_diagram = strategy.to_text_diagram().strip() expected_text_diagram = """ 0: ───────0↦1─────────█─── │ │ 1: ───────1↦0─────────█─── 2: ───█─────────0↦1─────── │ │ 3: ───█─────────1↦0─────── """.strip() assert actual_text_diagram == expected_text_diagram strategy = cirq.Circuit(operations) cca.rectify_acquaintance_strategy(strategy, False) actual_text_diagram = strategy.to_text_diagram() expected_text_diagram = """ 0: ───0↦1───────█───────── │ │ 1: ───1↦0───────█───────── 2: ─────────█───────0↦1─── │ │ 3: ─────────█───────1↦0─── """.strip() assert actual_text_diagram == expected_text_diagram
def test_uses_consistent_swap_gate(): a, b = cirq.LineQubit.range(2) circuit = cirq.Circuit.from_ops( [cca.SwapPermutationGate()(a, b), cca.SwapPermutationGate()(a, b)]) assert cca.uses_consistent_swap_gate(circuit, cirq.SWAP) assert not cca.uses_consistent_swap_gate(circuit, cirq.CZ) circuit = cirq.Circuit.from_ops([ cca.SwapPermutationGate(cirq.CZ)(a, b), cca.SwapPermutationGate(cirq.CZ)(a, b) ]) assert cca.uses_consistent_swap_gate(circuit, cirq.CZ) assert not cca.uses_consistent_swap_gate(circuit, cirq.SWAP) circuit = cirq.Circuit.from_ops([ cca.SwapPermutationGate()(a, b), cca.SwapPermutationGate(cirq.CZ)(a, b) ]) assert not cca.uses_consistent_swap_gate(circuit, cirq.SWAP) assert not cca.uses_consistent_swap_gate(circuit, cirq.CZ)
TYPE_CHECKING, ) import numpy as np import networkx as nx from cirq import circuits, ops, value import cirq.contrib.acquaintance as cca from cirq.contrib.routing.initialization import get_initial_mapping from cirq.contrib.routing.swap_network import SwapNetwork from cirq.contrib.routing.utils import get_time_slices, ops_are_consistent_with_device_graph if TYPE_CHECKING: import cirq SWAP = cca.SwapPermutationGate() QidPair = Tuple[ops.Qid, ops.Qid] def route_circuit_greedily( circuit: circuits.Circuit, device_graph: nx.Graph, **kwargs ) -> SwapNetwork: """Greedily routes a circuit on a given device. Alternates between heuristically picking a few SWAPs to change the mapping and applying all logical operations possible given the new mapping, until all logical operations have been applied. The SWAP selection heuristic is as follows. In every iteration, the remaining two-qubit gates are partitioned into time slices. (See utils.get_time_slices for details.) For each set of candidate SWAPs, the new
def test_swap_gate_eq(): assert cca.SwapPermutationGate() == cca.SwapPermutationGate(cirq.SWAP) assert cca.SwapPermutationGate() != cca.SwapPermutationGate(cirq.CZ) assert cca.SwapPermutationGate(cirq.CZ) == cca.SwapPermutationGate(cirq.CZ)
0: ───4───█───4───╲0╱───2───────2─────────2───█───2───╲0╱───1───────1─────────1───█───1───╲0╱───3─── │ │ │ │ │ │ 1: ───2───█───2───╱1╲───4───█───4───╲0╱───1───█───1───╱1╲───2───█───2───╲0╱───3───█───3───╱1╲───1─── │ │ │ │ 2: ───0───█───0───╲0╱───1───█───1───╱1╲───4───█───4───╲0╱───3───█───3───╱1╲───2───█───2───╲0╱───0─── │ │ │ │ │ │ 3: ───1───█───1───╱1╲───0───█───0───╲0╱───3───█───3───╱1╲───4───█───4───╲0╱───0───█───0───╱1╲───2─── │ │ │ │ 4: ───3───────3─────────3───█───3───╱1╲───0───────0─────────0───█───0───╱1╲───4───────4─────────4─── """ cirq.testing.assert_has_diagram(circuit, expected_diagram) @pytest.mark.parametrize('circuit', [ cirq.Circuit.from_ops( cca.SwapPermutationGate()(*qubit_pair) for qubit_pair in [random.sample(cirq.LineQubit.range(10), 2) for _ in range(20)]) for _ in range(4) ]) def test_return_to_initial_mapping(circuit): qubits = sorted(circuit.all_qubits()) cca.return_to_initial_mapping(circuit) initial_mapping = {q: i for i, q in enumerate(qubits)} mapping = dict(initial_mapping) cca.update_mapping(mapping, circuit.all_operations()) assert mapping == initial_mapping def test_uses_consistent_swap_gate():