diff --git a/examples/python/commutation_relation.py b/examples/python/commutation_relation.py index e70dcb59ef7..819091f9e12 100644 --- a/examples/python/commutation_relation.py +++ b/examples/python/commutation_relation.py @@ -1,10 +1,8 @@ from qiskit import * -from qiskit.tools.visualization import * -from qiskit.converters import circuit_to_dag from qiskit.transpiler import PassManager from qiskit.transpiler.passes import CommutationAnalysis, CommutationTransformation -from qiskit.transpiler import transpile_dag +from qiskit.transpiler import transpile qr = QuantumRegister(5, 'qr') circuit = QuantumCircuit(qr) @@ -21,14 +19,13 @@ circuit.cx(qr[2], qr[3]) circuit.cx(qr[3], qr[2]) -dag = circuit_to_dag(circuit) -circuit.draw(interactive=True, output='latex') - -dag_drawer(dag) +print(circuit.draw()) pm = PassManager() pm.append([CommutationAnalysis(), CommutationTransformation()]) -dag = transpile_dag(dag, pass_manager=pm) -dag_drawer(dag) +# TODO make it not needed to have a backend +backend_device = BasicAer.get_backend('qasm_simulator') +circuit = transpile(circuit, backend_device, pass_manager=pm) +print(circuit.draw()) diff --git a/qiskit/dagcircuit/_dagcircuit.py b/qiskit/dagcircuit/_dagcircuit.py index a8d5a462a7e..84f620541dc 100644 --- a/qiskit/dagcircuit/_dagcircuit.py +++ b/qiskit/dagcircuit/_dagcircuit.py @@ -1468,9 +1468,9 @@ def collect_runs(self, namelist): # Iterate through the nodes of self in topological order # and form tuples containing sequences of gates # on the same qubit(s). - ts = list(self.node_nums_in_topological_order()) - nodes_seen = dict(zip(ts, [False] * len(ts))) - for node in ts: + tops_node = list(self.node_nums_in_topological_order()) + nodes_seen = dict(zip(tops_node, [False] * len(tops_node))) + for node in tops_node: nd = self.multi_graph.node[node] if nd["type"] == "op" and nd["name"] in namelist \ and not nodes_seen[node]: diff --git a/qiskit/transpiler/passes/commutation_analysis.py b/qiskit/transpiler/passes/commutation_analysis.py index 9f418d58257..56945b9dfe7 100644 --- a/qiskit/transpiler/passes/commutation_analysis.py +++ b/qiskit/transpiler/passes/commutation_analysis.py @@ -19,8 +19,8 @@ A rule-based analysis would be potentially faster, but more limited. """ -import numpy as np from collections import defaultdict +import numpy as np from qiskit.transpiler._basepasses import AnalysisPass @@ -40,10 +40,10 @@ def run(self, dag): Run the pass on the DAG, and write the discovered commutation relations into the property_set. """ - ts = list(dag.node_nums_in_topological_order()) + tops_node = list(dag.node_nums_in_topological_order()) # Initiation of the node_order - for num, node in enumerate(ts): + for num, node in enumerate(tops_node): self.node_order[node] = num # Initiate the commutation set @@ -57,7 +57,7 @@ def run(self, dag): self.property_set['commutation_set'][wire_name] = [] # Add edges to the dictionary for each qubit - for node in ts: + for node in tops_node: for edge in dag.multi_graph.edges([node], data=True): edge_name = edge[2]['name'] @@ -83,31 +83,22 @@ def run(self, dag): self.property_set['commutation_set'][wire_name].append([node]) if node not in self.property_set['commutation_set'][wire_name][-1]: - if _commute(dag.multi_graph.node[node], dag.multi_graph.node[self.property_set['commutation_set'][wire_name][-1][-1]]): + test_node = self.property_set['commutation_set'][wire_name][-1][-1] + if _commute(dag.multi_graph.node[node], dag.multi_graph.node[test_node]): self.property_set['commutation_set'][wire_name][-1].append(node) else: self.property_set['commutation_set'][wire_name].append([node]) + temp_len = len(self.property_set['commutation_set'][wire_name]) + self.property_set['commutation_set'][(node, wire_name)] = temp_len - 1 - self.property_set['commutation_set'][(node, wire_name)] = len(self.property_set['commutation_set'][wire_name]) - 1 - - # Output the grouped set for testing - # for wire in dag.wires: - # wire_name = "{0}[{1}]".format(str(wire[0].name), str(wire[1])) - # print(wire_name) - # for group in self.property_set['commutation_set'][wire_name]: - # print(group) -def _get_node_order(node): - """Get order of edges on a wire""" - return self.node_order[node] - -def _GateMasterDef(name = '', para = None): +def _gate_master_def(name, para=None): if name == 'h': return 1. / np.sqrt(2) * np.array([[1.0, 1.0], [1.0, -1.0]], dtype=np.complex) if name == 'x': return np.array([[0.0, 1.0], - [1.0,0.0]], dtype=np.complex) + [1.0, 0.0]], dtype=np.complex) if name == 'y': return np.array([[0.0, -1.0j], [1.0j, 0.0]], dtype=np.complex) @@ -128,10 +119,10 @@ def _GateMasterDef(name = '', para = None): [0.0, 0.0, -1.0j, 0.0]], dtype=np.complex) if name == 'z': return np.array([[1.0, 0.0], - [0.0,-1.0]], dtype=np.complex) + [0.0, -1.0]], dtype=np.complex) if name == 't': return np.array([[1.0, 0.0], - [0.0,np.exp(1j * np.pi / 4.0)]], dtype=np.complex) + [0.0, np.exp(1j * np.pi / 4.0)]], dtype=np.complex) if name == 's': return np.array([[1.0, 0.0], [0.0, np.exp(1j * np.pi / 2.0)]], dtype=np.complex) @@ -154,64 +145,65 @@ def _GateMasterDef(name = '', para = None): dtype=np.complex) if name == 'u2': return 1. / np.sqrt(2) * np.array( - [[1, -np.exp(1j * float(para[1]))], - [np.exp(1j * float(para[0])), np.exp(1j * (float(para[0]) + float(para[1])))]], - dtype=np.complex) + [[1, -np.exp(1j * float(para[1]))], + [np.exp(1j * float(para[0])), np.exp(1j * (float(para[0]) + float(para[1])))]], + dtype=np.complex) if name == 'u3': return 1./np.sqrt(2) * np.array( - [[np.cos(float(para[0]) / 2.), - -np.exp(1j * float(para[2])) * np.sin(float(para[0]) / 2.)], - [np.exp(1j * float(para[1])) * np.sin(float(para[0]) / 2.), - np.cos(float(para[0]) / 2.) * np.exp(1j * (float(para[2]) + float(para[1])))]], - dtype=np.complex) + [[np.cos(float(para[0]) / 2.), + -np.exp(1j * float(para[2])) * np.sin(float(para[0]) / 2.)], + [np.exp(1j * float(para[1])) * np.sin(float(para[0]) / 2.), + np.cos(float(para[0]) / 2.) * np.exp(1j * (float(para[2]) + float(para[1])))]], + dtype=np.complex) if name == 'P0': - return np.array([[1.0, 0.0], [0.0,0.0]], dtype = np.complex) + return np.array([[1.0, 0.0], [0.0, 0.0]], dtype=np.complex) if name == 'P1': - return np.array([[0.0, 0.0], [0.0,1.0]], dtype = np.complex) + return np.array([[0.0, 0.0], [0.0, 1.0]], dtype=np.complex) if name == 'Id': return np.identity(2) - return None def _calc_product(node1, node2): - + wire_num = len(set(node1["qargs"] + node2["qargs"])) - wires = sorted(list(map(lambda x: "{0}[{1}]".format(str(x[0].name), str(x[1])), list(set(node1["qargs"] + node2["qargs"]))))) - final_U = np.identity(2 ** wire_num, dtype = np.complex) - + wires = sorted(list(map(lambda x: "{0}[{1}]".format(str(x[0].name), str(x[1])), + list(set(node1["qargs"] + node2["qargs"]))))) + final_unitary = np.identity(2 ** wire_num, dtype=np.complex) + for node in [node1, node2]: qstate_list = [np.identity(2)] * wire_num if node['name'] == 'cx' or node['name'] == 'cy' or node['name'] == 'cz': - - qstate_list_ext = [np.identity(2)] * wire_num - - node_ctrl = "{0}[{1}]".format(str(node["qargs"][0][0].name), str(node["qargs"][0][1])) - node_tgt = "{0}[{1}]".format(str(node["qargs"][1][0].name), str(node["qargs"][1][1])) - ctrl = wires.index(node_ctrl) - tgt = wires.index(node_tgt) - - qstate_list[ctrl] = _GateMasterDef(name = 'P0') - qstate_list[tgt] = _GateMasterDef(name = 'Id') - qstate_list_ext[ctrl] = _GateMasterDef(name = 'P1') - if node['name'] == 'cx': - qstate_list_ext[tgt] = _GateMasterDef(name = 'x') - if node['name'] == 'cy': - qstate_list_ext[tgt] = _GateMasterDef(name = 'y') - if node['name'] == 'cz': - qstate_list_ext[tgt] = _GateMasterDef(name = 'z') - - rt_list = [qstate_list] + [qstate_list_ext] + + qstate_list_ext = [np.identity(2)] * wire_num + + node_ctrl = "{0}[{1}]".format(str(node["qargs"][0][0].name), str(node["qargs"][0][1])) + node_tgt = "{0}[{1}]".format(str(node["qargs"][1][0].name), str(node["qargs"][1][1])) + ctrl = wires.index(node_ctrl) + tgt = wires.index(node_tgt) + + qstate_list[ctrl] = _gate_master_def(name='P0') + qstate_list[tgt] = _gate_master_def(name='Id') + qstate_list_ext[ctrl] = _gate_master_def(name='P1') + if node['name'] == 'cx': + qstate_list_ext[tgt] = _gate_master_def(name='x') + if node['name'] == 'cy': + qstate_list_ext[tgt] = _gate_master_def(name='y') + if node['name'] == 'cz': + qstate_list_ext[tgt] = _gate_master_def(name='z') + + rt_list = [qstate_list] + [qstate_list_ext] else: - mat = _GateMasterDef(name = node['name']) - node_num = "{0}[{1}]".format(str(node["qargs"][0][0].name), str(node["qargs"][0][1])) + mat = _gate_master_def(name=node['name'], para=node['op'].param) + node_num = "{0}[{1}]".format(str(node["qargs"][0][0].name), + str(node["qargs"][0][1])) qstate_list[wires.index(node_num)] = mat rt_list = [qstate_list] @@ -221,9 +213,8 @@ def _calc_product(node1, node2): for state in rt_list: crt = crt + _kron_list(state) - final_U = np.dot(crt, final_U) - - return final_U + final_unitary = np.dot(crt, final_unitary) + return final_unitary def _kron_list(args): ret = args[0] @@ -234,7 +225,6 @@ def _kron_list(args): def _matrix_commute(node1, node2): # Good for composite gates or any future # user-defined gate of equal or less than 2 qubits. - if set(node1["qargs"]) & set(node2["qargs"]) == set(): return True diff --git a/qiskit/transpiler/passes/commutation_transformation.py b/qiskit/transpiler/passes/commutation_transformation.py index 72d8771ef3b..567b1321d36 100644 --- a/qiskit/transpiler/passes/commutation_transformation.py +++ b/qiskit/transpiler/passes/commutation_transformation.py @@ -12,8 +12,6 @@ from qiskit.transpiler._basepasses import TransformationPass from qiskit.transpiler.passes import CommutationAnalysis -from qiskit.transpiler import AnalysisPass -import numpy as np class CommutationTransformation(TransformationPass): @@ -66,9 +64,6 @@ def run(self, dag): for next_node in wire_commutation_set[c_set_ind + 1]: - nd = dag.multi_graph.node[node1] - next_nd = dag.multi_graph.node[next_node] - edge_on_wire = False for temp_edge in dag.multi_graph.edges([node1], data=True): if temp_edge[1] == next_node and temp_edge[2]['name'] == wire_name: diff --git a/test/python/transpiler/test_commutation_analysis.py b/test/python/transpiler/test_commutation_analysis.py index 6b93649c936..e53b13dc751 100644 --- a/test/python/transpiler/test_commutation_analysis.py +++ b/test/python/transpiler/test_commutation_analysis.py @@ -11,7 +11,6 @@ import unittest from qiskit import QuantumRegister, QuantumCircuit -from qiskit.dagcircuit import DAGCircuit from qiskit.transpiler import PropertySet from qiskit.transpiler.passes import CommutationAnalysis from qiskit.converters import circuit_to_dag @@ -19,6 +18,7 @@ class TestCommutationAnalysis(QiskitTestCase): + """Test the Communttion pass.""" def setUp(self): @@ -26,6 +26,7 @@ def setUp(self): self.pset = self.pass_.property_set = PropertySet() def test_commutation_set_property_is_created(self): + """Test property is created""" qr = QuantumRegister(3, 'qr') circuit = QuantumCircuit(qr) circuit.h(qr) @@ -216,6 +217,7 @@ def test_jordan_wigner_type_circuit(self): self.assertEqual(self.pset["commutation_set"]["qr[5]"], [[11], [17], [18], [19], [12]]) def test_all_commute_circuit(self): + """Test circuit with that all commute""" qr = QuantumRegister(5, 'qr') circuit = QuantumCircuit(qr) circuit.cx(qr[0], qr[1])