def write_circuit(file_obj, circuit, metadata_serializer=None): """Write a single QuantumCircuit object in the file like object. Args: file_obj (FILE): The file like object to write the circuit data in. circuit (QuantumCircuit): The circuit data to write. metadata_serializer (JSONEncoder): An optional JSONEncoder class that will be passed the :attr:`.QuantumCircuit.metadata` dictionary for each circuit in ``circuits`` and will be used as the ``cls`` kwarg on the ``json.dump()`` call to JSON serialize that dictionary. """ metadata_raw = json.dumps( circuit.metadata, separators=(",", ":"), cls=metadata_serializer ).encode(common.ENCODE) metadata_size = len(metadata_raw) num_instructions = len(circuit) circuit_name = circuit.name.encode(common.ENCODE) global_phase_type, global_phase_data = value.dumps_value(circuit.global_phase) with io.BytesIO() as reg_buf: num_qregs = _write_registers(reg_buf, circuit.qregs, circuit.qubits) num_cregs = _write_registers(reg_buf, circuit.cregs, circuit.clbits) registers_raw = reg_buf.getvalue() num_registers = num_qregs + num_cregs # Write circuit header header_raw = formats.CIRCUIT_HEADER_V2( name_size=len(circuit_name), global_phase_type=global_phase_type, global_phase_size=len(global_phase_data), num_qubits=circuit.num_qubits, num_clbits=circuit.num_clbits, metadata_size=metadata_size, num_registers=num_registers, num_instructions=num_instructions, ) header = struct.pack(formats.CIRCUIT_HEADER_V2_PACK, *header_raw) file_obj.write(header) file_obj.write(circuit_name) file_obj.write(global_phase_data) file_obj.write(metadata_raw) # Write header payload file_obj.write(registers_raw) instruction_buffer = io.BytesIO() custom_instructions = {} index_map = {} index_map["q"] = {bit: index for index, bit in enumerate(circuit.qubits)} index_map["c"] = {bit: index for index, bit in enumerate(circuit.clbits)} for instruction in circuit.data: _write_instruction(instruction_buffer, instruction, custom_instructions, index_map) file_obj.write(struct.pack(formats.CUSTOM_CIRCUIT_DEF_HEADER_PACK, len(custom_instructions))) for name, instruction in custom_instructions.items(): _write_custom_instruction(file_obj, name, instruction) instruction_buffer.seek(0) file_obj.write(instruction_buffer.read()) instruction_buffer.close()
def _dumps_operand(operand): if isinstance(operand, library.Waveform): type_key = type_keys.ScheduleOperand.WAVEFORM data_bytes = common.data_to_binary(operand, _write_waveform) elif isinstance(operand, library.SymbolicPulse): type_key = type_keys.ScheduleOperand.SYMBOLIC_PULSE data_bytes = common.data_to_binary(operand, _write_symbolic_pulse) elif isinstance(operand, channels.Channel): type_key = type_keys.ScheduleOperand.CHANNEL data_bytes = common.data_to_binary(operand, _write_channel) else: type_key, data_bytes = value.dumps_value(operand) return type_key, data_bytes
def _write_pauli_evolution_gate(file_obj, evolution_gate): operator_list = evolution_gate.operator standalone = False if not isinstance(operator_list, list): operator_list = [operator_list] standalone = True num_operators = len(operator_list) def _write_elem(buffer, op): elem_data = common.data_to_binary(op.to_list(array=True), np.save) elem_metadata = struct.pack(formats.SPARSE_PAULI_OP_LIST_ELEM_PACK, len(elem_data)) buffer.write(elem_metadata) buffer.write(elem_data) pauli_data_buf = io.BytesIO() for operator in operator_list: data = common.data_to_binary(operator, _write_elem) pauli_data_buf.write(data) time_type, time_data = value.dumps_value(evolution_gate.time) time_size = len(time_data) synth_class = str(type(evolution_gate.synthesis).__name__) settings_dict = evolution_gate.synthesis.settings synth_data = json.dumps({ "class": synth_class, "settings": settings_dict }).encode(common.ENCODE) synth_size = len(synth_data) pauli_evolution_raw = struct.pack( formats.PAULI_EVOLUTION_DEF_PACK, num_operators, standalone, time_type, time_size, synth_size, ) file_obj.write(pauli_evolution_raw) file_obj.write(pauli_data_buf.getvalue()) pauli_data_buf.close() file_obj.write(time_data) file_obj.write(synth_data)
def _write_instruction_parameter(file_obj, param): if isinstance(param, QuantumCircuit): type_key = common.ProgramTypeKey.CIRCUIT data = common.data_to_binary(param, write_circuit) elif isinstance(param, range): type_key = common.ContainerTypeKey.RANGE data = struct.pack(formats.RANGE_PACK, param.start, param.stop, param.step) elif isinstance(param, tuple): type_key = common.ContainerTypeKey.TUPLE data = common.sequence_to_binary(param, _write_instruction_parameter) elif isinstance(param, int): # TODO This uses little endian. This should be fixed in next QPY version. type_key = common.ValueTypeKey.INTEGER data = struct.pack("<q", param) elif isinstance(param, float): # TODO This uses little endian. This should be fixed in next QPY version. type_key = common.ValueTypeKey.FLOAT data = struct.pack("<d", param) else: type_key, data = value.dumps_value(param) common.write_instruction_param(file_obj, type_key, data)
def _dumps_instruction_parameter(param): if isinstance(param, QuantumCircuit): type_key = type_keys.Program.CIRCUIT data_bytes = common.data_to_binary(param, write_circuit) elif isinstance(param, range): type_key = type_keys.Container.RANGE data_bytes = struct.pack(formats.RANGE_PACK, param.start, param.stop, param.step) elif isinstance(param, tuple): type_key = type_keys.Container.TUPLE data_bytes = common.sequence_to_binary(param, _dumps_instruction_parameter) elif isinstance(param, int): # TODO This uses little endian. This should be fixed in next QPY version. type_key = type_keys.Value.INTEGER data_bytes = struct.pack("<q", param) elif isinstance(param, float): # TODO This uses little endian. This should be fixed in next QPY version. type_key = type_keys.Value.FLOAT data_bytes = struct.pack("<d", param) else: type_key, data_bytes = value.dumps_value(param) return type_key, data_bytes