Skip to content

Commit

Permalink
add check_map
Browse files Browse the repository at this point in the history
  • Loading branch information
ewinston committed Sep 1, 2022
1 parent cb1398d commit 349dca4
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 42 deletions.
8 changes: 5 additions & 3 deletions qiskit/transpiler/passes/routing/stochastic_swap.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ def _transpile_controlflow_multiblock(self, cf_op, current_layout):

for i, block in enumerate(cf_op.blocks):
dag_block = circuit_to_dag(block)
_pass = self.__class__(new_coupling, initial_layout=None, seed=self.seed)
_pass = self.__class__(new_coupling, initial_layout=None, seed=(i + 1) * self.seed)
updated_dag_block = _pass.run(dag_block)
block_dags.append(updated_dag_block)
block_layouts.append(_pass.property_set["final_layout"].copy())
Expand All @@ -401,6 +401,7 @@ def _transpile_controlflow_multiblock(self, cf_op, current_layout):
new_coupling,
block_layouts[i],
block_layouts[maxind],
seed = i*self.seed,
)
match_dag = layout_xform.run(dag)
block_circuits.append(dag_to_circuit(match_dag))
Expand All @@ -422,12 +423,13 @@ def _transpile_controlflow_looping(self, cf_op, current_layout):

new_coupling = layout_transform(self.coupling_map, current_layout)
dag_block = circuit_to_dag(cf_op.blocks[0])
_pass = self.__class__(new_coupling, initial_layout=None, seed=self.seed)
_pass = self.__class__(new_coupling, initial_layout=None, seed=2 * self.seed)
start_qreg = QuantumRegister(len(self._qubit_indices), "q")
start_layout = Layout.generate_trivial_layout(start_qreg)
updated_dag_block = _pass.run(dag_block)
updated_layout = _pass.property_set["final_layout"].copy()
layout_xform = LayoutTransformation(new_coupling, updated_layout, start_layout)
layout_xform = LayoutTransformation(new_coupling, updated_layout,
start_layout, seed=self.seed)
match_dag = layout_xform.run(updated_dag_block)
match_circ = dag_to_circuit(match_dag)
return cf_op.replace_blocks([match_circ]), current_layout
Expand Down
6 changes: 6 additions & 0 deletions qiskit/transpiler/passes/utils/check_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"""Check if a DAG circuit is already mapped to a coupling map."""

from qiskit.transpiler.basepasses import AnalysisPass
from qiskit.circuit.controlflow import ControlFlowOp


class CheckMap(AnalysisPass):
Expand Down Expand Up @@ -41,6 +42,7 @@ def run(self, dag):
Args:
dag (DAGCircuit): DAG to map.
"""
from qiskit.converters import circuit_to_dag
self.property_set["is_swap_mapped"] = True

if self.coupling_map is None or len(self.coupling_map.graph) == 0:
Expand All @@ -64,3 +66,7 @@ def run(self, dag):
)
self.property_set["is_swap_mapped"] = False
return
for cf_instr in dag.op_nodes(op=ControlFlowOp):
for block in cf_instr.op.blocks:
dag_block = circuit_to_dag(block)
self.run(dag_block)
34 changes: 33 additions & 1 deletion test/python/transpiler/test_check_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import unittest

from qiskit import QuantumRegister, QuantumCircuit
from qiskit import QuantumRegister, QuantumCircuit, ClassicalRegister
from qiskit.transpiler.passes import CheckMap
from qiskit.transpiler import CouplingMap
from qiskit.converters import circuit_to_dag
Expand Down Expand Up @@ -85,6 +85,38 @@ def test_swap_mapped_false(self):

self.assertFalse(pass_.property_set["is_swap_mapped"])

def test_swap_mapped_cf_true(self):
"""Check control flow blocks are mapped."""
num_qubits = 3
coupling = CouplingMap([(i, i + 1) for i in range(num_qubits - 1)])
qr = QuantumRegister(3)
cr = ClassicalRegister(3)
circuit = QuantumCircuit(qr, cr)
true_body = QuantumCircuit(qr)
true_body.swap(0, 1)
true_body.cx(2, 1)
circuit.if_else((cr[0], 0), true_body, None, qr, cr)
dag = circuit_to_dag(circuit)
pass_ = CheckMap(coupling)
pass_.run(dag)
self.assertTrue(pass_.property_set["is_swap_mapped"])

def test_swap_mapped_cf_false(self):
"""Check control flow blocks are mapped."""
num_qubits = 3
coupling = CouplingMap([(i, i + 1) for i in range(num_qubits - 1)])
qr = QuantumRegister(3)
cr = ClassicalRegister(3)
circuit = QuantumCircuit(qr, cr)
true_body = QuantumCircuit(qr)
true_body.cx(0, 2)
circuit.if_else((cr[0], 0), true_body, None, qr, cr)
dag = circuit_to_dag(circuit)
pass_ = CheckMap(coupling)
pass_.run(dag)
self.assertFalse(pass_.property_set["is_swap_mapped"])



if __name__ == "__main__":
unittest.main()
95 changes: 57 additions & 38 deletions test/python/transpiler/test_stochastic_swap.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from qiskit.converters import circuit_to_dag, dag_to_circuit
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit.test import QiskitTestCase
from qiskit.transpiler.passes.utils import CheckMap
from qiskit.quantum_info.analysis.distance import hellinger_distance
from qiskit.utils import optionals

Expand Down Expand Up @@ -928,10 +929,8 @@ def test_controlflow_no_layout_change(self):
expected.measure(qreg, creg[[0, 2, 1, 3, 4]])
self.assertEqual(cqc, expected)

@unittest.skipUnless(optionals.HAS_AER, "Qiskit Aer is required to run this test")
#@data(1, 2, 3, 4, 5)
#def test_controlflow_for_loop(self, nloops):
def test_controlflow_for_loop(self):
@data(1, 2, 3)
def test_controlflow_for_loop(self, nloops):
nloops=1
"""test for loop"""
num_qubits = 3
Expand All @@ -945,73 +944,66 @@ def test_controlflow_for_loop(self):
for_body.cx(0, 2)
loop_parameter = None
qc.for_loop(range(nloops), loop_parameter, for_body, qreg, creg)
qc.barrier()
qc.measure(qreg, creg)

dag = circuit_to_dag(qc)
cdag = StochasticSwap(coupling, seed=687).run(dag)
cqc = dag_to_circuit(cdag)

sim = Aer.get_backend("aer_simulator")
in_results = sim.run(qc, shots=4096, seed_simulator=10).result().get_counts()
out_results = sim.run(cqc, shots=4096, seed_simulator=11).result().get_counts()
expected = QuantumCircuit(qreg, creg)
expected.h(0)
expected.x(1)
efor_body = QuantumCircuit(qreg, creg)
efor_body.swap(1, 2)
efor_body.cx(0, 1)
efor_body.swap(1, 2)
efor_body.swap(0, 1)
efor_body.cx(1, 2)
efor_body.swap(0, 1)
loop_parameter = None
expected.for_loop(range(nloops), loop_parameter, efor_body, qreg, creg)
expected.barrier()
expected.measure(qreg, creg)
print('')
print(cqc)
print(cqc.data[2].operation.params[2])
print(expected)
print(expected.data[2].operation.params[2])
self.assertLess(hellinger_distance(in_results, out_results), 0.01)
for instr in cqc.data[2].operation.params[2]
print(node.name)
if node.op.name == 'swap':
print(repr(node))

#self.assertEqual(cqc, expected)
expected.measure(qreg, creg)
self.assertEqual(cqc, expected)

@unittest.skipUnless(optionals.HAS_AER, "Qiskit Aer is required to run this test")
def test_controlflow_while_loop(self):
"""test while loop"""
from qiskit.circuit.library.standard_gates import CCXGate

shots = 100
num_qubits = 4
qreg = QuantumRegister(num_qubits, "q")
creg = ClassicalRegister(len(qreg))
coupling = CouplingMap([(i, i + 1) for i in range(num_qubits - 1)])
check_map_pass = CheckMap(coupling)
qc = QuantumCircuit(qreg, creg)
while_body = QuantumCircuit(qreg, creg)
while_body.reset(qreg[2:])
while_body.h(qreg[2:])
while_body.compose(CCXGate().definition, [2, 3, 0], inplace=True)
while_body.measure(qreg[0], creg[0])
while_body.cx(0, 3)
while_body.measure(qreg[3], creg[3])
qc.while_loop((creg, 0), while_body, qc.qubits, qc.clbits)
qc.barrier()
qc.measure(qreg, creg)

dag = circuit_to_dag(qc)
cdag = StochasticSwap(coupling, seed=58).run(dag)
cqc = dag_to_circuit(cdag)
sim = Aer.get_backend("aer_simulator")
in_results = sim.run(qc, shots=shots, seed_simulator=10).result().get_counts()
out_results = sim.run(cqc, shots=shots, seed_simulator=11).result().get_counts()
self.assertLess(hellinger_distance(in_results, out_results), 0.01)
expected = QuantumCircuit(qreg, creg)
ewhile_body = QuantumCircuit(qreg, creg)
ewhile_body.reset(qreg[2:])
ewhile_body.h(qreg[2:])
ewhile_body.swap(0, 1)
ewhile_body.swap(2, 3)
ewhile_body.cx(1, 2)
ewhile_body.measure(qreg[2], creg[3])
ewhile_body.swap(1, 0)
ewhile_body.swap(3, 2)
expected.while_loop((creg, 0), ewhile_body, expected.qubits, expected.clbits)
expected.barrier()
expected.measure(qreg, creg)
check_map_pass.run(circuit_to_dag(expected))
self.assertEqual(cqc, expected)
self.assertTrue(check_map_pass.property_set["is_swap_mapped"])

@unittest.skipUnless(optionals.HAS_AER, "Qiskit Aer is required to run this test")
@data(392, 2023, 45, 27, 68)
def test_controlflow_nested_inner_cnot(self, seed):
"""test swap in nested if else controlflow construct; swap in inner"""
num_qubits = 5
num_qubits = 3
qreg = QuantumRegister(num_qubits, "q")
creg = ClassicalRegister(num_qubits)
coupling = CouplingMap([(i, i + 1) for i in range(num_qubits - 1)])
Expand All @@ -1024,24 +1016,51 @@ def test_controlflow_nested_inner_cnot(self, seed):

for_body = QuantumCircuit(qreg, creg)
for_body.delay(10, 0)
for_body.cx(1, 3)
for_body.cx(0, 2)
loop_parameter = None
true_body.for_loop(range(3), loop_parameter, for_body, qreg, creg)

false_body = QuantumCircuit(qreg, creg)
false_body.y(0)
qc.if_else((creg[0], 0), true_body, false_body, qreg, creg)
qc.barrier()
qc.measure(qreg, creg)

dag = circuit_to_dag(qc)
cdag = StochasticSwap(coupling, seed=seed).run(dag)
cqc = dag_to_circuit(cdag)

expected = QuantumCircuit(qreg, creg)
expected.h(0)
expected.x(1)
expected.measure(0, 0)
etrue_body = QuantumCircuit(qreg, creg)
etrue_body.x(0)

efor_body = QuantumCircuit(qreg, creg)
efor_body.delay(10, 0)
efor_body.swap(0, 1)
efor_body.cx(1, 2)
efor_body.swap(1, 0)
etrue_body.for_loop(range(3), loop_parameter, efor_body, qreg, creg)

efalse_body = QuantumCircuit(qreg, creg)
efalse_body.y(0)
expected.if_else((creg[0], 0), etrue_body, efalse_body, qreg, creg)
expected.measure(qreg, creg)
print('')
print(cqc)
print(expected)
print(cqc.data[3].operation.params[0])
print(expected.data[3].operation.params[0])
print(cqc.data[3].operation.params[0].data[1].operation.params[2])
print(expected.data[3].operation.params[0].data[1].operation.params[2])
breakpoint()
sim = Aer.get_backend("aer_simulator")
in_results = sim.run(qc, shots=4096, seed_simulator=10).result().get_counts()
out_results = sim.run(cqc, shots=4096, seed_simulator=11).result().get_counts()
self.assertLess(hellinger_distance(in_results, out_results), 0.01)
check_map_pass.run(circuit_to_dag(expected))


@unittest.skipUnless(optionals.HAS_AER, "Qiskit Aer is required to run this test")
@data(392, 2023, 45, 27, 68)
Expand Down

0 comments on commit 349dca4

Please sign in to comment.