class TestDagApplyOperation(QiskitTestCase): """Test adding an op node to a dag.""" def setUp(self): self.dag = DAGCircuit() qreg = QuantumRegister(3, 'qr') creg = ClassicalRegister(2, 'cr') self.dag.add_qreg(qreg) self.dag.add_creg(creg) self.qubit0 = qreg[0] self.qubit1 = qreg[1] self.qubit2 = qreg[2] self.clbit0 = creg[0] self.clbit1 = creg[1] self.condition = (creg, 3) def test_apply_operation_back(self): """The apply_operation_back() method.""" self.dag.apply_operation_back(HGate(), [self.qubit0], [], condition=None) self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], [], condition=None) self.dag.apply_operation_back(Measure(), [self.qubit1, self.clbit1], [], condition=None) self.dag.apply_operation_back(XGate(), [self.qubit1], [], condition=self.condition) self.dag.apply_operation_back(Measure(), [self.qubit0, self.clbit0], [], condition=None) self.dag.apply_operation_back(Measure(), [self.qubit1, self.clbit1], [], condition=None) self.assertEqual(len(list(self.dag.nodes())), 16) self.assertEqual(len(list(self.dag.edges())), 17) def test_edges(self): """Test that DAGCircuit.edges() behaves as expected with ops.""" self.dag.apply_operation_back(HGate(), [self.qubit0], [], condition=None) self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], [], condition=None) self.dag.apply_operation_back(Measure(), [self.qubit1, self.clbit1], [], condition=None) self.dag.apply_operation_back(XGate(), [self.qubit1], [], condition=self.condition) self.dag.apply_operation_back(Measure(), [self.qubit0, self.clbit0], [], condition=None) self.dag.apply_operation_back(Measure(), [self.qubit1, self.clbit1], [], condition=None) out_edges = self.dag.edges(self.dag.output_map.values()) self.assertEqual(list(out_edges), []) in_edges = self.dag.edges(self.dag.input_map.values()) # number of edges for input nodes should be the same as number of wires self.assertEqual(len(list(in_edges)), 5) def test_apply_operation_back_conditional(self): """Test consistency of apply_operation_back with condition set.""" # Single qubit gate conditional: qc.h(qr[2]).c_if(cr, 3) h_gate = HGate() h_gate.condition = self.condition h_node = self.dag.apply_operation_back(h_gate, [self.qubit2], [], h_gate.condition) self.assertEqual(h_node.qargs, [self.qubit2]) self.assertEqual(h_node.cargs, []) self.assertEqual(h_node.condition, h_gate.condition) self.assertEqual( sorted(self.dag._get_multi_graph_in_edges(h_node._node_id)), sorted([ (self.dag.input_map[self.qubit2]._node_id, h_node._node_id, { 'wire': self.qubit2, 'name': 'qr[2]' }), (self.dag.input_map[self.clbit0]._node_id, h_node._node_id, { 'wire': self.clbit0, 'name': 'cr[0]' }), (self.dag.input_map[self.clbit1]._node_id, h_node._node_id, { 'wire': self.clbit1, 'name': 'cr[1]' }), ])) self.assertEqual( sorted(self.dag._get_multi_graph_out_edges(h_node._node_id)), sorted([ (h_node._node_id, self.dag.output_map[self.qubit2]._node_id, { 'wire': self.qubit2, 'name': 'qr[2]' }), (h_node._node_id, self.dag.output_map[self.clbit0]._node_id, { 'wire': self.clbit0, 'name': 'cr[0]' }), (h_node._node_id, self.dag.output_map[self.clbit1]._node_id, { 'wire': self.clbit1, 'name': 'cr[1]' }), ])) if self.dag._USE_RX: self.assertTrue(rx.is_directed_acyclic_graph( self.dag._multi_graph)) else: self.assertTrue(nx.is_directed_acyclic_graph( self.dag._multi_graph)) def test_apply_operation_back_conditional_measure(self): """Test consistency of apply_operation_back for conditional measure.""" # Measure targeting a clbit which is not a member of the conditional # register. qc.measure(qr[0], cr[0]).c_if(cr2, 0) new_creg = ClassicalRegister(1, 'cr2') self.dag.add_creg(new_creg) meas_gate = Measure() meas_gate.condition = (new_creg, 0) meas_node = self.dag.apply_operation_back(meas_gate, [self.qubit0], [self.clbit0], meas_gate.condition) self.assertEqual(meas_node.qargs, [self.qubit0]) self.assertEqual(meas_node.cargs, [self.clbit0]) self.assertEqual(meas_node.condition, meas_gate.condition) self.assertEqual( sorted(self.dag._get_multi_graph_in_edges(meas_node._node_id)), sorted([ (self.dag.input_map[self.qubit0]._node_id, meas_node._node_id, { 'wire': self.qubit0, 'name': 'qr[0]' }), (self.dag.input_map[self.clbit0]._node_id, meas_node._node_id, { 'wire': self.clbit0, 'name': 'cr[0]' }), (self.dag.input_map[new_creg[0]]._node_id, meas_node._node_id, { 'wire': Clbit(new_creg, 0), 'name': 'cr2[0]' }), ])) self.assertEqual( sorted(self.dag._get_multi_graph_out_edges(meas_node._node_id)), sorted([ (meas_node._node_id, self.dag.output_map[self.qubit0]._node_id, { 'wire': self.qubit0, 'name': 'qr[0]' }), (meas_node._node_id, self.dag.output_map[self.clbit0]._node_id, { 'wire': self.clbit0, 'name': 'cr[0]' }), (meas_node._node_id, self.dag.output_map[new_creg[0]]._node_id, { 'wire': Clbit(new_creg, 0), 'name': 'cr2[0]' }), ])) if self.dag._USE_RX: self.assertTrue(rx.is_directed_acyclic_graph( self.dag._multi_graph)) else: self.assertTrue(nx.is_directed_acyclic_graph( self.dag._multi_graph)) def test_apply_operation_back_conditional_measure_to_self(self): """Test consistency of apply_operation_back for measure onto conditioning bit.""" # Measure targeting a clbit which _is_ a member of the conditional # register. qc.measure(qr[0], cr[0]).c_if(cr, 3) meas_gate = Measure() meas_gate.condition = self.condition meas_node = self.dag.apply_operation_back(meas_gate, [self.qubit1], [self.clbit1], self.condition) self.assertEqual(meas_node.qargs, [self.qubit1]) self.assertEqual(meas_node.cargs, [self.clbit1]) self.assertEqual(meas_node.condition, meas_gate.condition) self.assertEqual( sorted(self.dag._get_multi_graph_in_edges(meas_node._node_id)), sorted([ (self.dag.input_map[self.qubit1]._node_id, meas_node._node_id, { 'wire': self.qubit1, 'name': 'qr[1]' }), (self.dag.input_map[self.clbit0]._node_id, meas_node._node_id, { 'wire': self.clbit0, 'name': 'cr[0]' }), (self.dag.input_map[self.clbit1]._node_id, meas_node._node_id, { 'wire': self.clbit1, 'name': 'cr[1]' }), ])) self.assertEqual( sorted(self.dag._get_multi_graph_out_edges(meas_node._node_id)), sorted([ (meas_node._node_id, self.dag.output_map[self.qubit1]._node_id, { 'wire': self.qubit1, 'name': 'qr[1]' }), (meas_node._node_id, self.dag.output_map[self.clbit0]._node_id, { 'wire': self.clbit0, 'name': 'cr[0]' }), (meas_node._node_id, self.dag.output_map[self.clbit1]._node_id, { 'wire': self.clbit1, 'name': 'cr[1]' }), ])) if self.dag._USE_RX: self.assertTrue(rx.is_directed_acyclic_graph( self.dag._multi_graph)) else: self.assertTrue(nx.is_directed_acyclic_graph( self.dag._multi_graph)) def test_apply_operation_front(self): """The apply_operation_front() method""" self.dag.apply_operation_back(HGate(), [self.qubit0], []) self.dag.apply_operation_front(Reset(), [self.qubit0], []) h_node = self.dag.op_nodes(op=HGate).pop() reset_node = self.dag.op_nodes(op=Reset).pop() self.assertIn(reset_node, set(self.dag.predecessors(h_node)))
class TestDagOperations(QiskitTestCase): """Test ops inside the dag""" def setUp(self): self.dag = DAGCircuit() qreg = QuantumRegister(3, 'qr') creg = ClassicalRegister(2, 'cr') self.dag.add_qreg(qreg) self.dag.add_creg(creg) self.qubit0 = qreg[0] self.qubit1 = qreg[1] self.qubit2 = qreg[2] self.clbit0 = creg[0] self.clbit1 = creg[1] self.condition = (creg, 3) def test_apply_operation_back(self): """The apply_operation_back() method.""" self.dag.apply_operation_back(HGate(), [self.qubit0], [], condition=None) self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], [], condition=None) self.dag.apply_operation_back(Measure(), [self.qubit1, self.clbit1], [], condition=None) self.dag.apply_operation_back(XGate(), [self.qubit1], [], condition=self.condition) self.dag.apply_operation_back(Measure(), [self.qubit0, self.clbit0], [], condition=None) self.dag.apply_operation_back(Measure(), [self.qubit1, self.clbit1], [], condition=None) self.assertEqual(len(list(self.dag.nodes())), 16) self.assertEqual(len(list(self.dag.edges())), 17) def test_edges(self): """Test that DAGCircuit.edges() behaves as expected with ops.""" self.dag.apply_operation_back(HGate(), [self.qubit0], [], condition=None) self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], [], condition=None) self.dag.apply_operation_back(Measure(), [self.qubit1, self.clbit1], [], condition=None) self.dag.apply_operation_back(XGate(), [self.qubit1], [], condition=self.condition) self.dag.apply_operation_back(Measure(), [self.qubit0, self.clbit0], [], condition=None) self.dag.apply_operation_back(Measure(), [self.qubit1, self.clbit1], [], condition=None) out_edges = self.dag.edges(self.dag.output_map.values()) self.assertEqual(list(out_edges), []) in_edges = self.dag.edges(self.dag.input_map.values()) # number of edges for input nodes should be the same as number of wires self.assertEqual(len(list(in_edges)), 5) def test_apply_operation_back_conditional(self): """Test consistency of apply_operation_back with condition set.""" # Single qubit gate conditional: qc.h(qr[2]).c_if(cr, 3) h_gate = HGate() h_gate.condition = self.condition h_node = self.dag.apply_operation_back( h_gate, [self.qubit2], [], h_gate.condition) self.assertEqual(h_node.qargs, [self.qubit2]) self.assertEqual(h_node.cargs, []) self.assertEqual(h_node.condition, h_gate.condition) self.assertEqual( sorted(self.dag._get_multi_graph_in_edges(h_node._node_id)), sorted([ (self.dag.input_map[self.qubit2]._node_id, h_node._node_id, {'wire': self.qubit2, 'name': 'qr[2]'}), (self.dag.input_map[self.clbit0]._node_id, h_node._node_id, {'wire': self.clbit0, 'name': 'cr[0]'}), (self.dag.input_map[self.clbit1]._node_id, h_node._node_id, {'wire': self.clbit1, 'name': 'cr[1]'}), ])) self.assertEqual( sorted(self.dag._get_multi_graph_out_edges(h_node._node_id)), sorted([ (h_node._node_id, self.dag.output_map[self.qubit2]._node_id, {'wire': self.qubit2, 'name': 'qr[2]'}), (h_node._node_id, self.dag.output_map[self.clbit0]._node_id, {'wire': self.clbit0, 'name': 'cr[0]'}), (h_node._node_id, self.dag.output_map[self.clbit1]._node_id, {'wire': self.clbit1, 'name': 'cr[1]'}), ])) if self.dag._USE_RX: self.assertTrue(rx.is_directed_acyclic_graph(self.dag._multi_graph)) else: self.assertTrue(nx.is_directed_acyclic_graph(self.dag._multi_graph)) def test_apply_operation_back_conditional_measure(self): """Test consistency of apply_operation_back for conditional measure.""" # Measure targeting a clbit which is not a member of the conditional # register. qc.measure(qr[0], cr[0]).c_if(cr2, 0) new_creg = ClassicalRegister(1, 'cr2') self.dag.add_creg(new_creg) meas_gate = Measure() meas_gate.condition = (new_creg, 0) meas_node = self.dag.apply_operation_back( meas_gate, [self.qubit0], [self.clbit0], meas_gate.condition) self.assertEqual(meas_node.qargs, [self.qubit0]) self.assertEqual(meas_node.cargs, [self.clbit0]) self.assertEqual(meas_node.condition, meas_gate.condition) self.assertEqual( sorted(self.dag._get_multi_graph_in_edges(meas_node._node_id)), sorted([ (self.dag.input_map[self.qubit0]._node_id, meas_node._node_id, {'wire': self.qubit0, 'name': 'qr[0]'}), (self.dag.input_map[self.clbit0]._node_id, meas_node._node_id, {'wire': self.clbit0, 'name': 'cr[0]'}), (self.dag.input_map[new_creg[0]]._node_id, meas_node._node_id, {'wire': Clbit(new_creg, 0), 'name': 'cr2[0]'}), ])) self.assertEqual( sorted(self.dag._get_multi_graph_out_edges(meas_node._node_id)), sorted([ (meas_node._node_id, self.dag.output_map[self.qubit0]._node_id, {'wire': self.qubit0, 'name': 'qr[0]'}), (meas_node._node_id, self.dag.output_map[self.clbit0]._node_id, {'wire': self.clbit0, 'name': 'cr[0]'}), (meas_node._node_id, self.dag.output_map[new_creg[0]]._node_id, {'wire': Clbit(new_creg, 0), 'name': 'cr2[0]'}), ])) if self.dag._USE_RX: self.assertTrue(rx.is_directed_acyclic_graph(self.dag._multi_graph)) else: self.assertTrue(nx.is_directed_acyclic_graph(self.dag._multi_graph)) def test_apply_operation_back_conditional_measure_to_self(self): """Test consistency of apply_operation_back for measure onto conditioning bit.""" # Measure targeting a clbit which _is_ a member of the conditional # register. qc.measure(qr[0], cr[0]).c_if(cr, 3) meas_gate = Measure() meas_gate.condition = self.condition meas_node = self.dag.apply_operation_back( meas_gate, [self.qubit1], [self.clbit1], self.condition) self.assertEqual(meas_node.qargs, [self.qubit1]) self.assertEqual(meas_node.cargs, [self.clbit1]) self.assertEqual(meas_node.condition, meas_gate.condition) self.assertEqual( sorted(self.dag._get_multi_graph_in_edges(meas_node._node_id)), sorted([ (self.dag.input_map[self.qubit1]._node_id, meas_node._node_id, {'wire': self.qubit1, 'name': 'qr[1]'}), (self.dag.input_map[self.clbit0]._node_id, meas_node._node_id, {'wire': self.clbit0, 'name': 'cr[0]'}), (self.dag.input_map[self.clbit1]._node_id, meas_node._node_id, {'wire': self.clbit1, 'name': 'cr[1]'}), ])) self.assertEqual( sorted(self.dag._get_multi_graph_out_edges(meas_node._node_id)), sorted([ (meas_node._node_id, self.dag.output_map[self.qubit1]._node_id, {'wire': self.qubit1, 'name': 'qr[1]'}), (meas_node._node_id, self.dag.output_map[self.clbit0]._node_id, {'wire': self.clbit0, 'name': 'cr[0]'}), (meas_node._node_id, self.dag.output_map[self.clbit1]._node_id, {'wire': self.clbit1, 'name': 'cr[1]'}), ])) if self.dag._USE_RX: self.assertTrue(rx.is_directed_acyclic_graph(self.dag._multi_graph)) else: self.assertTrue(nx.is_directed_acyclic_graph(self.dag._multi_graph)) def test_apply_operation_front(self): """The apply_operation_front() method""" self.dag.apply_operation_back(HGate(), [self.qubit0], []) self.dag.apply_operation_front(Reset(), [self.qubit0], []) h_node = self.dag.op_nodes(op=HGate).pop() reset_node = self.dag.op_nodes(op=Reset).pop() self.assertIn(reset_node, set(self.dag.predecessors(h_node))) def test_get_op_nodes_all(self): """The method dag.op_nodes() returns all op nodes""" self.dag.apply_operation_back(HGate(), [self.qubit0], []) self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], []) self.dag.apply_operation_back(Reset(), [self.qubit0], []) op_nodes = self.dag.op_nodes() self.assertEqual(len(op_nodes), 3) for node in op_nodes: self.assertIsInstance(node.op, Instruction) def test_get_op_nodes_particular(self): """The method dag.gates_nodes(op=AGate) returns all the AGate nodes""" self.dag.apply_operation_back(HGate(), [self.qubit0], []) self.dag.apply_operation_back(HGate(), [self.qubit1], []) self.dag.apply_operation_back(Reset(), [self.qubit0], []) self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], []) op_nodes = self.dag.op_nodes(op=HGate) self.assertEqual(len(op_nodes), 2) op_node_1 = op_nodes.pop() op_node_2 = op_nodes.pop() self.assertIsInstance(op_node_1.op, HGate) self.assertIsInstance(op_node_2.op, HGate) def test_quantum_successors(self): """The method dag.quantum_successors() returns successors connected by quantum edges""" # q_0: |0>─────■───|0>─ # ┌─┐┌─┴─┐ # q_1: |0>┤M├┤ X ├───── # └╥┘└───┘ # c_0: 0 ═╬═══════════ # ║ # c_1: 0 ═╩═══════════ self.dag.apply_operation_back(Measure(), [self.qubit1, self.clbit1], []) self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], []) self.dag.apply_operation_back(Reset(), [self.qubit0], []) successor_measure = self.dag.quantum_successors( self.dag.named_nodes('measure').pop()) cnot_node = next(successor_measure) with self.assertRaises(StopIteration): next(successor_measure) self.assertIsInstance(cnot_node.op, CXGate) successor_cnot = self.dag.quantum_successors(cnot_node) # Ordering between Reset and out[q1] is indeterminant. successor1 = next(successor_cnot) successor2 = next(successor_cnot) with self.assertRaises(StopIteration): next(successor_cnot) self.assertTrue( (successor1.type == 'out' and isinstance(successor2.op, Reset)) or (successor2.type == 'out' and isinstance(successor1.op, Reset)) ) def test_quantum_predecessors(self): """The method dag.quantum_predecessors() returns predecessors connected by quantum edges""" # q_0: |0>─|0>───■───── # ┌─┴─┐┌─┐ # q_1: |0>─────┤ X ├┤M├ # └───┘└╥┘ # c_0: 0 ═══════════╬═ # ║ # c_1: 0 ═══════════╩═ self.dag.apply_operation_back(Reset(), [self.qubit0], []) self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], []) self.dag.apply_operation_back(Measure(), [self.qubit1, self.clbit1], []) predecessor_measure = self.dag.quantum_predecessors( self.dag.named_nodes('measure').pop()) cnot_node = next(predecessor_measure) with self.assertRaises(StopIteration): next(predecessor_measure) self.assertIsInstance(cnot_node.op, CXGate) predecessor_cnot = self.dag.quantum_predecessors(cnot_node) # Ordering between Reset and in[q1] is indeterminant. predecessor1 = next(predecessor_cnot) predecessor2 = next(predecessor_cnot) with self.assertRaises(StopIteration): next(predecessor_cnot) self.assertTrue( (predecessor1.type == 'in' and isinstance(predecessor2.op, Reset)) or (predecessor2.type == 'in' and isinstance(predecessor1.op, Reset)) ) def test_get_gates_nodes(self): """The method dag.gate_nodes() returns all gate nodes""" self.dag.apply_operation_back(HGate(), [self.qubit0], []) self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], []) self.dag.apply_operation_back(Reset(), [self.qubit0], []) op_nodes = self.dag.gate_nodes() self.assertEqual(len(op_nodes), 2) op_node_1 = op_nodes.pop() op_node_2 = op_nodes.pop() self.assertIsInstance(op_node_1.op, Gate) self.assertIsInstance(op_node_2.op, Gate) def test_two_q_gates(self): """The method dag.two_qubit_ops() returns all 2Q gate operation nodes""" self.dag.apply_operation_back(HGate(), [self.qubit0], []) self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], []) self.dag.apply_operation_back(Barrier(2), [self.qubit0, self.qubit1], []) self.dag.apply_operation_back(Reset(), [self.qubit0], []) op_nodes = self.dag.two_qubit_ops() self.assertEqual(len(op_nodes), 1) op_node = op_nodes.pop() self.assertIsInstance(op_node.op, Gate) self.assertEqual(len(op_node.qargs), 2) def test_get_named_nodes(self): """The get_named_nodes(AName) method returns all the nodes with name AName""" self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], []) self.dag.apply_operation_back(HGate(), [self.qubit0], []) self.dag.apply_operation_back(CXGate(), [self.qubit2, self.qubit1], []) self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit2], []) self.dag.apply_operation_back(HGate(), [self.qubit2], []) # The ordering is not assured, so we only compare the output (unordered) sets. # We use tuples because lists aren't hashable. named_nodes = self.dag.named_nodes('cx') node_qargs = {tuple(node.qargs) for node in named_nodes} expected_qargs = { (self.qubit0, self.qubit1), (self.qubit2, self.qubit1), (self.qubit0, self.qubit2)} self.assertEqual(expected_qargs, node_qargs) def test_topological_nodes(self): """The topological_nodes() method""" self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], []) self.dag.apply_operation_back(HGate(), [self.qubit0], []) self.dag.apply_operation_back(CXGate(), [self.qubit2, self.qubit1], []) self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit2], []) self.dag.apply_operation_back(HGate(), [self.qubit2], []) named_nodes = self.dag.topological_nodes() expected = [('qr[0]', []), ('qr[1]', []), ('cx', [self.qubit0, self.qubit1]), ('h', [self.qubit0]), ('qr[2]', []), ('cx', [self.qubit2, self.qubit1]), ('cx', [self.qubit0, self.qubit2]), ('h', [self.qubit2]), ('qr[0]', []), ('qr[1]', []), ('qr[2]', []), ('cr[0]', []), ('cr[0]', []), ('cr[1]', []), ('cr[1]', [])] self.assertEqual(expected, [(i.name, i.qargs) for i in named_nodes]) def test_topological_op_nodes(self): """The topological_op_nodes() method""" self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], []) self.dag.apply_operation_back(HGate(), [self.qubit0], []) self.dag.apply_operation_back(CXGate(), [self.qubit2, self.qubit1], []) self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit2], []) self.dag.apply_operation_back(HGate(), [self.qubit2], []) named_nodes = self.dag.topological_op_nodes() expected = [('cx', [self.qubit0, self.qubit1]), ('h', [self.qubit0]), ('cx', [self.qubit2, self.qubit1]), ('cx', [self.qubit0, self.qubit2]), ('h', [self.qubit2])] self.assertEqual(expected, [(i.name, i.qargs) for i in named_nodes]) def test_dag_nodes_on_wire(self): """Test that listing the gates on a qubit/classical bit gets the correct gates""" self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], []) self.dag.apply_operation_back(HGate(), [self.qubit0], []) qbit = self.dag.qubits()[0] self.assertEqual([0, 10, 11, 1], [i._node_id for i in self.dag.nodes_on_wire(qbit)]) self.assertEqual([10, 11], [i._node_id for i in self.dag.nodes_on_wire(qbit, only_ops=True)]) cbit = self.dag.clbits()[0] self.assertEqual([6, 7], [i._node_id for i in self.dag.nodes_on_wire(cbit)]) self.assertEqual([], [i._node_id for i in self.dag.nodes_on_wire(cbit, only_ops=True)]) with self.assertRaises(DAGCircuitError): next(self.dag.nodes_on_wire((qbit.register, 7))) def test_dag_nodes_on_wire_multiple_successors(self): """ Test that if a DAGNode has multiple successors in the DAG along one wire, they are all retrieved in order. This could be the case for a circuit such as q0_0: |0>──■─────────■── ┌─┴─┐┌───┐┌─┴─┐ q0_1: |0>┤ X ├┤ H ├┤ X ├ └───┘└───┘└───┘ Both the 2nd CX gate and the H gate follow the first CX gate in the DAG, so they both must be returned but in the correct order. """ self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], []) self.dag.apply_operation_back(HGate(), [self.qubit1], []) self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], []) nodes = self.dag.nodes_on_wire(self.dag.qubits()[1], only_ops=True) node_names = [nd.name for nd in nodes] self.assertEqual(node_names, ['cx', 'h', 'cx']) def test_remove_op_node(self): """Test remove_op_node method.""" self.dag.apply_operation_back(HGate(), [self.qubit0]) op_nodes = self.dag.gate_nodes() h_gate = op_nodes.pop() self.dag.remove_op_node(h_gate) self.assertEqual(len(self.dag.gate_nodes()), 0) def test_remove_op_node_longer(self): """Test remove_op_node method in a "longer" dag""" self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1]) self.dag.apply_operation_back(HGate(), [self.qubit0]) self.dag.apply_operation_back(CXGate(), [self.qubit2, self.qubit1]) self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit2]) self.dag.apply_operation_back(HGate(), [self.qubit2]) op_nodes = list(self.dag.topological_op_nodes()) self.dag.remove_op_node(op_nodes[0]) expected = [('h', [self.qubit0]), ('cx', [self.qubit2, self.qubit1]), ('cx', [self.qubit0, self.qubit2]), ('h', [self.qubit2])] self.assertEqual(expected, [(i.name, i.qargs) for i in self.dag.topological_op_nodes()]) def test_remove_non_op_node(self): """Try to remove a non-op node with remove_op_node method.""" self.dag.apply_operation_back(HGate(), [self.qubit0]) in_node = next(self.dag.topological_nodes()) self.assertRaises(DAGCircuitError, self.dag.remove_op_node, in_node) def test_dag_collect_runs(self): """Test the collect_runs method with 3 different gates.""" self.dag.apply_operation_back(U1Gate(3.14), [self.qubit0]) self.dag.apply_operation_back(U1Gate(3.14), [self.qubit0]) self.dag.apply_operation_back(U1Gate(3.14), [self.qubit0]) self.dag.apply_operation_back(CXGate(), [self.qubit2, self.qubit1]) self.dag.apply_operation_back(CXGate(), [self.qubit1, self.qubit2]) self.dag.apply_operation_back(HGate(), [self.qubit2]) collected_runs = self.dag.collect_runs(['u1', 'cx', 'h']) self.assertEqual(len(collected_runs), 3) for run in collected_runs: if run[0].name == 'cx': self.assertEqual(len(run), 2) self.assertEqual(['cx'] * 2, [x.name for x in run]) self.assertEqual( [[self.qubit2, self.qubit1], [self.qubit1, self.qubit2]], [x.qargs for x in run]) elif run[0].name == 'h': self.assertEqual(len(run), 1) self.assertEqual(['h'], [x.name for x in run]) self.assertEqual([[self.qubit2]], [x.qargs for x in run]) elif run[0].name == 'u1': self.assertEqual(len(run), 3) self.assertEqual(['u1'] * 3, [x.name for x in run]) self.assertEqual( [[self.qubit0], [self.qubit0], [self.qubit0]], [x.qargs for x in run]) else: self.fail('Unknown run encountered') def test_dag_collect_runs_start_with_conditional(self): """Test collect runs with a conditional at the start of the run.""" self.dag.apply_operation_back( HGate(), [self.qubit0], condition=self.condition) self.dag.apply_operation_back(HGate(), [self.qubit0]) self.dag.apply_operation_back(HGate(), [self.qubit0]) collected_runs = self.dag.collect_runs(['h']) self.assertEqual(len(collected_runs), 1) run = collected_runs.pop() self.assertEqual(len(run), 2) self.assertEqual(['h', 'h'], [x.name for x in run]) self.assertEqual([[self.qubit0], [self.qubit0]], [x.qargs for x in run]) def test_dag_collect_runs_conditional_in_middle(self): """Test collect_runs with a conditional in the middle of a run.""" self.dag.apply_operation_back(HGate(), [self.qubit0]) self.dag.apply_operation_back( HGate(), [self.qubit0], condition=self.condition) self.dag.apply_operation_back(HGate(), [self.qubit0]) collected_runs = self.dag.collect_runs(['h']) # Should return 2 single h gate runs (1 before condition, 1 after) self.assertEqual(len(collected_runs), 2) for run in collected_runs: self.assertEqual(len(run), 1) self.assertEqual(['h'], [x.name for x in run]) self.assertEqual([[self.qubit0]], [x.qargs for x in run])