In [ ]:
import cirq
import recirq
import networkx as nx
from cirq.contrib.svg import SVGCircuit
import numpy as np
In [ ]:
from pytket.predicates import CompilationUnit, ConnectivityPredicate
from pytket.passes import SequencePass, RoutingPass, DecomposeSwapsToCXs
from pytket.routing import GraphPlacement
In [ ]:
from recirq.qaoa.problem_circuits import get_generic_qaoa_circuit
from recirq.qaoa.gates_and_compilation import compile_problem_unitary_to_arbitrary_zz, \
compile_driver_unitary_to_rx
problem_graph = nx.random_regular_graph(d=3, n=10)
nx.set_edge_attributes(problem_graph, values=1, name='weight')
circuit_qubits = cirq.LineQubit.range(10, 20)
gammas = np.random.randn(2)
betas = np.random.randn(2)
circuit = get_generic_qaoa_circuit(
problem_graph=problem_graph,
qubits=circuit_qubits,
gammas=gammas,
betas=betas)
circuit = compile_problem_unitary_to_arbitrary_zz(circuit)
circuit = compile_driver_unitary_to_rx(circuit)
SVGCircuit(circuit)
In [ ]:
import cirq.contrib.routing as ccr
uncompiled_c_graph = ccr.get_circuit_connectivity(circuit)
nx.draw_networkx(uncompiled_c_graph)
In [ ]:
import cirq.google as cg
dev_graph = ccr.xmon_device_to_graph(cg.Sycamore23)
nx.draw_networkx(dev_graph)
In [ ]:
# alias for the device. If this notebook were wrapped
# in a function, `circuit` and `device` would be the arguments
device = cg.Sycamore23
In [ ]:
index_to_qubit = sorted(device.qubit_set())
qubit_to_index = {q: i for i, q in enumerate(index_to_qubit)}
In [ ]:
import pytket
from pytket.circuit import Node
def _qubit_index_edges():
dev_graph = ccr.xmon_device_to_graph(device)
for n1, n2 in dev_graph.edges:
#yield Node('q', n1.row, n1.col), Node('q', n2.row, n2.col)
yield (qubit_to_index[n1], qubit_to_index[n2])
def _device_to_tket_device():
arc = pytket.routing.Architecture(
list(_qubit_index_edges())
)
return pytket.device.Device({}, {}, arc)
tk_circuit = pytket.cirq.cirq_to_tk(circuit)
tk_device = _device_to_tket_device()
In [ ]:
tk_circuit.qubits
In [ ]:
tk_device.coupling
In [ ]:
from pytket.predicates import CompilationUnit, ConnectivityPredicate
from pytket.passes import SequencePass, RoutingPass, DecomposeSwapsToCXs, PlacementPass
from pytket.routing import GraphPlacement
In [ ]:
unit = CompilationUnit(tk_circuit, [ConnectivityPredicate(tk_device)])
passes = SequencePass([
PlacementPass(GraphPlacement(tk_device)),
RoutingPass(tk_device)])
passes.apply(unit)
valid = unit.check_all_predicates()
assert valid
In [ ]:
unit.initial_map
In [ ]:
def tk_to_i(tk):
i = tk.index
assert len(i) == 1, i
return i[0]
initial_map = {cirq.LineQubit(tk_to_i(n1)): index_to_qubit[tk_to_i(n2)] for n1, n2 in unit.initial_map.items()}
initial_map
In [ ]:
unit.final_map
In [ ]:
final_map = {cirq.LineQubit(tk_to_i(n1)): index_to_qubit[tk_to_i(n2)]
for n1, n2 in unit.final_map.items()}
final_map
In [ ]:
unit.circuit.qubits
In [ ]:
routed_circuit = pytket.cirq.tk_to_cirq(unit.circuit)
routed_circuit = routed_circuit.transform_qubits(lambda q: index_to_qubit[q.x])
SVGCircuit(routed_circuit)
In [ ]:
routed_c_graph = ccr.get_circuit_connectivity(routed_circuit)
nx.draw_networkx(routed_c_graph)
In [ ]:
for _, op, _ in routed_circuit.findall_operations_with_gate_type(cirq.TwoQubitGate):
a, b = op.qubits
assert a.is_adjacent(b)
In [ ]:
import cirq.contrib.acquaintance as cca
def permute_gate(qubits, permutation):
return cca.LinearPermutationGate(
num_qubits=len(qubits),
permutation={i: permutation[i] for i in range(len(permutation))}
).on(*qubits)
final_to_initial_map = {final_map[cq]: initial_map[cq]
for cq in circuit_qubits}
initial_qubits = [initial_map[cq] for cq in circuit_qubits]
final_permutation = [initial_qubits.index(final_to_initial_map[q])
for q in initial_qubits]
rcircuit_with_perm = routed_circuit.copy()
rcircuit_with_perm.append(permute_gate(initial_qubits, final_permutation))
expected = circuit.unitary(qubit_order=cirq.QubitOrder.explicit(circuit_qubits))
actual = rcircuit_with_perm.unitary(qubit_order=cirq.QubitOrder.explicit(initial_qubits))
cirq.testing.assert_allclose_up_to_global_phase(expected, actual, atol=1e-8)