def test_compose_permuted(self): """Composing two dags of the same width, permuted wires. ┌───┐ lqr_1_0: |0>───┤ H ├─── rqr_0: |0>──■─────── ├───┤ │ ┌───┐ lqr_1_1: |0>───┤ X ├─── rqr_1: |0>──┼──┤ X ├ ┌──┴───┴──┐ │ ├───┤ lqr_1_2: |0>┤ U1(0.1) ├ rqr_2: |0>──┼──┤ Y ├ └─────────┘ ┌─┴─┐└───┘ lqr_2_0: |0>─────■───── + rqr_3: |0>┤ X ├───── = ┌─┴─┐ └───┘┌───┐ lqr_2_1: |0>───┤ X ├─── rqr_4: |0>─────┤ Z ├ └───┘ └───┘ lcr_0: 0 ══════════════ lcr_1: 0 ══════════════ ┌───┐ ┌───┐ lqr_1_0: |0>───┤ H ├───┤ Z ├ ├───┤ ├───┤ lqr_1_1: |0>───┤ X ├───┤ X ├ ┌──┴───┴──┐├───┤ lqr_1_2: |0>┤ U1(0.1) ├┤ Y ├ └─────────┘└───┘ lqr_2_0: |0>─────■───────■── ┌─┴─┐ ┌─┴─┐ lqr_2_1: |0>───┤ X ├───┤ X ├ └───┘ └───┘ lcr_0: 0 ═══════════════════ lcr_1: 0 ═══════════════════ """ qreg = QuantumRegister(5, 'rqr') right_qubit0 = qreg[0] right_qubit1 = qreg[1] right_qubit2 = qreg[2] right_qubit3 = qreg[3] right_qubit4 = qreg[4] circuit_right = QuantumCircuit(qreg) circuit_right.cx(qreg[0], qreg[3]) circuit_right.x(qreg[1]) circuit_right.y(qreg[2]) circuit_right.z(qreg[4]) dag_left = circuit_to_dag(self.circuit_left) dag_right = circuit_to_dag(circuit_right) # permuted wiring dag_left.compose(dag_right, edge_map={ right_qubit0: self.left_qubit3, right_qubit1: self.left_qubit1, right_qubit2: self.left_qubit2, right_qubit3: self.left_qubit4, right_qubit4: self.left_qubit0 }) circuit_composed = dag_to_circuit(dag_left) circuit_expected = self.circuit_left.copy() circuit_expected.z(self.left_qubit0) circuit_expected.x(self.left_qubit1) circuit_expected.y(self.left_qubit2) circuit_expected.cx(self.left_qubit3, self.left_qubit4) self.assertEqual(circuit_composed, circuit_expected)
# print(n_orbitals) initial_hf = HartreeFock(num_qubits=n_qubits, num_orbitals=n_orbitals, qubit_mapping=core._qubit_mapping, two_qubit_reduction=False, num_particles=n_electrons) var_form = UCCSD(num_qubits=n_qubits, num_orbitals=n_orbitals, num_particles=n_electrons, depth=1, initial_state=initial_hf, qubit_mapping=core._qubit_mapping, two_qubit_reduction=False) number_amplitudes = len(var_form._single_excitations) + len( var_form._double_excitations) amplitudes = [1e-4] * number_amplitudes circuit = var_form.construct_circuit(amplitudes) dag = circuit_to_dag(circuit) dag = Unroller(['cx', 'u1', 'u3']).run(dag) circuit = dag_to_circuit(dag) qasm = circuit.qasm() filename = '{m}_{f}_{q}_{b}.qasm'.format( m=mol_name, f=('frz' if freeze_core else 'cmplt'), q=qm_name, b=basis) with open(filename, 'w') as ofile: ofile.write(qasm) print(filename) print(circuit.count_ops())
def run(self, dag): """Translate an input DAGCircuit to the target basis. Args: dag (DAGCircuit): input dag Raises: TranspilerError: if the target basis cannot be reached Returns: DAGCircuit: translated circuit. """ if self._target_basis is None: return dag # Names of instructions assumed to supported by any backend. basic_instrs = ['measure', 'reset', 'barrier', 'snapshot'] target_basis = set(self._target_basis).union(basic_instrs) source_basis = set( (node.op.name, node.op.num_qubits) for node in dag.op_nodes()) logger.info( 'Begin BasisTranslator from source basis %s to target ' 'basis %s.', source_basis, target_basis) # Search for a path from source to target basis. search_start_time = time.time() basis_transforms = _basis_search(self._equiv_lib, source_basis, target_basis, _basis_heuristic) search_end_time = time.time() logger.info('Basis translation path search completed in %.3fs.', search_end_time - search_start_time) if basis_transforms is None: raise TranspilerError( 'Unable to map source basis {} to target basis {} ' 'over library {}.'.format(source_basis, target_basis, self._equiv_lib)) # Compose found path into a set of instruction substitution rules. compose_start_time = time.time() instr_map = _compose_transforms(basis_transforms, source_basis, dag) compose_end_time = time.time() logger.info('Basis translation paths composed in %.3fs.', compose_end_time - compose_start_time) # Replace source instructions with target translations. replace_start_time = time.time() for node in dag.op_nodes(): if node.name in target_basis: continue if (node.op.name, node.op.num_qubits) in instr_map: target_params, target_dag = instr_map[node.op.name, node.op.num_qubits] if len(node.op.params) != len(target_params): raise TranspilerError( 'Translation num_params not equal to op num_params.' 'Op: {} {} Translation: {}\n{}'.format( node.op.params, node.op.name, target_params, target_dag)) # Convert target to circ and back to assign_parameters, since # DAGCircuits won't have a ParameterTable. from qiskit.converters import dag_to_circuit, circuit_to_dag target_circuit = dag_to_circuit(target_dag) target_circuit.assign_parameters(dict( zip_longest(target_params, node.op.params)), inplace=True) bound_target_dag = circuit_to_dag(target_circuit) if (len(bound_target_dag.op_nodes()) == 1 and len(bound_target_dag.op_nodes()[0].qargs) == len( node.qargs)): dag.substitute_node(node, bound_target_dag.op_nodes()[0].op, inplace=True) else: dag.substitute_node_with_dag(node, bound_target_dag) else: raise TranspilerError('BasisTranslator did not map {}.'.format( node.name)) replace_end_time = time.time() logger.info('Basis translation instructions replaced in %.3fs.', replace_end_time - replace_start_time) return dag
def test_unrolling_parameterized_composite_gates(self): """Verify unrolling circuits with parameterized composite gates.""" mock_sel = EquivalenceLibrary(base=std_eqlib) qr1 = QuantumRegister(2) subqc = QuantumCircuit(qr1) theta = Parameter('theta') subqc.rz(theta, qr1[0]) subqc.cx(qr1[0], qr1[1]) subqc.rz(theta, qr1[1]) # Expanding across register with shared parameter qr2 = QuantumRegister(4) qc = QuantumCircuit(qr2) sub_instr = circuit_to_instruction(subqc, equivalence_library=mock_sel) qc.append(sub_instr, [qr2[0], qr2[1]]) qc.append(sub_instr, [qr2[2], qr2[3]]) dag = circuit_to_dag(qc) pass_ = UnrollCustomDefinitions(mock_sel, ['u1', 'cx']) dag = pass_.run(dag) out_dag = BasisTranslator(mock_sel, ['u1', 'cx']).run(dag) expected = QuantumCircuit(qr2) expected.u1(theta, qr2[0]) expected.u1(theta, qr2[2]) expected.cx(qr2[0], qr2[1]) expected.cx(qr2[2], qr2[3]) expected.u1(theta, qr2[1]) expected.u1(theta, qr2[3]) self.assertEqual(circuit_to_dag(expected), out_dag) # Expanding across register with shared parameter qc = QuantumCircuit(qr2) phi = Parameter('phi') gamma = Parameter('gamma') sub_instr = circuit_to_instruction(subqc, {theta: phi}, mock_sel) qc.append(sub_instr, [qr2[0], qr2[1]]) sub_instr = circuit_to_instruction(subqc, {theta: gamma}, mock_sel) qc.append(sub_instr, [qr2[2], qr2[3]]) dag = circuit_to_dag(qc) pass_ = UnrollCustomDefinitions(mock_sel, ['u1', 'cx']) dag = pass_.run(dag) out_dag = BasisTranslator(mock_sel, ['u1', 'cx']).run(dag) expected = QuantumCircuit(qr2) expected.u1(phi, qr2[0]) expected.u1(gamma, qr2[2]) expected.cx(qr2[0], qr2[1]) expected.cx(qr2[2], qr2[3]) expected.u1(phi, qr2[1]) expected.u1(gamma, qr2[3]) self.assertEqual(circuit_to_dag(expected), out_dag)
def _get_layered_instructions(circuit, reverse_bits=False, justify=None): """ Given a circuit, return a tuple (qregs, cregs, ops) where qregs and cregs are the quantum and classical registers in order (based on reverse_bits) and ops is a list of DAG nodes which type is "operation". Args: circuit (QuantumCircuit): From where the information is extracted. reverse_bits (bool): If true the order of the bits in the registers is reversed. justify (str) : `left`, `right` or `none`. Defaults to `left`. Says how the circuit should be justified. Returns: Tuple(list,list,list): To be consumed by the visualizer directly. """ if justify: justify = justify.lower() # default to left justify = justify if justify in ('right', 'none') else 'left' dag = circuit_to_dag(circuit) ops = [] qregs = [] cregs = [] for qreg in dag.qregs.values(): qregs += [(qreg, bitno) for bitno in range(qreg.size)] for creg in dag.cregs.values(): cregs += [(creg, bitno) for bitno in range(creg.size)] if justify == 'none': for node in dag.topological_op_nodes(): ops.append([node]) if justify == 'left': for dag_layer in dag.layers(): layers = [] current_layer = [] dag_nodes = dag_layer['graph'].op_nodes() dag_nodes.sort(key=lambda nd: nd._node_id) for node in dag_nodes: multibit_gate = len(node.qargs) + len(node.cargs) > 1 if multibit_gate: # need to see if it crosses over any other nodes gate_span = _get_gate_span(qregs, node) all_indices = [] for check_node in dag_nodes: if check_node != node: all_indices += _get_gate_span(qregs, check_node) if any(i in gate_span for i in all_indices): # needs to be a new layer layers.append([node]) else: # can be added current_layer.append(node) else: current_layer.append(node) if current_layer: layers.append(current_layer) ops += layers if justify == 'right': dag_layers = [] for dag_layer in dag.layers(): dag_layers.append(dag_layer) # Have to work from the end of the circuit dag_layers.reverse() # Dict per layer, keys are qubits and values are the gate layer_dicts = [{}] for dag_layer in dag_layers: dag_instructions = dag_layer['graph'].op_nodes() # sort into the order they were input dag_instructions.sort(key=lambda nd: nd._node_id) for instruction_node in dag_instructions: gate_span = _get_gate_span(qregs, instruction_node) added = False for i in range(len(layer_dicts)): # iterate from the end curr_dict = layer_dicts[-1 - i] if any(index in curr_dict for index in gate_span): added = True if i == 0: new_dict = {} for index in gate_span: new_dict[index] = instruction_node layer_dicts.append(new_dict) else: curr_dict = layer_dicts[-i] for index in gate_span: curr_dict[index] = instruction_node break if not added: for index in gate_span: layer_dicts[0][index] = instruction_node # need to convert from dict format to layers layer_dicts.reverse() ops = [list(layer.values()) for layer in layer_dicts] if reverse_bits: qregs.reverse() cregs.reverse() return qregs, cregs, ops
def modify_subcircuit_instance(subcircuit, init, meas): """ Modify the different init, meas for a given subcircuit Returns: Modified subcircuit_instance List of mutated measurements """ subcircuit_dag = circuit_to_dag(subcircuit) subcircuit_instance_dag = copy.deepcopy(subcircuit_dag) for i, x in enumerate(init): q = subcircuit.qubits[i] if x == "zero": continue elif x == "one": subcircuit_instance_dag.apply_operation_front( op=XGate(), qargs=[q], cargs=[] ) elif x == "plus": subcircuit_instance_dag.apply_operation_front( op=HGate(), qargs=[q], cargs=[] ) elif x == "minus": subcircuit_instance_dag.apply_operation_front( op=HGate(), qargs=[q], cargs=[] ) subcircuit_instance_dag.apply_operation_front( op=XGate(), qargs=[q], cargs=[] ) elif x == "plusI": subcircuit_instance_dag.apply_operation_front( op=SGate(), qargs=[q], cargs=[] ) subcircuit_instance_dag.apply_operation_front( op=HGate(), qargs=[q], cargs=[] ) elif x == "minusI": subcircuit_instance_dag.apply_operation_front( op=SGate(), qargs=[q], cargs=[] ) subcircuit_instance_dag.apply_operation_front( op=HGate(), qargs=[q], cargs=[] ) subcircuit_instance_dag.apply_operation_front( op=XGate(), qargs=[q], cargs=[] ) else: raise Exception("Illegal initialization :", x) for i, x in enumerate(meas): q = subcircuit.qubits[i] if x == "I" or x == "comp": continue elif x == "X": subcircuit_instance_dag.apply_operation_back( op=HGate(), qargs=[q], cargs=[] ) elif x == "Y": subcircuit_instance_dag.apply_operation_back( op=SdgGate(), qargs=[q], cargs=[] ) subcircuit_instance_dag.apply_operation_back( op=HGate(), qargs=[q], cargs=[] ) else: raise Exception("Illegal measurement basis:", x) subcircuit_instance_circuit = dag_to_circuit(subcircuit_instance_dag) return subcircuit_instance_circuit
def test_congestion(self): """Test code path that falls back to serial layers.""" coupling = CouplingMap([[0, 1], [1, 2], [1, 3]]) qr = QuantumRegister(2, 'q') ar = QuantumRegister(2, 'a') cr = ClassicalRegister(4, 'c') circ = QuantumCircuit(qr, ar, cr) circ.cx(qr[1], ar[0]) circ.cx(qr[0], ar[1]) circ.measure(qr[0], cr[0]) circ.h(qr) circ.h(ar) circ.cx(qr[0], qr[1]) circ.cx(ar[0], ar[1]) circ.measure(qr[0], cr[0]) circ.measure(qr[1], cr[1]) circ.measure(ar[0], cr[2]) circ.measure(ar[1], cr[3]) dag = circuit_to_dag(circ) # ┌─┐┌───┐ ┌─┐ # q_0: |0>─────────────────■──────────────────┤M├┤ H ├──■─────┤M├ # ┌───┐ │ └╥┘└───┘┌─┴─┐┌─┐└╥┘ # q_1: |0>──■───────┤ H ├──┼───────────────────╫──────┤ X ├┤M├─╫─ # ┌─┴─┐┌───┐└───┘ │ ┌─┐ ║ └───┘└╥┘ ║ # a_0: |0>┤ X ├┤ H ├───────┼─────────■─────┤M├─╫────────────╫──╫─ # └───┘└───┘ ┌─┴─┐┌───┐┌─┴─┐┌─┐└╥┘ ║ ║ ║ # a_1: |0>───────────────┤ X ├┤ H ├┤ X ├┤M├─╫──╫────────────╫──╫─ # └───┘└───┘└───┘└╥┘ ║ ║ ║ ║ # c_0: 0 ═══════════════════════════════╬══╬══╩════════════╬══╩═ # ║ ║ ║ # c_1: 0 ═══════════════════════════════╬══╬═══════════════╩════ # ║ ║ # c_2: 0 ═══════════════════════════════╬══╩════════════════════ # ║ # c_3: 0 ═══════════════════════════════╩═══════════════════════ # # ┌─┐┌───┐ ┌─┐ # q_0: |0>────────────────────■──┤M├┤ H ├──────────────────■──┤M├────── # ┌─┴─┐└╥┘└───┘┌───┐┌───┐ ┌─┴─┐└╥┘┌─┐ # q_1: |0>──■───X───────────┤ X ├─╫──────┤ H ├┤ X ├─X────┤ X ├─╫─┤M├─── # ┌─┴─┐ │ ┌───┐└───┘ ║ └───┘└─┬─┘ │ └───┘ ║ └╥┘┌─┐ # a_0: |0>┤ X ├─┼──────┤ H ├──────╫─────────────■───┼──────────╫──╫─┤M├ # └───┘ │ ┌───┐└───┘ ║ │ ┌─┐ ║ ║ └╥┘ # a_1: |0>──────X─┤ H ├───────────╫─────────────────X─┤M├──────╫──╫──╫─ # └───┘ ║ └╥┘ ║ ║ ║ # c_0: 0 ════════════════════════╩════════════════════╬═══════╩══╬══╬═ # ║ ║ ║ # c_1: 0 ═════════════════════════════════════════════╬══════════╩══╬═ # ║ ║ # c_2: 0 ═════════════════════════════════════════════╬═════════════╩═ # ║ # c_3: 0 ═════════════════════════════════════════════╩═══════════════ # # Layout from mapper: # {qr[0]: 0, # qr[1]: 1, # ar[0]: 2, # ar[1]: 3} # # 2 # | # 0 - 1 - 3 expected = QuantumCircuit(qr, ar, cr) expected.cx(qr[1], ar[0]) expected.swap(qr[0], qr[1]) expected.cx(qr[1], ar[1]) expected.h(ar[1]) expected.h(ar[0]) expected.measure(qr[1], cr[0]) expected.h(qr[0]) expected.swap(qr[1], ar[1]) expected.h(ar[1]) expected.cx(ar[0], qr[1]) expected.measure(ar[0], cr[2]) expected.swap(qr[1], ar[1]) expected.measure(ar[1], cr[3]) expected.cx(qr[1], qr[0]) expected.measure(qr[1], cr[0]) expected.measure(qr[0], cr[1]) expected_dag = circuit_to_dag(expected) layout = Layout({qr[0]: 0, qr[1]: 1, ar[0]: 2, ar[1]: 3}) pass_ = StochasticSwap(coupling, layout, 20, 13) after = pass_.run(dag) self.assertEqual(expected_dag, after)
def test_unrolling_parameterized_composite_gates(self): """Verify unrolling circuits with parameterized composite gates.""" mock_sel = EquivalenceLibrary(base=std_eqlib) qr1 = QuantumRegister(2) subqc = QuantumCircuit(qr1) theta = Parameter("theta") subqc.rz(theta, qr1[0]) subqc.cx(qr1[0], qr1[1]) subqc.rz(theta, qr1[1]) # Expanding across register with shared parameter qr2 = QuantumRegister(4) qc = QuantumCircuit(qr2) sub_instr = circuit_to_instruction(subqc, equivalence_library=mock_sel) qc.append(sub_instr, [qr2[0], qr2[1]]) qc.append(sub_instr, [qr2[2], qr2[3]]) dag = circuit_to_dag(qc) pass_ = UnrollCustomDefinitions(mock_sel, ["p", "cx"]) dag = pass_.run(dag) out_dag = BasisTranslator(mock_sel, ["p", "cx"]).run(dag) # Pick up -1 * theta / 2 global phase four twice (once for each RZ -> P # in each of the two sub_instr instructions). expected = QuantumCircuit(qr2, global_phase=-1 * 4 * theta / 2.0) expected.p(theta, qr2[0]) expected.p(theta, qr2[2]) expected.cx(qr2[0], qr2[1]) expected.cx(qr2[2], qr2[3]) expected.p(theta, qr2[1]) expected.p(theta, qr2[3]) self.assertEqual(circuit_to_dag(expected), out_dag) # Expanding across register with shared parameter qc = QuantumCircuit(qr2) phi = Parameter("phi") gamma = Parameter("gamma") sub_instr = circuit_to_instruction(subqc, {theta: phi}, mock_sel) qc.append(sub_instr, [qr2[0], qr2[1]]) sub_instr = circuit_to_instruction(subqc, {theta: gamma}, mock_sel) qc.append(sub_instr, [qr2[2], qr2[3]]) dag = circuit_to_dag(qc) pass_ = UnrollCustomDefinitions(mock_sel, ["p", "cx"]) dag = pass_.run(dag) out_dag = BasisTranslator(mock_sel, ["p", "cx"]).run(dag) expected = QuantumCircuit(qr2, global_phase=-1 * (2 * phi + 2 * gamma) / 2.0) expected.p(phi, qr2[0]) expected.p(gamma, qr2[2]) expected.cx(qr2[0], qr2[1]) expected.cx(qr2[2], qr2[3]) expected.p(phi, qr2[1]) expected.p(gamma, qr2[3]) self.assertEqual(circuit_to_dag(expected), out_dag)
def test_congestion(self): """Test code path that falls back to serial layers.""" coupling = CouplingMap([[0, 1], [1, 2], [1, 3]]) qr = QuantumRegister(4, 'q') cr = ClassicalRegister(4, 'c') circ = QuantumCircuit(qr, cr) circ.cx(qr[1], qr[2]) circ.cx(qr[0], qr[3]) circ.measure(qr[0], cr[0]) circ.h(qr) circ.cx(qr[0], qr[1]) circ.cx(qr[2], qr[3]) circ.measure(qr[0], cr[0]) circ.measure(qr[1], cr[1]) circ.measure(qr[2], cr[2]) circ.measure(qr[3], cr[3]) dag = circuit_to_dag(circ) # ┌─┐┌───┐ ┌─┐ # q_0: |0>─────────────────■──────────────────┤M├┤ H ├──■─────┤M├ # ┌───┐ │ └╥┘└───┘┌─┴─┐┌─┐└╥┘ # q_1: |0>──■───────┤ H ├──┼───────────────────╫──────┤ X ├┤M├─╫─ # ┌─┴─┐┌───┐└───┘ │ ┌─┐ ║ └───┘└╥┘ ║ # q_2: |0>┤ X ├┤ H ├───────┼─────────■─────┤M├─╫────────────╫──╫─ # └───┘└───┘ ┌─┴─┐┌───┐┌─┴─┐┌─┐└╥┘ ║ ║ ║ # q_3: |0>───────────────┤ X ├┤ H ├┤ X ├┤M├─╫──╫────────────╫──╫─ # └───┘└───┘└───┘└╥┘ ║ ║ ║ ║ # c_0: 0 ═══════════════════════════════╬══╬══╩════════════╬══╩═ # ║ ║ ║ # c_1: 0 ═══════════════════════════════╬══╬═══════════════╩════ # ║ ║ # c_2: 0 ═══════════════════════════════╬══╩════════════════════ # ║ # c_3: 0 ═══════════════════════════════╩═══════════════════════ # # ┌───┐ ┌───┐ ┌─┐ # q_0: |0>───────X──┤ H ├──────────────────────┤ X ├───┤M├ # │ └───┘┌─┐ ┌───┐ └─┬─┘┌─┐└╥┘ # q_1: |0>──■────X────■──┤M├──────X─┤ X ├─X──────■──┤M├─╫─ # ┌─┴─┐┌───┐ │ └╥┘ │ └─┬─┘ │ ┌─┐ └╥┘ ║ # q_2: |0>┤ X ├┤ H ├──┼───╫───────┼───■───┼─┤M├──────╫──╫─ # └───┘└───┘┌─┴─┐ ║ ┌───┐ │ ┌───┐ │ └╥┘ ┌─┐ ║ ║ # q_3: |0>──────────┤ X ├─╫─┤ H ├─X─┤ H ├─X──╫──┤M├──╫──╫─ # └───┘ ║ └───┘ └───┘ ║ └╥┘ ║ ║ # c_0: 0 ════════════════╩══════════════════╬═══╬═══╩══╬═ # ║ ║ ║ # c_1: 0 ═══════════════════════════════════╬═══╬══════╩═ # ║ ║ # c_2: 0 ═══════════════════════════════════╩═══╬════════ # ║ # c_3: 0 ═══════════════════════════════════════╩════════ # # 2 # | # 0 - 1 - 3 expected = QuantumCircuit(qr, cr) expected.cx(qr[1], qr[2]) expected.h(qr[2]) expected.swap(qr[0], qr[1]) expected.h(qr[0]) expected.cx(qr[1], qr[3]) expected.measure(qr[1], cr[0]) expected.h(qr[3]) expected.swap(qr[1], qr[3]) expected.cx(qr[2], qr[1]) expected.h(qr[3]) expected.swap(qr[1], qr[3]) expected.measure(qr[2], cr[2]) expected.measure(qr[3], cr[3]) expected.cx(qr[1], qr[0]) expected.measure(qr[1], cr[0]) expected.measure(qr[0], cr[1]) expected_dag = circuit_to_dag(expected) pass_ = StochasticSwap(coupling, 20, 999) after = pass_.run(dag) self.assertEqual(expected_dag, after)
def test_unroll_1q_chain_conditional(self): """Test unroll chain of 1-qubit gates interrupted by conditional.""" # ┌───┐┌─────┐┌───┐┌───┐┌─────────┐┌─────────┐┌─────────┐┌─┐ ┌───┐ ┌───┐ » # qr: ┤ H ├┤ Tdg ├┤ Z ├┤ T ├┤ Ry(0.5) ├┤ Rz(0.3) ├┤ Rx(0.1) ├┤M├─┤ X ├──┤ Y ├─» # └───┘└─────┘└───┘└───┘└─────────┘└─────────┘└─────────┘└╥┘ └─╥─┘ └─╥─┘ » # ║ ┌──╨──┐┌──╨──┐» # cr: 1/══════════════════════════════════════════════════════╩═╡ 0x1 ╞╡ 0x1 ╞» # 0 └─────┘└─────┘» # « ┌───┐ # « qr: ─┤ Z ├─ # « └─╥─┘ # « ┌──╨──┐ # «cr: 1/╡ 0x1 ╞ # « └─────┘ qr = QuantumRegister(1, "qr") cr = ClassicalRegister(1, "cr") circuit = QuantumCircuit(qr, cr) circuit.h(qr) circuit.tdg(qr) circuit.z(qr) circuit.t(qr) circuit.ry(0.5, qr) circuit.rz(0.3, qr) circuit.rx(0.1, qr) circuit.measure(qr, cr) circuit.x(qr).c_if(cr, 1) circuit.y(qr).c_if(cr, 1) circuit.z(qr).c_if(cr, 1) dag = circuit_to_dag(circuit) pass_ = UnrollCustomDefinitions(std_eqlib, ["u1", "u2", "u3"]) dag = pass_.run(dag) pass_ = BasisTranslator(std_eqlib, ["u1", "u2", "u3"]) unrolled_dag = pass_.run(dag) # Pick up -1 * 0.3 / 2 global phase for one RZ -> U1. # # global phase: 6.1332 # ┌─────────┐┌──────────┐┌───────┐┌─────────┐┌─────────────┐┌─────────┐» # qr: ┤ U2(0,π) ├┤ U1(-π/4) ├┤ U1(π) ├┤ U1(π/4) ├┤ U3(0.5,0,0) ├┤ U1(0.3) ├» # └─────────┘└──────────┘└───────┘└─────────┘└─────────────┘└─────────┘» # cr: 1/═══════════════════════════════════════════════════════════════════» # » # « ┌──────────────────┐┌─┐┌───────────┐┌───────────────┐┌───────┐ # « qr: ┤ U3(0.1,-π/2,π/2) ├┤M├┤ U3(π,0,π) ├┤ U3(π,π/2,π/2) ├┤ U1(π) ├ # « └──────────────────┘└╥┘└─────╥─────┘└───────╥───────┘└───╥───┘ # « ║ ┌──╨──┐ ┌──╨──┐ ┌──╨──┐ # «cr: 1/═════════════════════╩════╡ 0x1 ╞════════╡ 0x1 ╞══════╡ 0x1 ╞═ # « 0 └─────┘ └─────┘ └─────┘ ref_circuit = QuantumCircuit(qr, cr, global_phase=-0.3 / 2) ref_circuit.append(U2Gate(0, pi), [qr[0]]) ref_circuit.append(U1Gate(-pi / 4), [qr[0]]) ref_circuit.append(U1Gate(pi), [qr[0]]) ref_circuit.append(U1Gate(pi / 4), [qr[0]]) ref_circuit.append(U3Gate(0.5, 0, 0), [qr[0]]) ref_circuit.append(U1Gate(0.3), [qr[0]]) ref_circuit.append(U3Gate(0.1, -pi / 2, pi / 2), [qr[0]]) ref_circuit.measure(qr[0], cr[0]) ref_circuit.append(U3Gate(pi, 0, pi), [qr[0]]).c_if(cr, 1) ref_circuit.append(U3Gate(pi, pi / 2, pi / 2), [qr[0]]).c_if(cr, 1) ref_circuit.append(U1Gate(pi), [qr[0]]).c_if(cr, 1) ref_dag = circuit_to_dag(ref_circuit) self.assertEqual(unrolled_dag, ref_dag)
def test_unroll_all_instructions(self): """Test unrolling a circuit containing all standard instructions.""" qr = QuantumRegister(3, "qr") cr = ClassicalRegister(3, "cr") circuit = QuantumCircuit(qr, cr) circuit.crx(0.5, qr[1], qr[2]) circuit.cry(0.5, qr[1], qr[2]) circuit.ccx(qr[0], qr[1], qr[2]) circuit.ch(qr[0], qr[2]) circuit.crz(0.5, qr[1], qr[2]) circuit.cswap(qr[1], qr[0], qr[2]) circuit.append(CU1Gate(0.1), [qr[0], qr[2]]) circuit.append(CU3Gate(0.2, 0.1, 0.0), [qr[1], qr[2]]) circuit.cx(qr[1], qr[0]) circuit.cy(qr[1], qr[2]) circuit.cz(qr[2], qr[0]) circuit.h(qr[1]) circuit.i(qr[0]) circuit.rx(0.1, qr[0]) circuit.ry(0.2, qr[1]) circuit.rz(0.3, qr[2]) circuit.rzz(0.6, qr[1], qr[0]) circuit.s(qr[0]) circuit.sdg(qr[1]) circuit.swap(qr[1], qr[2]) circuit.t(qr[2]) circuit.tdg(qr[0]) circuit.append(U1Gate(0.1), [qr[1]]) circuit.append(U2Gate(0.2, -0.1), [qr[0]]) circuit.append(U3Gate(0.3, 0.0, -0.1), [qr[2]]) circuit.x(qr[2]) circuit.y(qr[1]) circuit.z(qr[0]) # circuit.snapshot('0') # circuit.measure(qr, cr) dag = circuit_to_dag(circuit) pass_ = UnrollCustomDefinitions(std_eqlib, ["u3", "cx", "id"]) dag = pass_.run(dag) pass_ = BasisTranslator(std_eqlib, ["u3", "cx", "id"]) unrolled_dag = pass_.run(dag) ref_circuit = QuantumCircuit(qr, cr) ref_circuit.append(U3Gate(0, 0, pi / 2), [qr[2]]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.append(U3Gate(-0.25, 0, 0), [qr[2]]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.append(U3Gate(0.25, -pi / 2, 0), [qr[2]]) ref_circuit.append(U3Gate(0.25, 0, 0), [qr[2]]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.append(U3Gate(-0.25, 0, 0), [qr[2]]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.append(U3Gate(pi / 2, 0, pi), [qr[2]]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.append(U3Gate(0, 0, -pi / 4), [qr[2]]) ref_circuit.cx(qr[0], qr[2]) ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[2]]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[1]]) ref_circuit.append(U3Gate(0, 0, -pi / 4), [qr[2]]) ref_circuit.cx(qr[0], qr[2]) ref_circuit.cx(qr[0], qr[1]) ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[0]]) ref_circuit.append(U3Gate(0, 0, -pi / 4), [qr[1]]) ref_circuit.cx(qr[0], qr[1]) ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[2]]) ref_circuit.append(U3Gate(pi / 2, 0, pi), [qr[2]]) ref_circuit.append(U3Gate(0, 0, pi / 2), [qr[2]]) ref_circuit.append(U3Gate(pi / 2, 0, pi), [qr[2]]) ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[2]]) ref_circuit.cx(qr[0], qr[2]) ref_circuit.append(U3Gate(0, 0, -pi / 4), [qr[2]]) ref_circuit.append(U3Gate(pi / 2, 0, pi), [qr[2]]) ref_circuit.append(U3Gate(0, 0, -pi / 2), [qr[2]]) ref_circuit.append(U3Gate(0, 0, 0.25), [qr[2]]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.append(U3Gate(0, 0, -0.25), [qr[2]]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.cx(qr[2], qr[0]) ref_circuit.append(U3Gate(pi / 2, 0, pi), [qr[2]]) ref_circuit.cx(qr[0], qr[2]) ref_circuit.append(U3Gate(0, 0, -pi / 4), [qr[2]]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[2]]) ref_circuit.cx(qr[0], qr[2]) ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[0]]) ref_circuit.append(U3Gate(0, 0, -pi / 4), [qr[2]]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.cx(qr[1], qr[0]) ref_circuit.append(U3Gate(0, 0, -pi / 4), [qr[0]]) ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[1]]) ref_circuit.cx(qr[1], qr[0]) ref_circuit.append(U3Gate(0, 0, 0.05), [qr[1]]) ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[2]]) ref_circuit.append(U3Gate(pi / 2, 0, pi), [qr[2]]) ref_circuit.cx(qr[2], qr[0]) ref_circuit.append(U3Gate(0, 0, 0.05), [qr[0]]) ref_circuit.cx(qr[0], qr[2]) ref_circuit.append(U3Gate(0, 0, -0.05), [qr[2]]) ref_circuit.cx(qr[0], qr[2]) ref_circuit.append(U3Gate(0, 0, 0.05), [qr[2]]) ref_circuit.append(U3Gate(0, 0, -0.05), [qr[2]]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.append(U3Gate(-0.1, 0, -0.05), [qr[2]]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.cx(qr[1], qr[0]) ref_circuit.append(U3Gate(pi / 2, 0, pi), [qr[0]]) ref_circuit.append(U3Gate(0.1, 0.1, 0), [qr[2]]) ref_circuit.append(U3Gate(0, 0, -pi / 2), [qr[2]]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.append(U3Gate(pi / 2, 0, pi), [qr[1]]) ref_circuit.append(U3Gate(0.2, 0, 0), [qr[1]]) ref_circuit.append(U3Gate(0, 0, pi / 2), [qr[2]]) ref_circuit.cx(qr[2], qr[0]) ref_circuit.append(U3Gate(pi / 2, 0, pi), [qr[0]]) ref_circuit.i(qr[0]) ref_circuit.append(U3Gate(0.1, -pi / 2, pi / 2), [qr[0]]) ref_circuit.cx(qr[1], qr[0]) ref_circuit.append(U3Gate(0, 0, 0.6), [qr[0]]) ref_circuit.cx(qr[1], qr[0]) ref_circuit.append(U3Gate(0, 0, pi / 2), [qr[0]]) ref_circuit.append(U3Gate(0, 0, -pi / 4), [qr[0]]) ref_circuit.append(U3Gate(pi / 2, 0.2, -0.1), [qr[0]]) ref_circuit.append(U3Gate(0, 0, pi), [qr[0]]) ref_circuit.append(U3Gate(0, 0, -pi / 2), [qr[1]]) ref_circuit.append(U3Gate(0, 0, 0.3), [qr[2]]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.cx(qr[2], qr[1]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.append(U3Gate(0, 0, 0.1), [qr[1]]) ref_circuit.append(U3Gate(pi, pi / 2, pi / 2), [qr[1]]) ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[2]]) ref_circuit.append(U3Gate(0.3, 0.0, -0.1), [qr[2]]) ref_circuit.append(U3Gate(pi, 0, pi), [qr[2]]) # ref_circuit.snapshot('0') # ref_circuit.measure(qr, cr) # ref_dag = circuit_to_dag(ref_circuit) self.assertTrue( Operator(dag_to_circuit(unrolled_dag)).equiv(ref_circuit))
qc.u3(3.14, 3.14, 3.14, qr[0]) qc.h(qr[0]) qc.h(qr[1]) qc.cx(qr[0], qr[1]) qc.h(qr[0]) qc.h(qr[1]) qc.cx(qr[0], qr[1]) qc.h(qr[0]) qc.h(qr[1]) qc.cx(qr[0], qr[1]) qc.swap(qr[0], qr[2]) qc.ch(qr[0], qr[2]) qc.t(qr[1]) qc.h(qr) dag = converters.circuit_to_dag(qc) dag = passes.Unroller(['u1', 'u2', 'u3', 'cx', 'id']).run(dag) block_pass = passes.Collect2qBlocks() block_pass.run(dag) consolidate_pass = passes.ConsolidateBlocks() consolidate_pass.property_set['block_list'] = block_pass.property_set[ 'block_list'] out_dag = consolidate_pass.run(dag) out_circ = converters.dag_to_circuit(out_dag) print(out_circ.draw(output='latex_source')) unrolled_output_dag = passes.Unroller(['u1', 'u2', 'u3', 'cx', 'id']).run(out_dag) unrolled_output_dag = passes.Optimize1qGates().run(unrolled_output_dag)
def test_compose_inorder(self): """Composing two dags of the same width, default order. ┌───┐ lqr_1_0: |0>───┤ H ├─── rqr_0: |0>──■─────── ├───┤ │ ┌───┐ lqr_1_1: |0>───┤ X ├─── rqr_1: |0>──┼──┤ X ├ ┌──┴───┴──┐ │ ├───┤ lqr_1_2: |0>┤ U1(0.1) ├ + rqr_2: |0>──┼──┤ Y ├ = └─────────┘ ┌─┴─┐└───┘ lqr_2_0: |0>─────■───── rqr_3: |0>┤ X ├───── ┌─┴─┐ └───┘┌───┐ lqr_2_1: |0>───┤ X ├─── rqr_4: |0>─────┤ Z ├ └───┘ └───┘ lcr_0: 0 ═══════════ lcr_1: 0 ═══════════ ┌───┐ lqr_1_0: |0>───┤ H ├─────■─────── ├───┤ │ ┌───┐ lqr_1_1: |0>───┤ X ├─────┼──┤ X ├ ┌──┴───┴──┐ │ ├───┤ lqr_1_2: |0>┤ U1(0.1) ├──┼──┤ Y ├ └─────────┘┌─┴─┐└───┘ lqr_2_0: |0>─────■─────┤ X ├───── ┌─┴─┐ └───┘┌───┐ lqr_2_1: |0>───┤ X ├────────┤ Z ├ └───┘ └───┘ lcr_0: 0 ════════════════════════ lcr_1: 0 ════════════════════════ """ qreg = QuantumRegister(5, 'rqr') right_qubit0 = qreg[0] right_qubit1 = qreg[1] right_qubit2 = qreg[2] right_qubit3 = qreg[3] right_qubit4 = qreg[4] circuit_right = QuantumCircuit(qreg) circuit_right.cx(qreg[0], qreg[3]) circuit_right.x(qreg[1]) circuit_right.y(qreg[2]) circuit_right.z(qreg[4]) dag_left = circuit_to_dag(self.circuit_left) dag_right = circuit_to_dag(circuit_right) # default wiring: i <- i dag_left.compose(dag_right) circuit_composed = dag_to_circuit(dag_left) circuit_expected = self.circuit_left.copy() circuit_expected.cx(self.left_qubit0, self.left_qubit3) circuit_expected.x(self.left_qubit1) circuit_expected.y(self.left_qubit2) circuit_expected.z(self.left_qubit4) self.assertEqual(circuit_composed, circuit_expected)
def test_compose_classical(self): """Composing on classical bits. ┌───┐ ┌─────┐┌─┐ lqr_1_0: |0>───┤ H ├─── rqr_0: |0>──■──┤ Tdg ├┤M├ ├───┤ ┌─┴─┐└─┬─┬─┘└╥┘ lqr_1_1: |0>───┤ X ├─── rqr_1: |0>┤ X ├──┤M├───╫─ ┌──┴───┴──┐ └───┘ └╥┘ ║ lqr_1_2: |0>┤ U1(0.1) ├ + rcr_0: 0 ════════╬════╩═ = └─────────┘ ║ lqr_2_0: |0>─────■───── rcr_1: 0 ════════╩══════ ┌─┴─┐ lqr_2_1: |0>───┤ X ├─── └───┘ lcr_0: 0 ══════════════ lcr_1: 0 ══════════════ ┌───┐ lqr_1_0: |0>───┤ H ├────────────────── ├───┤ ┌─────┐┌─┐ lqr_1_1: |0>───┤ X ├─────■──┤ Tdg ├┤M├ ┌──┴───┴──┐ │ └─────┘└╥┘ lqr_1_2: |0>┤ U1(0.1) ├──┼──────────╫─ └─────────┘ │ ║ lqr_2_0: |0>─────■───────┼──────────╫─ ┌─┴─┐ ┌─┴─┐ ┌─┐ ║ lqr_2_1: |0>───┤ X ├───┤ X ├──┤M├───╫─ └───┘ └───┘ └╥┘ ║ lcr_0: 0 ═══════════════════╩════╬═ ║ lcr_1: 0 ════════════════════════╩═ """ qreg = QuantumRegister(2, 'rqr') creg = ClassicalRegister(2, 'rcr') right_qubit0 = qreg[0] right_qubit1 = qreg[1] right_clbit0 = creg[0] right_clbit1 = creg[1] circuit_right = QuantumCircuit(qreg, creg) circuit_right.cx(qreg[0], qreg[1]) circuit_right.tdg(qreg[0]) circuit_right.measure(qreg, creg) dag_left = circuit_to_dag(self.circuit_left) dag_right = circuit_to_dag(circuit_right) # permuted subset of qubits and clbits dag_left.compose(dag_right, edge_map={ right_qubit0: self.left_qubit1, right_qubit1: self.left_qubit4, right_clbit0: self.left_clbit1, right_clbit1: self.left_clbit0 }) circuit_composed = dag_to_circuit(dag_left) circuit_expected = self.circuit_left.copy() circuit_expected.cx(self.left_qubit1, self.left_qubit4) circuit_expected.tdg(self.left_qubit1) circuit_expected.measure(self.left_qubit4, self.left_clbit0) circuit_expected.measure(self.left_qubit1, self.left_clbit1) self.assertEqual(circuit_composed, circuit_expected)
#circuit.cu1(pi/8, qreg_q[3], qreg_q[0]) #circuit.cu1(pi/4, qreg_q[3], qreg_q[1]) #circuit.cu1(pi/2, qreg_q[3], qreg_q[2]) #circuit.h(qreg_q[3]) #circuit.draw(output='text') mapping = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ,13] #layout = Layout({qr[i]: mapping[i] for i in range(14)}) list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10] #de=circuit.decompose(); circuit.draw(output='mpl',filename='crosstalkqft.jpg') circuit.qasm(filename='qaoa_10.qasm') print(circuit.depth()) new_circ = transpile(circuit, backend=backend, initial_layout=mapping, routing_method='sabre') #new_circ.draw(output='mpl',filename='crosstalkbase.jpg') new_circ.qasm(filename='crosstalkqft10.qasm') print(new_circ.depth()) dag = circuit_to_dag(new_circ) print(crosstalk_prop) pass_ = CrosstalkAdaptiveSchedule(backend.properties(), crosstalk_prop) print(list) scheduled_dag = pass_.run(dag) scheduled_circuit = dag_to_circuit(scheduled_dag) print(scheduled_circuit.depth()) scheduled_circuit.draw(output='mpl',filename='crosstalkqft.jpg')
def expected_dag(): q0 = QuantumRegister(5, "q0") c1 = ClassicalRegister(1, "c1") qc = QuantumCircuit(q0, c1) qc.h(q0[0]) return circuit_to_dag(qc)
def test_optimize_nswap_nmeasure(self): """ Remove severals swap affecting multiple measurements ┌─┐ ┌─┐ q_0: ─X──X─────X────┤M├───────────────────────────────── q_0: ──────┤M├─────────────── │ │ │ └╥┘ ┌─┐ ┌─┐└╥┘ q_1: ─X──X──X──X──X──╫─────X────┤M├───────────────────── q_1: ───┤M├─╫──────────────── │ │ ║ │ └╥┘ ┌─┐ ┌─┐└╥┘ ║ q_2: ───────X──X──X──╫──X──X─────╫──X────┤M├──────────── q_2: ┤M├─╫──╫──────────────── │ ║ │ ║ │ └╥┘┌─┐ └╥┘ ║ ║ ┌─┐ q_3: ─X─────X──X─────╫──X──X──X──╫──X─────╫─┤M├───────── q_3: ─╫──╫──╫────┤M├───────── │ │ ║ │ │ ║ ║ └╥┘┌─┐ ║ ║ ║ └╥┘ ┌─┐ q_4: ─X──X──X──X─────╫──X──X──X──╫──X─────╫──╫─┤M├────── ==> q_4: ─╫──╫──╫─────╫───────┤M├ │ │ ║ │ ║ │ ║ ║ └╥┘┌─┐ ║ ║ ║ ┌─┐ ║ └╥┘ q_5: ────X──X──X──X──╫──X──X─────╫──X──X──╫──╫──╫─┤M├─── q_5: ─╫──╫──╫─┤M├─╫────────╫─ │ │ ║ │ ║ │ ║ ║ ║ └╥┘┌─┐ ║ ║ ║ └╥┘ ║ ┌─┐ ║ q_6: ─X──X──X──X──X──╫──X──X─────╫─────X──╫──╫──╫──╫─┤M├ q_6: ─╫──╫──╫──╫──╫─┤M├────╫─ │ │ │ ║ │ ┌─┐ ║ ║ ║ ║ ║ └╥┘ ║ ║ ║ ║ ║ └╥┘┌─┐ ║ q_7: ─X──X─────X─────╫──X─┤M├────╫────────╫──╫──╫──╫──╫─ q_7: ─╫──╫──╫──╫──╫──╫─┤M├─╫─ ║ └╥┘ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ └╥┘ ║ c: 8/════════════════╩═════╩═════╩════════╩══╩══╩══╩══╩═ c: 8/═╩══╩══╩══╩══╩══╩══╩══╩═ 0 7 1 2 3 4 5 6 0 1 2 3 4 5 6 7 """ circuit = QuantumCircuit(8, 8) circuit.swap(3, 4) circuit.swap(6, 7) circuit.swap(0, 1) circuit.swap(6, 7) circuit.swap(4, 5) circuit.swap(0, 1) circuit.swap(5, 6) circuit.swap(3, 4) circuit.swap(1, 2) circuit.swap(6, 7) circuit.swap(4, 5) circuit.swap(2, 3) circuit.swap(0, 1) circuit.swap(5, 6) circuit.swap(1, 2) circuit.swap(6, 7) circuit.swap(4, 5) circuit.swap(2, 3) circuit.swap(3, 4) circuit.swap(3, 4) circuit.swap(5, 6) circuit.swap(1, 2) circuit.swap(4, 5) circuit.swap(2, 3) circuit.swap(5, 6) circuit.measure(range(8), range(8)) dag = circuit_to_dag(circuit) expected = QuantumCircuit(8, 8) expected.measure(0, 2) expected.measure(1, 1) expected.measure(2, 0) expected.measure(3, 4) expected.measure(4, 7) expected.measure(5, 3) expected.measure(6, 5) expected.measure(7, 6) pass_ = OptimizeSwapBeforeMeasure() after = pass_.run(dag) self.assertEqual(circuit_to_dag(expected), after)
def expected_dag(): q0 = QuantumRegister(2, "q0") qc = QuantumCircuit(q0) return circuit_to_dag(qc)
def test_overoptimization_case(self): """Check mapper overoptimization. The mapper should not change the semantics of the input. An overoptimization introduced issue #81: https://github.com/Qiskit/qiskit-terra/issues/81 """ coupling = CouplingMap([[0, 2], [1, 2], [2, 3]]) qr = QuantumRegister(4, 'q') cr = ClassicalRegister(4, 'c') circuit = QuantumCircuit(qr, cr) circuit.x(qr[0]) circuit.y(qr[1]) circuit.z(qr[2]) circuit.cx(qr[0], qr[1]) circuit.cx(qr[2], qr[3]) circuit.s(qr[1]) circuit.t(qr[2]) circuit.h(qr[3]) circuit.cx(qr[1], qr[2]) circuit.measure(qr[0], cr[0]) circuit.measure(qr[1], cr[1]) circuit.measure(qr[2], cr[2]) circuit.measure(qr[3], cr[3]) dag = circuit_to_dag(circuit) # ┌───┐ ┌─┐ # q_0: | 0 >┤ X ├────────────■───────────────────────────┤M├───────── # └───┘┌───┐ ┌─┴─┐ ┌───┐ └╥┘┌─┐ # q_1: | 0 >─────┤ Y ├─────┤ X ├─────┤ S ├────────────■───╫─┤M├────── # └───┘┌───┐└───┘ └───┘┌───┐ ┌─┴─┐ ║ └╥┘┌─┐ # q_2: | 0 >──────────┤ Z ├───────■───────┤ T ├─────┤ X ├─╫──╫─┤M├─── # └───┘ ┌─┴─┐ └───┘┌───┐└───┘ ║ ║ └╥┘┌─┐ # q_3: | 0 >────────────────────┤ X ├──────────┤ H ├──────╫──╫──╫─┤M├ # └───┘ └───┘ ║ ║ ║ └╥┘ # c_0: 0 ══════════════════════════════════════════════╩══╬══╬══╬═ # ║ ║ ║ # c_1: 0 ═════════════════════════════════════════════════╩══╬══╬═ # ║ ║ # c_2: 0 ════════════════════════════════════════════════════╩══╬═ # ║ # c_3: 0 ═══════════════════════════════════════════════════════╩═ # expected = QuantumCircuit(qr, cr) expected.z(qr[2]) expected.y(qr[1]) expected.x(qr[0]) expected.swap(qr[1], qr[2]) expected.cx(qr[0], qr[2]) expected.swap(qr[2], qr[3]) expected.cx(qr[1], qr[2]) expected.s(qr[3]) expected.t(qr[1]) expected.h(qr[2]) expected.measure(qr[0], cr[0]) expected.swap(qr[1], qr[2]) expected.cx(qr[3], qr[2]) expected.measure(qr[1], cr[3]) expected.measure(qr[3], cr[1]) expected.measure(qr[2], cr[2]) expected_dag = circuit_to_dag(expected) # ┌───┐ ┌─┐ # q_0: |0>─────────────┤ X ├──■──┤M├──────────────────────────────────────── # ┌───┐ └───┘ │ └╥┘ ┌───┐ ┌───┐┌─┐ # q_1: |0>─────┤ Y ├─X────────┼───╫───────────■──┤ T ├────────┤ X ├┤M├────── # ┌───┐└───┘ │ ┌─┴─┐ ║ ┌─┴─┐└───┘┌───┐ └─┬─┘└╥┘┌─┐ # q_2: |0>┤ Z ├──────X──────┤ X ├─╫──X──────┤ X ├─────┤ H ├─X───■───╫─┤M├─── # └───┘ └───┘ ║ │ ┌───┐└───┘ └───┘ │ ║ └╥┘┌─┐ # q_3: |0>────────────────────────╫──X─┤ S ├────────────────X───────╫──╫─┤M├ # ║ └───┘ ║ ║ └╥┘ # c_0: 0 ════════════════════════╩═════════════════════════════════╬══╬══╬═ # ║ ║ ║ # c_1: 0 ══════════════════════════════════════════════════════════╬══╩══╬═ # ║ ║ # c_2: 0 ══════════════════════════════════════════════════════════╩═════╬═ # ║ # c_3: 0 ════════════════════════════════════════════════════════════════╩═ # # Layout -- # {qr[0]: 0, # qr[1]: 1, # qr[2]: 2, # qr[3]: 3} pass_ = StochasticSwap(coupling, None, 20, 13) after = pass_.run(dag) self.assertEqual(expected_dag, after)
def expected_dag(): q0 = QuantumRegister(1, "q0") c0 = ClassicalRegister(2, "c0") qc = QuantumCircuit(q0, c0) qc.x(q0[0]).c_if(c0[0], 0) return circuit_to_dag(qc)
def test_unroll_all_instructions(self): """Test unrolling a circuit containing all standard instructions. """ qr = QuantumRegister(3, 'qr') cr = ClassicalRegister(3, 'cr') circuit = QuantumCircuit(qr, cr) circuit.crx(0.5, qr[1], qr[2]) circuit.cry(0.5, qr[1], qr[2]) circuit.ccx(qr[0], qr[1], qr[2]) circuit.ch(qr[0], qr[2]) circuit.crz(0.5, qr[1], qr[2]) circuit.cswap(qr[1], qr[0], qr[2]) circuit.cu1(0.1, qr[0], qr[2]) circuit.cu3(0.2, 0.1, 0.0, qr[1], qr[2]) circuit.cx(qr[1], qr[0]) circuit.cy(qr[1], qr[2]) circuit.cz(qr[2], qr[0]) circuit.h(qr[1]) circuit.i(qr[0]) circuit.rx(0.1, qr[0]) circuit.ry(0.2, qr[1]) circuit.rz(0.3, qr[2]) circuit.rzz(0.6, qr[1], qr[0]) circuit.s(qr[0]) circuit.sdg(qr[1]) circuit.swap(qr[1], qr[2]) circuit.t(qr[2]) circuit.tdg(qr[0]) circuit.u1(0.1, qr[1]) circuit.u2(0.2, -0.1, qr[0]) circuit.u3(0.3, 0.0, -0.1, qr[2]) circuit.x(qr[2]) circuit.y(qr[1]) circuit.z(qr[0]) # circuit.snapshot('0') # circuit.measure(qr, cr) dag = circuit_to_dag(circuit) pass_ = UnrollCustomDefinitions(std_eqlib, ['u3', 'cx', 'id']) dag = pass_.run(dag) pass_ = BasisTranslator(std_eqlib, ['u3', 'cx', 'id']) unrolled_dag = pass_.run(dag) ref_circuit = QuantumCircuit(qr, cr) ref_circuit.u3(0, 0, pi / 2, qr[2]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.u3(-0.25, 0, 0, qr[2]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.u3(0.25, -pi / 2, 0, qr[2]) ref_circuit.u3(0.25, 0, 0, qr[2]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.u3(-0.25, 0, 0, qr[2]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.u3(pi / 2, 0, pi, qr[2]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.u3(0, 0, -pi / 4, qr[2]) ref_circuit.cx(qr[0], qr[2]) ref_circuit.u3(0, 0, pi / 4, qr[2]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.u3(0, 0, pi / 4, qr[1]) ref_circuit.u3(0, 0, -pi / 4, qr[2]) ref_circuit.cx(qr[0], qr[2]) ref_circuit.cx(qr[0], qr[1]) ref_circuit.u3(0, 0, pi / 4, qr[0]) ref_circuit.u3(0, 0, -pi / 4, qr[1]) ref_circuit.cx(qr[0], qr[1]) ref_circuit.u3(0, 0, pi / 4, qr[2]) ref_circuit.u3(pi / 2, 0, pi, qr[2]) ref_circuit.u3(0, 0, pi / 2, qr[2]) ref_circuit.u3(pi / 2, 0, pi, qr[2]) ref_circuit.u3(0, 0, pi / 4, qr[2]) ref_circuit.cx(qr[0], qr[2]) ref_circuit.u3(0, 0, -pi / 4, qr[2]) ref_circuit.u3(pi / 2, 0, pi, qr[2]) ref_circuit.u3(0, 0, -pi / 2, qr[2]) ref_circuit.u3(0, 0, 0.25, qr[2]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.u3(0, 0, -0.25, qr[2]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.cx(qr[2], qr[0]) ref_circuit.u3(pi / 2, 0, pi, qr[2]) ref_circuit.cx(qr[0], qr[2]) ref_circuit.u3(0, 0, -pi / 4, qr[2]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.u3(0, 0, pi / 4, qr[2]) ref_circuit.cx(qr[0], qr[2]) ref_circuit.u3(0, 0, pi / 4, qr[0]) ref_circuit.u3(0, 0, -pi / 4, qr[2]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.cx(qr[1], qr[0]) ref_circuit.u3(0, 0, -pi / 4, qr[0]) ref_circuit.u3(0, 0, pi / 4, qr[1]) ref_circuit.cx(qr[1], qr[0]) ref_circuit.u3(0, 0, 0.05, qr[1]) ref_circuit.u3(0, 0, pi / 4, qr[2]) ref_circuit.u3(pi / 2, 0, pi, qr[2]) ref_circuit.cx(qr[2], qr[0]) ref_circuit.u3(0, 0, 0.05, qr[0]) ref_circuit.cx(qr[0], qr[2]) ref_circuit.u3(0, 0, -0.05, qr[2]) ref_circuit.cx(qr[0], qr[2]) ref_circuit.u3(0, 0, 0.05, qr[2]) ref_circuit.u3(0, 0, -0.05, qr[2]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.u3(-0.1, 0, -0.05, qr[2]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.cx(qr[1], qr[0]) ref_circuit.u3(pi / 2, 0, pi, qr[0]) ref_circuit.u3(0.1, 0.1, 0, qr[2]) ref_circuit.u3(0, 0, -pi / 2, qr[2]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.u3(pi / 2, 0, pi, qr[1]) ref_circuit.u3(0.2, 0, 0, qr[1]) ref_circuit.u3(0, 0, pi / 2, qr[2]) ref_circuit.cx(qr[2], qr[0]) ref_circuit.u3(pi / 2, 0, pi, qr[0]) ref_circuit.i(qr[0]) ref_circuit.u3(0.1, -pi / 2, pi / 2, qr[0]) ref_circuit.cx(qr[1], qr[0]) ref_circuit.u3(0, 0, 0.6, qr[0]) ref_circuit.cx(qr[1], qr[0]) ref_circuit.u3(0, 0, pi / 2, qr[0]) ref_circuit.u3(0, 0, -pi / 4, qr[0]) ref_circuit.u3(pi / 2, 0.2, -0.1, qr[0]) ref_circuit.u3(0, 0, pi, qr[0]) ref_circuit.u3(0, 0, -pi / 2, qr[1]) ref_circuit.u3(0, 0, 0.3, qr[2]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.cx(qr[2], qr[1]) ref_circuit.cx(qr[1], qr[2]) ref_circuit.u3(0, 0, 0.1, qr[1]) ref_circuit.u3(pi, pi / 2, pi / 2, qr[1]) ref_circuit.u3(0, 0, pi / 4, qr[2]) ref_circuit.u3(0.3, 0.0, -0.1, qr[2]) ref_circuit.u3(pi, 0, pi, qr[2]) # ref_circuit.snapshot('0') # ref_circuit.measure(qr, cr) # ref_dag = circuit_to_dag(ref_circuit) self.assertTrue( Operator(dag_to_circuit(unrolled_dag)).equiv(ref_circuit))
def test_targetsuccessive_identity_advanced_removal(self): """ Should remove target successive identity gates with DIFFERENT sets of control qubits. In this case CCCX(4,5,6,7) & CCX(5,6,7). """ circuit = QuantumCircuit(8) circuit.h(0) circuit.h(1) circuit.h(2) circuit.h(3) circuit.h(4) circuit.h(5) for i in range(3): circuit.cx(i * 2 + 1, i * 2) circuit.cx(3, 5) for i in range(2): circuit.ccx(i * 2, i * 2 + 1, i * 2 + 3) circuit.cx(i * 2 + 3, i * 2 + 2) circuit.ccx(4, 5, 6) for i in range(1, -1, -1): circuit.ccx(i * 2, i * 2 + 1, i * 2 + 3) circuit.cx(3, 5) circuit.cx(5, 6) circuit.cx(3, 5) circuit.x(6) for i in range(2): circuit.ccx(i * 2, i * 2 + 1, i * 2 + 3) for i in range(1, -1, -1): circuit.cx(i * 2 + 3, i * 2 + 2) circuit.ccx(i * 2, i * 2 + 1, i * 2 + 3) circuit.cx(1, 0) circuit.ccx(6, 1, 0) circuit.ccx(0, 1, 3) circuit.ccx(6, 3, 2) circuit.ccx(2, 3, 5) circuit.ccx(6, 5, 4) circuit.append(XGate().control(3), [4, 5, 6, 7], []) for i in range(1, -1, -1): circuit.ccx(i * 2, i * 2 + 1, i * 2 + 3) circuit.cx(3, 5) for i in range(1, 3): circuit.cx(i * 2 + 1, i * 2) circuit.ccx(5, 6, 7) expected = QuantumCircuit(8) expected.h(0) expected.h(1) expected.h(2) expected.h(3) expected.h(4) expected.h(5) for i in range(3): expected.cx(i * 2 + 1, i * 2) expected.cx(3, 5) for i in range(2): expected.ccx(i * 2, i * 2 + 1, i * 2 + 3) expected.cx(i * 2 + 3, i * 2 + 2) expected.ccx(4, 5, 6) for i in range(1, -1, -1): expected.ccx(i * 2, i * 2 + 1, i * 2 + 3) expected.cx(3, 5) expected.cx(5, 6) expected.cx(3, 5) expected.x(6) for i in range(2): expected.ccx(i * 2, i * 2 + 1, i * 2 + 3) for i in range(1, -1, -1): expected.cx(i * 2 + 3, i * 2 + 2) expected.ccx(i * 2, i * 2 + 1, i * 2 + 3) expected.cx(1, 0) expected.ccx(6, 1, 0) expected.ccx(0, 1, 3) expected.ccx(6, 3, 2) expected.ccx(2, 3, 5) expected.ccx(6, 5, 4) for i in range(1, -1, -1): expected.ccx(i * 2, i * 2 + 1, i * 2 + 3) expected.cx(3, 5) for i in range(1, 3): expected.cx(i * 2 + 1, i * 2) stv = Statevector.from_label('0' * circuit.num_qubits) self.assertEqual(stv @ circuit, stv @ expected) pass_ = HoareOptimizer(size=5) result = pass_.run(circuit_to_dag(circuit)) self.assertEqual(result, circuit_to_dag(expected))
coupling = CouplingMap([[0, 1], [1, 2], [1, 3]]) qr = QuantumRegister(4, 'q') cr = ClassicalRegister(4, 'c') circ = QuantumCircuit(qr, cr) circ.cx(qr[1], qr[2]) circ.cx(qr[0], qr[3]) circ.measure(qr[0], cr[0]) circ.h(qr) circ.cx(qr[0], qr[1]) circ.cx(qr[2], qr[3]) circ.measure(qr[0], cr[0]) circ.measure(qr[1], cr[1]) circ.measure(qr[2], cr[2]) circ.measure(qr[3], cr[3]) dag = circuit_to_dag(circ) # ┌─┐┌───┐ ┌─┐ # q_0: |0>─────────────────■──────────────────┤M├┤ H ├──■─────┤M├ # ┌───┐ │ └╥┘└───┘┌─┴─┐┌─┐└╥┘ # q_1: |0>──■───────┤ H ├──┼───────────────────╫──────┤ X ├┤M├─╫─ # ┌─┴─┐┌───┐└───┘ │ ┌─┐ ║ └───┘└╥┘ ║ # q_2: |0>┤ X ├┤ H ├───────┼─────────■─────┤M├─╫────────────╫──╫─ # └───┘└───┘ ┌─┴─┐┌───┐┌─┴─┐┌─┐└╥┘ ║ ║ ║ # q_3: |0>───────────────┤ X ├┤ H ├┤ X ├┤M├─╫──╫────────────╫──╫─ # └───┘└───┘└───┘└╥┘ ║ ║ ║ ║ # c_0: 0 ═══════════════════════════════╬══╬══╩════════════╬══╩═ # ║ ║ ║ # c_1: 0 ═══════════════════════════════╬══╬═══════════════╩════ # ║ ║ # c_2: 0 ═══════════════════════════════╬══╩════════════════════ # ║
def test_cswap_removal(self): """ Should remove Fredkin gates because the optimizer can deduce the targets are in the same state """ circuit = QuantumCircuit(10) # prep circuit.x(0) circuit.h(3) circuit.h(4) circuit.h(5) circuit.h(6) # find first non-zero bit of reg(3-6), store position in reg(1-2) circuit.cx(3, 0) circuit.ccx(0, 4, 1) circuit.cx(1, 0) circuit.ccx(0, 5, 2) circuit.cx(2, 0) circuit.ccx(0, 6, 1) circuit.ccx(0, 6, 2) circuit.ccx(1, 2, 0) # shift circuit circuit.cswap(1, 7, 8) circuit.cswap(1, 8, 9) circuit.cswap(1, 9, 3) circuit.cswap(1, 3, 4) circuit.cswap(1, 4, 5) circuit.cswap(1, 5, 6) circuit.cswap(2, 7, 9) circuit.cswap(2, 8, 3) circuit.cswap(2, 9, 4) circuit.cswap(2, 3, 5) circuit.cswap(2, 4, 6) expected = QuantumCircuit(10) # prep expected.x(0) expected.h(3) expected.h(4) expected.h(5) expected.h(6) # find first non-zero bit of reg(3-6), store position in reg(1-2) expected.cx(3, 0) expected.ccx(0, 4, 1) expected.cx(1, 0) expected.ccx(0, 5, 2) expected.cx(2, 0) expected.ccx(0, 6, 1) expected.ccx(0, 6, 2) expected.ccx(1, 2, 0) # optimized shift circuit expected.cswap(1, 3, 4) expected.cswap(1, 4, 5) expected.cswap(1, 5, 6) expected.cswap(2, 3, 5) expected.cswap(2, 4, 6) stv = Statevector.from_label('0' * circuit.num_qubits) self.assertEqual(stv @ circuit, stv @ expected) pass_ = HoareOptimizer(size=0) result = pass_.run(circuit_to_dag(circuit)) self.assertEqual(result, circuit_to_dag(expected))
def __eq__(self, other): # TODO: remove the DAG from this function from qiskit.converters import circuit_to_dag return circuit_to_dag(self) == circuit_to_dag(other)
def get_controlled_circuit(circuit, ctl_qubit, tgt_circuit=None, use_basis_gates=True): """ Construct the controlled version of a given circuit. Args: circuit (QuantumCircuit) : the base circuit ctl_qubit (Qubit) : the control qubit to use tgt_circuit (QuantumCircuit) : the target controlled circuit to be modified in-place use_basis_gates (bool) : boolean flag to indicate whether or not only basis gates should be used Return: QuantumCircuit: a QuantumCircuit object with the base circuit being controlled by ctl_qubit Raises: RuntimeError: unexpected operation """ if tgt_circuit is not None: qc = tgt_circuit else: qc = QuantumCircuit() # get all the qubits and clbits qregs = circuit.qregs qubits = [] for qreg in qregs: if not qc.has_register(qreg): qc.add_register(qreg) qubits.extend(qreg) cregs = circuit.cregs clbits = [] for creg in cregs: if not qc.has_register(creg): qc.add_register(creg) clbits.extend(creg) # get all operations unroller = Unroller(basis=['u1', 'u2', 'u3', 'cx']) ops = dag_to_circuit(unroller.run(circuit_to_dag(circuit))).data # process all basis gates to add control if not qc.has_register(ctl_qubit.register): qc.add_register(ctl_qubit.register) for op in ops: if op[0].name == 'id': apply_cu3(qc, 0, 0, 0, ctl_qubit, op[1][0], use_basis_gates=use_basis_gates) elif op[0].name == 'u1': apply_cu1(qc, *op[0].params, ctl_qubit, op[1][0], use_basis_gates=use_basis_gates) elif op[0].name == 'u2': apply_cu3(qc, np.pi / 2, *op[0].params, ctl_qubit, op[1][0], use_basis_gates=use_basis_gates) elif op[0].name == 'u3': apply_cu3(qc, *op[0].params, ctl_qubit, op[1][0], use_basis_gates=use_basis_gates) elif op[0].name == 'cx': apply_ccx(qc, ctl_qubit, *op[1], use_basis_gates=use_basis_gates) elif op[0].name == 'measure': qc.measure(op[1], op[2]) elif op[0].name == 'barrier': qc.barrier(op[1]) else: raise RuntimeError('Unexpected operation {}.'.format(op[0].name)) return qc
def _compose_transforms(basis_transforms, source_basis, source_dag): """Compose a set of basis transforms into a set of replacements. Args: basis_transforms (List[Tuple[gate_name, params, equiv]]): List of transforms to compose. source_basis (Set[Tuple[gate_name: str, gate_num_qubits: int]]): Names of gates which need to be translated. source_dag (DAGCircuit): DAG with example gates from source_basis. (Used to determine num_params for gate in source_basis.) Returns: Dict[gate_name, Tuple(params, dag)]: Dictionary mapping between each gate in source_basis and a DAGCircuit instance to replace it. Gates in source_basis but not affected by basis_transforms will be included as a key mapping to itself. """ example_gates = {(node.op.name, node.op.num_qubits): node.op for node in source_dag.op_nodes()} mapped_instrs = {} for gate_name, gate_num_qubits in source_basis: # Need to grab a gate instance to find num_qubits and num_params. # Can be removed following https://github.com/Qiskit/qiskit-terra/pull/3947 . example_gate = example_gates[gate_name, gate_num_qubits] num_params = len(example_gate.params) placeholder_params = ParameterVector(gate_name, num_params) placeholder_gate = Gate(gate_name, gate_num_qubits, list(placeholder_params)) placeholder_gate.params = list(placeholder_params) dag = DAGCircuit() qr = QuantumRegister(gate_num_qubits) dag.add_qreg(qr) dag.apply_operation_back(placeholder_gate, qr[:], []) mapped_instrs[gate_name, gate_num_qubits] = placeholder_params, dag for gate_name, gate_num_qubits, equiv_params, equiv in basis_transforms: logger.debug('Composing transform step: %s/%s %s =>\n%s', gate_name, gate_num_qubits, equiv_params, equiv) for mapped_instr_name, (dag_params, dag) in mapped_instrs.items(): doomed_nodes = [ node for node in dag.op_nodes() if (node.op.name, node.op.num_qubits) == (gate_name, gate_num_qubits) ] if doomed_nodes and logger.isEnabledFor(logging.DEBUG): from qiskit.converters import dag_to_circuit logger.debug( 'Updating transform for mapped instr %s %s from \n%s', mapped_instr_name, dag_params, dag_to_circuit(dag)) for node in doomed_nodes: from qiskit.converters import circuit_to_dag replacement = equiv.assign_parameters( dict(zip_longest(equiv_params, node.op.params))) replacement_dag = circuit_to_dag(replacement) dag.substitute_node_with_dag(node, replacement_dag) if doomed_nodes and logger.isEnabledFor(logging.DEBUG): from qiskit.converters import dag_to_circuit logger.debug('Updated transform for mapped instr %s %s to\n%s', mapped_instr_name, dag_params, dag_to_circuit(dag)) return mapped_instrs
for item in filename_list: path = os.path.join(basedir, item) file = os.path.splitext(item) filename, typen = file if typen == '.qasm': parentPath = '../../mapped_qasm/' parentPath = parentPath + filename + typen print(parentPath) ghz = QuantumCircuit.from_qasm_file(parentPath) # device = IBMQ.get_backend('ibmq_16_melbourne') # trans_ghz = transpile(ghz, device) dag = circuit_to_dag(ghz) # dag_drawer(dag, scale=0.7, filename='../pic/alu-v2_31.png') dag_id_depth = {} idDict = {} # _node_id to dag_id(starting from 0) idDict2 = {} # _dag_id to inDegreeList_id(starting from 0) groupResult = [] groupQargs = {} dagList = []
def test_qobj_to_circuits_single_no_qasm(self): """Check that qobj_to_circuits's result matches the qobj ini.""" qobj_in = assemble(self.circuit) out_circuit = qobj_to_circuits(qobj_in) self.assertEqual(circuit_to_dag(out_circuit[0]), self.dag)
def _synth_natural_direction( self, su4_mat, coupling_map, qubits, decomposer2q, gate_lengths, gate_errors, natural_direction, approximation_degree, pulse_optimize, ): preferred_direction = None synth_direction = None physical_gate_fidelity = None wires = None if natural_direction in {None, True} and coupling_map: neighbors0 = coupling_map.neighbors(qubits[0]) zero_one = qubits[1] in neighbors0 neighbors1 = coupling_map.neighbors(qubits[1]) one_zero = qubits[0] in neighbors1 if zero_one and not one_zero: preferred_direction = [0, 1] if one_zero and not zero_one: preferred_direction = [1, 0] if (natural_direction in {None, True} and preferred_direction is None and gate_lengths and gate_errors): len_0_1 = inf len_1_0 = inf twoq_gate_lengths = gate_lengths.get(decomposer2q.gate.name) if twoq_gate_lengths: len_0_1 = twoq_gate_lengths.get((qubits[0], qubits[1]), inf) len_1_0 = twoq_gate_lengths.get((qubits[1], qubits[0]), inf) if len_0_1 < len_1_0: preferred_direction = [0, 1] elif len_1_0 < len_0_1: preferred_direction = [1, 0] if preferred_direction: twoq_gate_errors = gate_errors.get("cx") gate_error = twoq_gate_errors.get( (qubits[preferred_direction[0]], qubits[preferred_direction[1]])) if gate_error: physical_gate_fidelity = 1 - gate_error if natural_direction is True and preferred_direction is None: raise TranspilerError( f"No preferred direction of gate on qubits {qubits} " "could be determined from coupling map or " "gate lengths.") if approximation_degree is not None: basis_fidelity = approximation_degree else: basis_fidelity = physical_gate_fidelity synth_circ = decomposer2q(su4_mat, basis_fidelity=basis_fidelity) synth_dag = circuit_to_dag(synth_circ) # if a natural direction exists but the synthesis is in the opposite direction, # resynthesize a new operator which is the original conjugated by swaps. # this new operator is doubly mirrored from the original and is locally equivalent. synth_dag_qubit_index = { qubit: index for index, qubit in enumerate(synth_dag.qubits) } if synth_dag.two_qubit_ops(): synth_direction = [ synth_dag_qubit_index[qubit] for qubit in synth_dag.two_qubit_ops()[0].qargs ] if (preferred_direction and pulse_optimize in {True, None} and synth_direction != preferred_direction): su4_mat_mm = deepcopy(su4_mat) su4_mat_mm[[1, 2]] = su4_mat_mm[[2, 1]] su4_mat_mm[:, [1, 2]] = su4_mat_mm[:, [2, 1]] synth_dag = circuit_to_dag( decomposer2q(su4_mat_mm, basis_fidelity=basis_fidelity)) wires = synth_dag.wires[::-1] return synth_dag, wires