def dag_to_circuit(dag): """Build a ``QuantumCircuit`` object from a ``DAGCircuit``. Args: dag (DAGCircuit): the input dag. Return: QuantumCircuit: the circuit representing the input dag. Example: .. jupyter-execute:: from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit from qiskit.dagcircuit import DAGCircuit from qiskit.converters import circuit_to_dag from qiskit.circuit.library.standard_gates import CHGate, U2Gate, CXGate from qiskit.converters import dag_to_circuit %matplotlib inline q = QuantumRegister(3, 'q') c = ClassicalRegister(3, 'c') circ = QuantumCircuit(q, c) circ.h(q[0]) circ.cx(q[0], q[1]) circ.measure(q[0], c[0]) circ.rz(0.5, q[1]).c_if(c, 2) dag = circuit_to_dag(circ) circuit = dag_to_circuit(dag) circuit.draw() """ name = dag.name or None circuit = QuantumCircuit( dag.qubits, dag.clbits, *dag.qregs.values(), *dag.cregs.values(), name=name, global_phase=dag.global_phase, ) circuit.metadata = dag.metadata circuit.calibrations = dag.calibrations for node in dag.topological_op_nodes(): # Get arguments for classical control (if any) inst = node.op.copy() circuit._append(inst, node.qargs, node.cargs) circuit.duration = dag.duration circuit.unit = dag.unit return circuit
def _experiments_to_circuits(qobj): """Return a list of QuantumCircuit object(s) from a qobj. Args: qobj (Qobj): The Qobj object to convert to QuantumCircuits Returns: list: A list of QuantumCircuit objects from the qobj """ if not qobj.experiments: return None circuits = [] for exp in qobj.experiments: quantum_registers = [QuantumRegister(i[1], name=i[0]) for i in exp.header.qreg_sizes] classical_registers = [ClassicalRegister(i[1], name=i[0]) for i in exp.header.creg_sizes] circuit = QuantumCircuit(*quantum_registers, *classical_registers, name=exp.header.name) qreg_dict = collections.OrderedDict() creg_dict = collections.OrderedDict() for reg in quantum_registers: qreg_dict[reg.name] = reg for reg in classical_registers: creg_dict[reg.name] = reg conditional = {} for i in exp.instructions: name = i.name qubits = [] params = getattr(i, "params", []) try: for qubit in i.qubits: qubit_label = exp.header.qubit_labels[qubit] qubits.append(qreg_dict[qubit_label[0]][qubit_label[1]]) except Exception: # pylint: disable=broad-except pass clbits = [] try: for clbit in i.memory: clbit_label = exp.header.clbit_labels[clbit] clbits.append(creg_dict[clbit_label[0]][clbit_label[1]]) except Exception: # pylint: disable=broad-except pass if hasattr(circuit, name): instr_method = getattr(circuit, name) if i.name in ["snapshot"]: _inst = instr_method( i.label, snapshot_type=i.snapshot_type, qubits=qubits, params=params ) elif i.name == "initialize": _inst = instr_method(params, qubits) elif i.name == "isometry": _inst = instr_method(*params, qubits, clbits) elif i.name in ["mcx", "mcu1", "mcp"]: _inst = instr_method(*params, qubits[:-1], qubits[-1], *clbits) else: _inst = instr_method(*params, *qubits, *clbits) elif name == "bfunc": conditional["value"] = int(i.val, 16) full_bit_size = sum(creg_dict[x].size for x in creg_dict) mask_map = {} raw_map = {} raw = [] for creg in creg_dict: size = creg_dict[creg].size reg_raw = [1] * size if not raw: raw = reg_raw else: for pos, val in enumerate(raw): if val == 1: raw[pos] = 0 raw = reg_raw + raw mask = [0] * (full_bit_size - len(raw)) + raw raw_map[creg] = mask mask_map[int("".join(str(x) for x in mask), 2)] = creg creg = mask_map[int(i.mask, 16)] conditional["register"] = creg_dict[creg] val = int(i.val, 16) mask = raw_map[creg] for j in reversed(mask): if j == 0: val = val >> 1 else: conditional["value"] = val break else: _inst = temp_opaque_instruction = Instruction( name=name, num_qubits=len(qubits), num_clbits=len(clbits), params=params ) circuit.append(temp_opaque_instruction, qubits, clbits) if conditional and name != "bfunc": _inst.c_if(conditional["register"], conditional["value"]) conditional = {} pulse_lib = qobj.config.pulse_library if hasattr(qobj.config, "pulse_library") else [] parametric_pulses = ( qobj.config.parametric_pulses if hasattr(qobj.config, "parametric_pulses") else [] ) # The dict update method did not work here; could investigate in the future if hasattr(qobj.config, "calibrations"): circuit.calibrations = dict( **circuit.calibrations, **_qobj_to_circuit_cals(qobj, pulse_lib, parametric_pulses) ) if hasattr(exp.config, "calibrations"): circuit.calibrations = dict( **circuit.calibrations, **_qobj_to_circuit_cals(exp, pulse_lib, parametric_pulses) ) circuits.append(circuit) return circuits
def read_circuit(file_obj, version, metadata_deserializer=None): """Read a single QuantumCircuit object from the file like object. Args: file_obj (FILE): The file like object to read the circuit data from. version (int): QPY version. metadata_deserializer (JSONDecoder): An optional JSONDecoder class that will be used for the ``cls`` kwarg on the internal ``json.load`` call used to deserialize the JSON payload used for the :attr:`.QuantumCircuit.metadata` attribute for a circuit in the file-like object. If this is not specified the circuit metadata will be parsed as JSON with the stdlib ``json.load()`` function using the default ``JSONDecoder`` class. Returns: QuantumCircuit: The circuit object from the file. Raises: QpyError: Invalid register. """ vectors = {} if version < 2: header, name, metadata = _read_header( file_obj, metadata_deserializer=metadata_deserializer) else: header, name, metadata = _read_header_v2( file_obj, version, vectors, metadata_deserializer=metadata_deserializer) global_phase = header["global_phase"] num_qubits = header["num_qubits"] num_clbits = header["num_clbits"] num_registers = header["num_registers"] num_instructions = header["num_instructions"] out_registers = {"q": {}, "c": {}} if num_registers > 0: circ = QuantumCircuit(name=name, global_phase=global_phase, metadata=metadata) if version < 4: registers = _read_registers(file_obj, num_registers) else: registers = _read_registers_v4(file_obj, num_registers) for bit_type_label, bit_type, reg_type in [ ("q", Qubit, QuantumRegister), ("c", Clbit, ClassicalRegister), ]: register_bits = set() # Add quantum registers and bits for register_name in registers[bit_type_label]: standalone, indices, in_circuit = registers[bit_type_label][ register_name] indices_defined = [x for x in indices if x >= 0] # If a register has no bits in the circuit skip it if not indices_defined: continue if standalone: start = min(indices_defined) count = start out_of_order = False for index in indices: if index < 0: out_of_order = True continue if not out_of_order and index != count: out_of_order = True count += 1 if index in register_bits: # If we have a bit in the position already it's been # added by an earlier register in the circuit # otherwise it's invalid qpy if not in_circuit: continue raise exceptions.QpyError( "Duplicate register bits found") register_bits.add(index) num_reg_bits = len(indices) # Create a standlone register of the appropriate length (from # the number of indices in the qpy data) and add it to the circuit reg = reg_type(num_reg_bits, register_name) # If any bits from qreg are out of order in the circuit handle # is case if out_of_order or not in_circuit: for index, pos in sorted(enumerate(x for x in indices if x >= 0), key=lambda x: x[1]): if bit_type_label == "q": bit_len = len(circ.qubits) else: bit_len = len(circ.clbits) if pos < bit_len: # If we have a bit in the position already it's been # added by an earlier register in the circuit # otherwise it's invalid qpy if not in_circuit: continue raise exceptions.QpyError( "Duplicate register bits found") # Fill any holes between the current register bit and the # next one if pos > bit_len: bits = [ bit_type() for _ in range(pos - bit_len) ] circ.add_bits(bits) circ.add_bits([reg[index]]) if in_circuit: circ.add_register(reg) else: if bit_type_label == "q": bit_len = len(circ.qubits) else: bit_len = len(circ.clbits) # If there is a hole between the start of the register and the # current bits and standalone bits to fill the gap. if start > len(circ.qubits): bits = [bit_type() for _ in range(start - bit_len)] circ.add_bits(bit_len) if in_circuit: circ.add_register(reg) out_registers[bit_type_label][register_name] = reg else: for index in indices: if bit_type_label == "q": bit_len = len(circ.qubits) else: bit_len = len(circ.clbits) # Add any missing bits bits = [bit_type() for _ in range(index + 1 - bit_len)] circ.add_bits(bits) if index in register_bits: raise exceptions.QpyError( "Duplicate register bits found") register_bits.add(index) if bit_type_label == "q": bits = [circ.qubits[i] for i in indices] else: bits = [circ.clbits[i] for i in indices] reg = reg_type(name=register_name, bits=bits) if in_circuit: circ.add_register(reg) out_registers[bit_type_label][register_name] = reg # If we don't have sufficient bits in the circuit after adding # all the registers add more bits to fill the circuit if len(circ.qubits) < num_qubits: qubits = [Qubit() for _ in range(num_qubits - len(circ.qubits))] circ.add_bits(qubits) if len(circ.clbits) < num_clbits: clbits = [Clbit() for _ in range(num_qubits - len(circ.clbits))] circ.add_bits(clbits) else: circ = QuantumCircuit( num_qubits, num_clbits, name=name, global_phase=global_phase, metadata=metadata, ) custom_operations = _read_custom_operations(file_obj, version, vectors) for _instruction in range(num_instructions): _read_instruction(file_obj, circ, out_registers, custom_operations, version, vectors) # Read calibrations if version >= 5: circ.calibrations = _read_calibrations(file_obj, version, vectors, metadata_deserializer) for vec_name, (vector, initialized_params) in vectors.items(): if len(initialized_params) != len(vector): warnings.warn( f"The ParameterVector: '{vec_name}' is not fully identical to its " "pre-serialization state. Elements " f"{', '.join([str(x) for x in set(range(len(vector))) - initialized_params])} " "in the ParameterVector will be not equal to the pre-serialized ParameterVector " f"as they weren't used in the circuit: {circ.name}", UserWarning, ) return circ