def test_multiple_composite_default(): q0, q1 = cirq.LineQubit.range(2) cnot = cirq.CNOT(q0, q1) circuit = cirq.Circuit() circuit.append([cnot, cnot]) circuit = cirq.expand_composite(circuit) expected = cirq.Circuit() decomp = [cirq.Y(q1)**-0.5, cirq.CZ(q0, q1), cirq.Y(q1)**0.5] expected.append([decomp, decomp]) assert_equal_mod_empty(expected, circuit)
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_non_recursive_expansion(): qubits = [cirq.NamedQubit(s) for s in 'xy'] no_decomp = lambda op: (isinstance(op, cirq.GateOperation) and op.gate == cirq.ISWAP) unexpanded_circuit = cirq.Circuit(cirq.ISWAP(*qubits)) circuit = cirq.expand_composite(unexpanded_circuit, no_decomp=no_decomp) assert circuit == unexpanded_circuit no_decomp = lambda op: (isinstance(op, cirq.GateOperation) and isinstance( op.gate, (cirq.CNotPowGate, cirq.HPowGate))) circuit = cirq.expand_composite(unexpanded_circuit, no_decomp=no_decomp) actual_text_diagram = circuit.to_text_diagram().strip() expected_text_diagram = """ x: ───@───H───X───S───X───S^-1───H───@─── │ │ │ │ y: ───X───────@───────@──────────────X─── """.strip() assert actual_text_diagram == expected_text_diagram
def test_circuit_diagrams(part_size, subgraph): qubits = cirq.LineQubit.range(2 * part_size) gate = cca.BipartiteSwapNetworkGate(subgraph, part_size) circuit = cirq.Circuit(gate(*qubits)) diagram = circuit_diagrams['undecomposed', subgraph, part_size] cirq.testing.assert_has_diagram(circuit, diagram) no_decomp = lambda op: isinstance(op.gate, ( cca.AcquaintanceOpportunityGate, cca.SwapPermutationGate)) circuit = cirq.expand_composite(circuit, no_decomp=no_decomp) diagram = circuit_diagrams['decomposed', subgraph, part_size] cirq.testing.assert_has_diagram(circuit, diagram)
def test_decompose_returns_not_flat_op_tree(): class DummyGate(cirq.SingleQubitGate): def _decompose_(self, qubits): (q0, ) = qubits # Yield a tuple of gates instead of yielding a gate yield cirq.X(q0), q0 = cirq.NamedQubit('q0') circuit = cirq.Circuit(DummyGate()(q0)) circuit = cirq.expand_composite(circuit) expected = cirq.Circuit(cirq.X(q0)) assert_equal_mod_empty(expected, circuit)
def test_mix_composite_non_composite(): q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit(cirq.X(q0), cirq.CNOT(q0, q1), cirq.X(q1)) circuit = cirq.expand_composite(circuit) expected = cirq.Circuit( cirq.X(q0), cirq.Y(q1)**-0.5, cirq.CZ(q0, q1), cirq.Y(q1)**0.5, cirq.X(q1), strategy=cirq.InsertStrategy.NEW, ) assert_equal_mod_empty(expected, circuit)
def test_recursive_composite(): q0, q1 = cirq.LineQubit.range(2) swap = cirq.SWAP(q0, q1) circuit = cirq.Circuit() circuit.append(swap) circuit = cirq.expand_composite(circuit) expected = cirq.Circuit( cirq.Y(q1)**-0.5, cirq.CZ(q0, q1), cirq.Y(q1)**0.5, cirq.Y(q0)**-0.5, cirq.CZ(q1, q0), cirq.Y(q0)**0.5, cirq.Y(q1)**-0.5, cirq.CZ(q0, q1), cirq.Y(q1)**0.5, ) assert_equal_mod_empty(expected, circuit)
def test_decompose_returns_deep_op_tree(): class DummyGate(cirq.testing.TwoQubitGate): def _decompose_(self, qubits): q0, q1 = qubits # Yield a tuple yield ((cirq.X(q0), cirq.Y(q0)), cirq.Z(q0)) # Yield nested lists yield [cirq.X(q0), [cirq.Y(q0), cirq.Z(q0)]] def generator(depth): if depth <= 0: yield cirq.CZ(q0, q1), cirq.Y(q0) else: yield cirq.X(q0), generator(depth - 1) yield cirq.Z(q0) # Yield nested generators yield generator(2) q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit(DummyGate()(q0, q1)) circuit = cirq.expand_composite(circuit) expected = cirq.Circuit( cirq.X(q0), cirq.Y(q0), cirq.Z(q0), # From tuple cirq.X(q0), cirq.Y(q0), cirq.Z(q0), # From nested lists # From nested generators cirq.X(q0), cirq.X(q0), cirq.CZ(q0, q1), cirq.Y(q0), cirq.Z(q0), cirq.Z(q0), ) assert_equal_mod_empty(expected, circuit)
def test_swap_network_gate(): qubits = tuple(cirq.NamedQubit(s) for s in alphabet) acquaintance_size = 3 n_parts = 3 part_lens = (acquaintance_size - 1,) * n_parts n_qubits = sum(part_lens) swap_network_op = cca.SwapNetworkGate(part_lens, acquaintance_size=acquaintance_size)( *qubits[:n_qubits] ) swap_network = cirq.Circuit(swap_network_op) expected_text_diagram = """ a: ───×(0,0)─── │ b: ───×(0,1)─── │ c: ───×(1,0)─── │ d: ───×(1,1)─── │ e: ───×(2,0)─── │ f: ───×(2,1)─── """.strip() ct.assert_has_diagram(swap_network, expected_text_diagram) no_decomp = lambda op: isinstance(op.gate, (cca.CircularShiftGate, cca.LinearPermutationGate)) swap_network = cirq.expand_composite(swap_network, no_decomp=no_decomp) expected_text_diagram = """ a: ───█───────╲0╱───█─────────────────█───────────╲0╱───█───────0↦1─── │ │ │ │ │ │ │ b: ───█───█───╲1╱───█───█─────────────█───█───────╲1╱───█───█───1↦0─── │ │ │ │ │ │ │ │ │ │ │ c: ───█───█───╱2╲───█───█───█───╲0╱───█───█───█───╱2╲───█───█───2↦3─── │ │ │ │ │ │ │ │ │ │ d: ───────█───╱3╲───█───█───█───╲1╱───█───█───█───╱3╲───────█───3↦2─── │ │ │ │ │ │ e: ─────────────────█───────█───╱2╲───█───────█─────────────────4↦5─── │ │ │ │ f: ─────────────────█───────────╱3╲───█─────────────────────────5↦4─── """.strip() ct.assert_has_diagram(swap_network, expected_text_diagram) acquaintance_size = 3 n_parts = 6 part_lens = (1,) * n_parts n_qubits = sum(part_lens) swap_network_op = cca.SwapNetworkGate(part_lens, acquaintance_size=acquaintance_size)( *qubits[:n_qubits] ) swap_network = cirq.Circuit(swap_network_op) no_decomp = lambda op: isinstance(op.gate, cca.CircularShiftGate) swap_network = cirq.expand_composite(swap_network, no_decomp=no_decomp) expected_text_diagram = """ a: ───╲0╱─────────╲0╱─────────╲0╱───────── │ │ │ b: ───╱1╲───╲0╱───╱1╲───╲0╱───╱1╲───╲0╱─── │ │ │ c: ───╲0╱───╱1╲───╲0╱───╱1╲───╲0╱───╱1╲─── │ │ │ d: ───╱1╲───╲0╱───╱1╲───╲0╱───╱1╲───╲0╱─── │ │ │ e: ───╲0╱───╱1╲───╲0╱───╱1╲───╲0╱───╱1╲─── │ │ │ f: ───╱1╲─────────╱1╲─────────╱1╲───────── """.strip() ct.assert_has_diagram(swap_network, expected_text_diagram)
def test_empty_moment(): circuit = cirq.Circuit([]) circuit = cirq.expand_composite(circuit) assert_equal_mod_empty(cirq.Circuit([]), circuit)
def test_do_not_decompose_no_compile(): q0, q1 = cirq.LineQubit.range(2) c = cirq.Circuit(cirq.CNOT(q0, q1).with_tags("no_compile")) context = cirq.TransformerContext(tags_to_ignore=("no_compile", )) assert_equal_mod_empty(c, cirq.expand_composite(c, context=context))
def test_complete_acquaintance_strategy(): qubits = [cirq.NamedQubit(s) for s in alphabet] with pytest.raises(ValueError): _ = cca.complete_acquaintance_strategy(qubits, -1) empty_strategy = cca.complete_acquaintance_strategy(qubits) assert empty_strategy._moments == [] trivial_strategy = cca.complete_acquaintance_strategy(qubits[:4], 1) actual_text_diagram = trivial_strategy.to_text_diagram().strip() expected_text_diagram = """ a: ───█─── b: ───█─── c: ───█─── d: ───█─── """.strip() assert actual_text_diagram == expected_text_diagram assert cca.get_acquaintance_size(trivial_strategy) == 1 quadratic_strategy = cca.complete_acquaintance_strategy(qubits[:8], 2) actual_text_diagram = quadratic_strategy.to_text_diagram().strip() expected_text_diagram = """ a: ───×(0,0)─── │ b: ───×(1,0)─── │ c: ───×(2,0)─── │ d: ───×(3,0)─── │ e: ───×(4,0)─── │ f: ───×(5,0)─── │ g: ───×(6,0)─── │ h: ───×(7,0)─── """.strip() assert actual_text_diagram == expected_text_diagram assert cca.get_acquaintance_size(quadratic_strategy) == 2 is_shift_or_lin_perm = lambda op: isinstance(op.gate, ( cca.CircularShiftGate, cca.LinearPermutationGate)) quadratic_strategy = cirq.expand_composite(quadratic_strategy, no_decomp=is_shift_or_lin_perm) actual_text_diagram = quadratic_strategy.to_text_diagram( transpose=True).strip() expected_text_diagram = '\n'.join(( "a b c d e f g h ".strip(), "│ │ │ │ │ │ │ │ ".strip(), "█───█ █───█ █───█ █───█ ".strip(), "│ │ │ │ │ │ │ │ ".strip(), "╲0╱─╱1╲ ╲0╱─╱1╲ ╲0╱─╱1╲ ╲0╱─╱1╲ ".strip(), "│ │ │ │ │ │ │ │ ".strip(), "│ █───█ █───█ █───█ │ ".strip(), "│ │ │ │ │ │ │ │ ".strip(), "│ ╲0╱─╱1╲ ╲0╱─╱1╲ ╲0╱─╱1╲ │ ".strip(), "│ │ │ │ │ │ │ │ ".strip(), "█───█ █───█ █───█ █───█ ".strip(), "│ │ │ │ │ │ │ │ ".strip(), "╲0╱─╱1╲ ╲0╱─╱1╲ ╲0╱─╱1╲ ╲0╱─╱1╲ ".strip(), "│ │ │ │ │ │ │ │ ".strip(), "│ █───█ █───█ █───█ │ ".strip(), "│ │ │ │ │ │ │ │ ".strip(), "│ ╲0╱─╱1╲ ╲0╱─╱1╲ ╲0╱─╱1╲ │ ".strip(), "│ │ │ │ │ │ │ │ ".strip(), "█───█ █───█ █───█ █───█ ".strip(), "│ │ │ │ │ │ │ │ ".strip(), "╲0╱─╱1╲ ╲0╱─╱1╲ ╲0╱─╱1╲ ╲0╱─╱1╲ ".strip(), "│ │ │ │ │ │ │ │ ".strip(), "│ █───█ █───█ █───█ │ ".strip(), "│ │ │ │ │ │ │ │ ".strip(), "│ ╲0╱─╱1╲ ╲0╱─╱1╲ ╲0╱─╱1╲ │ ".strip(), "│ │ │ │ │ │ │ │ ".strip(), "█───█ █───█ █───█ █───█ ".strip(), "│ │ │ │ │ │ │ │ ".strip(), "╲0╱─╱1╲ ╲0╱─╱1╲ ╲0╱─╱1╲ ╲0╱─╱1╲ ".strip(), "│ │ │ │ │ │ │ │ ".strip(), "│ █───█ █───█ █───█ │ ".strip(), "│ │ │ │ │ │ │ │ ".strip(), "│ ╲0╱─╱1╲ ╲0╱─╱1╲ ╲0╱─╱1╲ │ ".strip(), "│ │ │ │ │ │ │ │ ".strip(), )) assert actual_text_diagram == expected_text_diagram assert cca.get_acquaintance_size(quadratic_strategy) == 2 cubic_strategy = cca.complete_acquaintance_strategy(qubits[:4], 3) actual_text_diagram = cubic_strategy.to_text_diagram( transpose=True).strip() expected_text_diagram = """ a b c d │ │ │ │ ×(0,0)─×(0,1)─×(1,0)─×(1,1) │ │ │ │ ╱1╲────╲0╱ ╱1╲────╲0╱ │ │ │ │ ×(0,0)─×(1,0)─×(1,1)─×(2,0) │ │ │ │ │ ╲0╱────╱1╲ │ │ │ │ │ ×(0,0)─×(0,1)─×(1,0)─×(1,1) │ │ │ │ ╱1╲────╲0╱ ╱1╲────╲0╱ │ │ │ │ ×(0,0)─×(1,0)─×(1,1)─×(2,0) │ │ │ │ │ ╲0╱────╱1╲ │ │ │ │ │ """.strip() assert actual_text_diagram == expected_text_diagram assert cca.get_acquaintance_size(cubic_strategy) == 3
def test_expands_composite_recursively_preserving_structur(): q = cirq.LineQubit.range(2) c_nested = cirq.FrozenCircuit(cirq.SWAP(*q[:2]), cirq.SWAP(*q[:2]).with_tags("ignore"), cirq.SWAP(*q[:2])) c_nested_expanded = cirq.FrozenCircuit( [cirq.CNOT(*q), cirq.CNOT(*q[::-1]), cirq.CNOT(*q)], cirq.SWAP(*q[:2]).with_tags("ignore"), [cirq.CNOT(*q), cirq.CNOT(*q[::-1]), cirq.CNOT(*q)], ) c_orig = cirq.Circuit( c_nested, cirq.CircuitOperation( cirq.FrozenCircuit( c_nested, cirq.CircuitOperation(c_nested).repeat(5).with_tags("ignore"), cirq.CircuitOperation(c_nested).repeat(6).with_tags( "preserve_tag"), cirq.CircuitOperation(c_nested).repeat(7), c_nested, )).repeat(4).with_tags("ignore"), c_nested, cirq.CircuitOperation( cirq.FrozenCircuit( c_nested, cirq.CircuitOperation(c_nested).repeat(5).with_tags("ignore"), cirq.CircuitOperation(c_nested).repeat(6).with_tags( "preserve_tag"), cirq.CircuitOperation(c_nested).repeat(7), c_nested, )).repeat(5).with_tags("preserve_tag"), c_nested, ) c_expected = cirq.Circuit( c_nested_expanded, cirq.CircuitOperation( cirq.FrozenCircuit( c_nested, cirq.CircuitOperation(c_nested).repeat(5).with_tags("ignore"), cirq.CircuitOperation(c_nested).repeat(6).with_tags( "preserve_tag"), cirq.CircuitOperation(c_nested).repeat(7), c_nested, )).repeat(4).with_tags("ignore"), c_nested_expanded, cirq.CircuitOperation( cirq.FrozenCircuit( c_nested_expanded, cirq.CircuitOperation(c_nested).repeat(5).with_tags("ignore"), cirq.CircuitOperation(c_nested_expanded).repeat(6).with_tags( "preserve_tag"), cirq.CircuitOperation(c_nested_expanded).repeat(7), c_nested_expanded, )).repeat(5).with_tags("preserve_tag"), c_nested_expanded, ) context = cirq.TransformerContext(tags_to_ignore=["ignore"], deep=True) c_expanded = cirq.expand_composite( c_orig, no_decomp=lambda op: op.gate == cirq.CNOT, context=context) cirq.testing.assert_same_circuits(c_expanded, c_expected)