def circuits_to_qobj(circuits, user_qobj_header=None, run_config=None, qobj_id=None, backend_name=None, config=None, shots=None, max_credits=None, basis_gates=None, coupling_map=None, seed=None, memory=None): """Convert a list of circuits into a qobj. Args: circuits (list[QuantumCircuits] or QuantumCircuit): circuits to compile user_qobj_header (QobjHeader): header to pass to the results run_config (RunConfig): RunConfig object qobj_id (int): identifier for the generated qobj backend_name (str): TODO: delete after qiskit-terra 0.8 config (dict): TODO: delete after qiskit-terra 0.8 shots (int): TODO: delete after qiskit-terra 0.8 max_credits (int): TODO: delete after qiskit-terra 0.8 basis_gates (str): TODO: delete after qiskit-terra 0.8 coupling_map (list): TODO: delete after qiskit-terra 0.8 seed (int): TODO: delete after qiskit-terra 0.8 memory (bool): TODO: delete after qiskit-terra 0.8 Returns: Qobj: the Qobj to be run on the backends """ user_qobj_header = user_qobj_header or QobjHeader() run_config = run_config or RunConfig() if isinstance(circuits, QuantumCircuit): circuits = [circuits] if backend_name: warnings.warn('backend_name is not required anymore', DeprecationWarning) user_qobj_header.backend_name = backend_name if config: warnings.warn( 'config is not used anymore. Set all configs in ' 'run_config.', DeprecationWarning) if shots: warnings.warn('shots is not used anymore. Set it via run_config.', DeprecationWarning) run_config.shots = shots if basis_gates: warnings.warn('basis_gates was unused and will be removed.', DeprecationWarning) if coupling_map: warnings.warn('coupling_map was unused and will be removed.', DeprecationWarning) if seed: warnings.warn('seed is not used anymore. Set it via run_config', DeprecationWarning) run_config.seed = seed if memory: warnings.warn('memory is not used anymore. Set it via run_config', DeprecationWarning) run_config.memory = memory if max_credits: warnings.warn('max_credits is not used anymore. Set it via run_config', DeprecationWarning) run_config.max_credits = max_credits userconfig = QobjConfig(**run_config.to_dict()) experiments = [] max_n_qubits = 0 max_memory_slots = 0 for circuit in circuits: # header stuff n_qubits = 0 memory_slots = 0 qubit_labels = [] clbit_labels = [] qreg_sizes = [] creg_sizes = [] for qreg in circuit.qregs: qreg_sizes.append([qreg.name, qreg.size]) for j in range(qreg.size): qubit_labels.append([qreg.name, j]) n_qubits += qreg.size for creg in circuit.cregs: creg_sizes.append([creg.name, creg.size]) for j in range(creg.size): clbit_labels.append([creg.name, j]) memory_slots += creg.size # TODO: why do we need creq_sizes and qreg_sizes in header # TODO: we need to rethink memory_slots as they are tied to classical bit # TODO: when no more backends use the compiled_circuit_qasm lets delete it form header experimentheader = QobjExperimentHeader( qubit_labels=qubit_labels, n_qubits=n_qubits, qreg_sizes=qreg_sizes, clbit_labels=clbit_labels, memory_slots=memory_slots, creg_sizes=creg_sizes, name=circuit.name, compiled_circuit_qasm=circuit.qasm()) # TODO: why do we need n_qubits and memory_slots in both the header and the config experimentconfig = QobjExperimentConfig(n_qubits=n_qubits, memory_slots=memory_slots) instructions = [] for opt in circuit.data: current_instruction = QobjInstruction(name=opt.name) if opt.qargs: qubit_indices = [ qubit_labels.index([qubit[0].name, qubit[1]]) for qubit in opt.qargs ] current_instruction.qubits = qubit_indices if opt.cargs: clbit_indices = [ clbit_labels.index([clbit[0].name, clbit[1]]) for clbit in opt.cargs ] current_instruction.memory = clbit_indices if opt.params: params = list(map(lambda x: x.evalf(), opt.params)) current_instruction.params = params # TODO: I really dont like this for snapshot. I also think we should change # type to snap_type if opt.name == "snapshot": current_instruction.label = str(opt.params[0]) current_instruction.type = str(opt.params[1]) if opt.control: mask = 0 for clbit in clbit_labels: if clbit[0] == opt.control[0].name: mask |= (1 << clbit_labels.index(clbit)) current_instruction.conditional = QobjConditional( mask="0x%X" % mask, type='equals', val="0x%X" % opt.control[1]) instructions.append(current_instruction) experiments.append( QobjExperiment(instructions=instructions, header=experimentheader, config=experimentconfig)) if n_qubits > max_n_qubits: max_n_qubits = n_qubits if memory_slots > max_memory_slots: max_memory_slots = memory_slots userconfig.memory_slots = max_memory_slots userconfig.n_qubits = max_n_qubits return Qobj(qobj_id=qobj_id or str(uuid.uuid4()), config=userconfig, experiments=experiments, header=user_qobj_header)
def assemble_circuits(circuits, run_config=None, qobj_header=None, qobj_id=None): """Assembles a list of circuits into a qobj which can be run on the backend. Args: circuits (list[QuantumCircuits] or QuantumCircuit): circuits to assemble run_config (RunConfig): RunConfig object qobj_header (QobjHeader): header to pass to the results qobj_id (int): identifier for the generated qobj Returns: Qobj: the Qobj to be run on the backends """ qobj_header = qobj_header or QobjHeader() run_config = run_config or RunConfig() if isinstance(circuits, QuantumCircuit): circuits = [circuits] userconfig = QobjConfig(**run_config.to_dict()) experiments = [] max_n_qubits = 0 max_memory_slots = 0 for circuit in circuits: # header stuff n_qubits = 0 memory_slots = 0 qubit_labels = [] clbit_labels = [] qreg_sizes = [] creg_sizes = [] for qreg in circuit.qregs: qreg_sizes.append([qreg.name, qreg.size]) for j in range(qreg.size): qubit_labels.append([qreg.name, j]) n_qubits += qreg.size for creg in circuit.cregs: creg_sizes.append([creg.name, creg.size]) for j in range(creg.size): clbit_labels.append([creg.name, j]) memory_slots += creg.size # TODO: why do we need creq_sizes and qreg_sizes in header # TODO: we need to rethink memory_slots as they are tied to classical bit experimentheader = QobjExperimentHeader(qubit_labels=qubit_labels, n_qubits=n_qubits, qreg_sizes=qreg_sizes, clbit_labels=clbit_labels, memory_slots=memory_slots, creg_sizes=creg_sizes, name=circuit.name) # TODO: why do we need n_qubits and memory_slots in both the header and the config experimentconfig = QobjExperimentConfig(n_qubits=n_qubits, memory_slots=memory_slots) instructions = [] for opt in circuit.data: current_instruction = QobjInstruction(name=opt.name) if opt.qargs: qubit_indices = [ qubit_labels.index([qubit[0].name, qubit[1]]) for qubit in opt.qargs ] current_instruction.qubits = qubit_indices if opt.cargs: clbit_indices = [ clbit_labels.index([clbit[0].name, clbit[1]]) for clbit in opt.cargs ] current_instruction.memory = clbit_indices if opt.params: params = list(map(lambda x: x.evalf(), opt.params)) params = [ sympy.matrix2numpy(x, dtype=complex) if isinstance( x, sympy.Matrix) else x for x in params ] if len(params) == 1 and isinstance(params[0], numpy.ndarray): # TODO: Aer expects list of rows for unitary instruction params; # change to matrix in Aer. params = params[0] current_instruction.params = params # TODO (jay): I really dont like this for snapshot. I also think we should change # type to snap_type if opt.name == "snapshot": current_instruction.label = str(opt.params[0]) current_instruction.type = str(opt.params[1]) if opt.control: mask = 0 for clbit in clbit_labels: if clbit[0] == opt.control[0].name: mask |= (1 << clbit_labels.index(clbit)) current_instruction.conditional = QobjConditional( mask="0x%X" % mask, type='equals', val="0x%X" % opt.control[1]) instructions.append(current_instruction) experiments.append( QobjExperiment(instructions=instructions, header=experimentheader, config=experimentconfig)) if n_qubits > max_n_qubits: max_n_qubits = n_qubits if memory_slots > max_memory_slots: max_memory_slots = memory_slots userconfig.memory_slots = max_memory_slots userconfig.n_qubits = max_n_qubits return Qobj(qobj_id=qobj_id or str(uuid.uuid4()), config=userconfig, experiments=experiments, header=qobj_header, type=QobjType.QASM.value)