def test_gate_with_custom_names(): q0, q1, q2, q3 = cirq.LineQubit.range(4) gate = cirq.BooleanHamiltonianGate(['a', 'b'], ['a'], 0.1) assert cirq.decompose(gate.on(q0, q1)) == [cirq.Rz(rads=-0.05).on(q0)] assert cirq.decompose_once_with_qubits(gate, (q0, q1)) == [cirq.Rz(rads=-0.05).on(q0)] assert cirq.decompose(gate.on(q2, q3)) == [cirq.Rz(rads=-0.05).on(q2)] assert cirq.decompose_once_with_qubits(gate, (q2, q3)) == [cirq.Rz(rads=-0.05).on(q2)] with pytest.raises(ValueError, match='Wrong number of qubits'): gate.on(q2) with pytest.raises(ValueError, match='Wrong shape of qids'): gate.on(q0, cirq.LineQid(1, 3))
def test_decompose_once_with_qubits(): qs = cirq.LineQubit.range(3) # No default value results in descriptive error. with pytest.raises(TypeError, match='no _decompose_ method'): _ = cirq.decompose_once_with_qubits(NoMethod(), qs) with pytest.raises(TypeError, match='returned NotImplemented or None'): _ = cirq.decompose_once_with_qubits(DecomposeNotImplemented(), qs) with pytest.raises(TypeError, match='returned NotImplemented or None'): _ = cirq.decompose_once_with_qubits(DecomposeNone(), qs) # Default value works. assert cirq.decompose_once_with_qubits(NoMethod(), qs, 5) == 5 assert cirq.decompose_once_with_qubits(DecomposeNotImplemented(), qs, None) is None assert cirq.decompose_once_with_qubits(NoMethod(), qs, NotImplemented) is NotImplemented # Flattens into a list. assert cirq.decompose_once_with_qubits( DecomposeWithQubitsGiven(cirq.X.on_each), qs) == [ cirq.X(cirq.LineQubit(0)), cirq.X(cirq.LineQubit(1)), cirq.X(cirq.LineQubit(2)) ] assert cirq.decompose_once_with_qubits( DecomposeWithQubitsGiven(lambda *qubits: cirq.Y(qubits[0])), qs) == [cirq.Y(cirq.LineQubit(0))] assert cirq.decompose_once_with_qubits( DecomposeWithQubitsGiven(lambda *qubits: (cirq.Y(q) for q in qubits)), qs) == [ cirq.Y(cirq.LineQubit(0)), cirq.Y(cirq.LineQubit(1)), cirq.Y(cirq.LineQubit(2)) ] # Works when qubits are generated. def use_qubits_twice(*qubits): a = list(qubits) b = list(qubits) yield cirq.X.on_each(*a) yield cirq.Y.on_each(*b) assert (cirq.decompose_once_with_qubits( DecomposeWithQubitsGiven(use_qubits_twice), (q for q in qs)) == list(cirq.X.on_each(*qs)) + list(cirq.Y.on_each(*qs)))
def test_decomposes_despite_symbol(): q0, q1 = cirq.NamedQubit('q0'), cirq.NamedQubit('q1') gate = cirq.PauliInteractionGate(cirq.Z, False, cirq.X, False, exponent=sympy.Symbol('x')) assert cirq.decompose_once_with_qubits(gate, [q0, q1])
def test_swap_network_gate_permutation(part_lens, acquaintance_size): n_qubits = sum(part_lens) qubits = cirq.LineQubit.range(n_qubits) swap_network_gate = SwapNetworkGate(part_lens, acquaintance_size) operations = cirq.decompose_once_with_qubits(swap_network_gate, qubits) operations = list(cirq.flatten_op_tree(operations)) mapping = {q: i for i, q in enumerate(qubits)} update_mapping(mapping, operations) assert mapping == {q: i for i, q in enumerate(reversed(qubits))}
def test_parameterize(): parameterized_gate = cirq.PhasedXPowGate(exponent=cirq.Symbol('a'), phase_exponent=cirq.Symbol('b')) assert cirq.pow(parameterized_gate, 5, default=None) is None assert cirq.decompose_once_with_qubits(parameterized_gate, [cirq.LineQubit(0)], NotImplemented) is NotImplemented assert cirq.unitary(parameterized_gate, default=None) is None assert cirq.is_parameterized(parameterized_gate) resolver = cirq.ParamResolver({'a': 0.1, 'b': 0.2}) resolved_gate = cirq.resolve_parameters(parameterized_gate, resolver) assert resolved_gate == cirq.PhasedXPowGate(exponent=0.1, phase_exponent=0.2)
def test_child_class(): class Impl(cirq.ReversibleCompositeGate): def _decompose_(self, qubits): yield _FlipGate(1)(*qubits) yield _FlipGate(2)(*qubits), _FlipGate(3)(*qubits) gate = Impl() reversed_gate = gate**-1 assert gate is reversed_gate**-1 with pytest.raises(TypeError): _ = gate**0.5 with pytest.raises(TypeError): _ = reversed_gate**0.5 q = cirq.NamedQubit('q') assert (cirq.decompose_once_with_qubits( gate, [q]) == [_FlipGate(1)(q), _FlipGate(2)(q), _FlipGate(3)(q)]) assert (cirq.decompose_once_with_qubits(reversed_gate, [q]) == [ _FlipGate(~3)(q), _FlipGate(~2)(q), _FlipGate(~1)(q) ])
def test_linear_permutation_gate(n_elements, n_permuted): qubits = cirq.LineQubit.range(n_elements) elements = tuple(range(n_elements)) elements_to_permute = random.sample(elements, n_permuted) permuted_elements = random.sample(elements_to_permute, n_permuted) permutation = {e: p for e, p in zip(elements_to_permute, permuted_elements)} cca.PermutationGate.validate_permutation(permutation, n_elements) gate = cca.LinearPermutationGate(n_elements, permutation) ct.assert_equivalent_repr(gate) assert gate.permutation() == permutation mapping = dict(zip(qubits, elements)) for swap in cirq.flatten_op_tree(cirq.decompose_once_with_qubits( gate, qubits)): assert isinstance(swap, cirq.GateOperation) swap.gate.update_mapping(mapping, swap.qubits) for i in range(n_elements): p = permutation.get(elements[i], i) assert mapping.get(qubits[p], elements[i]) == i
def test_linear_permutation_gate(): for _ in range(20): n_elements = randint(5, 20) n_permuted = randint(0, n_elements) qubits = [cirq.NamedQubit(s) for s in alphabet[:n_elements]] elements = tuple(range(n_elements)) elements_to_permute = sample(elements, n_permuted) permuted_elements = sample(elements_to_permute, n_permuted) permutation = {e: p for e, p in zip(elements_to_permute, permuted_elements)} PermutationGate.validate_permutation(permutation, n_elements) gate = LinearPermutationGate(permutation) assert gate.permutation(n_elements) == permutation mapping = dict(zip(qubits, elements)) for swap in cirq.flatten_op_tree(cirq.decompose_once_with_qubits( gate, qubits)): assert isinstance(swap, cirq.GateOperation) swap.gate.update_mapping(mapping, swap.qubits) for i in range(n_elements): p = permutation.get(elements[i], i) assert mapping.get(qubits[p], elements[i]) == i
def test_parameterize(resolve_fn): parameterized_gate = cirq.PhasedXPowGate(exponent=sympy.Symbol('a'), phase_exponent=sympy.Symbol('b')) assert cirq.pow(parameterized_gate, 5) == cirq.PhasedXPowGate(exponent=sympy.Symbol('a') * 5, phase_exponent=sympy.Symbol('b')) assert (cirq.decompose_once_with_qubits( parameterized_gate, [cirq.LineQubit(0)], NotImplemented) is NotImplemented) assert cirq.unitary(parameterized_gate, default=None) is None assert cirq.is_parameterized(parameterized_gate) resolver = cirq.ParamResolver({'a': 0.1, 'b': 0.2}) resolved_gate = resolve_fn(parameterized_gate, resolver) assert resolved_gate == cirq.PhasedXPowGate(exponent=0.1, phase_exponent=0.2) unparameterized_gate = cirq.PhasedXPowGate(exponent=0.1, phase_exponent=0.2) assert not cirq.is_parameterized(unparameterized_gate) assert cirq.is_parameterized(unparameterized_gate**sympy.Symbol('a')) assert cirq.is_parameterized(unparameterized_gate**(sympy.Symbol('a') + 1))
def test_swap_network_decomposition(): qubits = cirq.LineQubit.range(8) swap_network_gate = cca.SwapNetworkGate((4, 4), 5) operations = cirq.decompose_once_with_qubits(swap_network_gate, qubits) circuit = cirq.Circuit(operations) expected_text_diagram = """ 0: ───█─────────────█─────────────╲0╱─────────────█─────────█───────0↦2─── │ │ │ │ │ │ 1: ───█─────────────█─────────────╲1╱─────────────█─────────█───────1↦3─── │ │ │ │ │ │ 2: ───█─────────────█───1↦0───────╲2╱───────1↦0───█─────────█───────2↦0─── │ │ │ │ │ │ │ │ 3: ───█───█─────────█───0↦1───█───╲3╱───█───0↦1───█─────────█───█───3↦1─── │ │ │ │ │ │ │ │ │ │ 4: ───█───█───0↦1───█─────────█───╱4╲───█─────────█───0↦1───█───█───4↦6─── │ │ │ │ │ │ │ │ 5: ───────█───1↦0─────────────█───╱5╲───█─────────────1↦0───────█───5↦7─── │ │ │ │ │ │ 6: ───────█───────────────────█───╱6╲───█───────────────────────█───6↦4─── │ │ │ │ │ │ 7: ───────█───────────────────█───╱7╲───█───────────────────────█───7↦5─── """.strip() ct.assert_has_diagram(circuit, expected_text_diagram)
def test_swap_network_decomposition(): qubits = cirq.LineQubit.range(8) swap_network_gate = SwapNetworkGate((4, 4), 5) operations = cirq.decompose_once_with_qubits(swap_network_gate, qubits) circuit = cirq.Circuit.from_ops(operations) actual_text_diagram = circuit.to_text_diagram() expected_text_diagram = """ 0: ───█─────────────█─────────────╲0╱─────────────█─────────█───────0↦2─── │ │ │ │ │ │ 1: ───█─────────────█─────────────╲1╱─────────────█─────────█───────1↦3─── │ │ │ │ │ │ 2: ───█─────────────█───1↦0───────╲2╱───────1↦0───█─────────█───────2↦0─── │ │ │ │ │ │ │ │ 3: ───█───█─────────█───0↦1───█───╲3╱───█───0↦1───█─────────█───█───3↦1─── │ │ │ │ │ │ │ │ │ 4: ───█───█───0↦1───█─────────█───╱4╲───█─────────█───0↦1───█───█───0↦2─── │ │ │ │ │ │ │ │ 5: ───────█───1↦0─────────────█───╱5╲───█─────────────1↦0───────█───1↦3─── │ │ │ │ │ │ 6: ───────█───────────────────█───╱6╲───█───────────────────────█───2↦0─── │ │ │ │ │ │ 7: ───────█───────────────────█───╱7╲───█───────────────────────█───3↦1─── """.strip() assert actual_text_diagram == expected_text_diagram
def test_decompose_raises(): g = cirq.ParallelGate(cirq.X, 2) qubits = cirq.LineQubit.range(4) with pytest.raises(ValueError, match=r'len\(qubits\)=4 should be 2'): cirq.decompose_once_with_qubits(g, qubits)
def _decompose_(self, qids): return cirq.inverse(cirq.decompose_once_with_qubits(self**-1, qids))