def _write_custom_instruction(file_obj, name, instruction): type_key = common.CircuitInstructionTypeKey.assign(instruction) has_definition = False size = 0 data = None num_qubits = instruction.num_qubits num_clbits = instruction.num_clbits if type_key == common.CircuitInstructionTypeKey.PAULI_EVOL_GATE: has_definition = True data = common.data_to_binary(instruction, _write_pauli_evolution_gate) size = len(data) elif instruction.definition is not None: has_definition = True data = common.data_to_binary(instruction.definition, write_circuit) size = len(data) name_raw = name.encode(common.ENCODE) custom_instruction_raw = struct.pack( formats.CUSTOM_CIRCUIT_INST_DEF_PACK, len(name_raw), type_key, num_qubits, num_clbits, has_definition, size, ) file_obj.write(custom_instruction_raw) file_obj.write(name_raw) if data: file_obj.write(data)
def _write_parameter_expression(file_obj, obj): from sympy import srepr, sympify expr_bytes = srepr(sympify(obj._symbol_expr)).encode(common.ENCODE) param_expr_header_raw = struct.pack(formats.PARAMETER_EXPR_PACK, len(obj._parameter_symbols), len(expr_bytes)) file_obj.write(param_expr_header_raw) file_obj.write(expr_bytes) for symbol, value in obj._parameter_symbols.items(): symbol_key = type_keys.Value.assign(symbol) # serialize key if symbol_key == type_keys.Value.PARAMETER_VECTOR: symbol_data = common.data_to_binary(symbol, _write_parameter_vec) else: symbol_data = common.data_to_binary(symbol, _write_parameter) # serialize value if value == symbol._symbol_expr: value_key = symbol_key value_data = bytes() else: value_key, value_data = dumps_value(value) elem_header = struct.pack( formats.PARAM_EXPR_MAP_ELEM_V3_PACK, symbol_key, value_key, len(value_data), ) file_obj.write(elem_header) file_obj.write(symbol_data) file_obj.write(value_data)
def _write_custom_operation(file_obj, name, operation, custom_operations): type_key = type_keys.CircuitInstruction.assign(operation) has_definition = False size = 0 data = None num_qubits = operation.num_qubits num_clbits = operation.num_clbits ctrl_state = 0 num_ctrl_qubits = 0 base_gate = None new_custom_instruction = [] if type_key == type_keys.CircuitInstruction.PAULI_EVOL_GATE: has_definition = True data = common.data_to_binary(operation, _write_pauli_evolution_gate) size = len(data) elif type_key == type_keys.CircuitInstruction.CONTROLLED_GATE: # For ControlledGate, we have to access and store the private `_definition` rather than the # public one, because the public one is mutated to include additional logic if the control # state is open, and the definition setter (during a subsequent read) uses the "fully # excited" control definition only. has_definition = True data = common.data_to_binary(operation._definition, write_circuit) size = len(data) num_ctrl_qubits = operation.num_ctrl_qubits ctrl_state = operation.ctrl_state base_gate = operation.base_gate elif operation.definition is not None: has_definition = True data = common.data_to_binary(operation.definition, write_circuit) size = len(data) if base_gate is None: base_gate_raw = b"" else: with io.BytesIO() as base_gate_buffer: new_custom_instruction = _write_instruction( base_gate_buffer, CircuitInstruction(base_gate, (), ()), custom_operations, {}) base_gate_raw = base_gate_buffer.getvalue() name_raw = name.encode(common.ENCODE) custom_operation_raw = struct.pack( formats.CUSTOM_CIRCUIT_INST_DEF_V2_PACK, len(name_raw), type_key, num_qubits, num_clbits, has_definition, size, num_ctrl_qubits, ctrl_state, len(base_gate_raw), ) file_obj.write(custom_operation_raw) file_obj.write(name_raw) if data: file_obj.write(data) file_obj.write(base_gate_raw) return new_custom_instruction
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_waveform(file_obj, data): samples_bytes = common.data_to_binary(data.samples, np.save) header = struct.pack( formats.WAVEFORM_PACK, data.epsilon, len(samples_bytes), data._limit_amplitude, ) file_obj.write(header) file_obj.write(samples_bytes) value.write_value(file_obj, data.name)
def dumps_value(obj): """Serialize input value object. Args: obj (any): Arbitrary value object to serialize. Returns: tuple: TypeKey and binary data. Raises: QpyError: Serializer for given format is not ready. """ type_key = type_keys.Value.assign(obj) if type_key == type_keys.Value.INTEGER: binary_data = struct.pack("!q", obj) elif type_key == type_keys.Value.FLOAT: binary_data = struct.pack("!d", obj) elif type_key == type_keys.Value.COMPLEX: binary_data = struct.pack(formats.COMPLEX_PACK, obj.real, obj.imag) elif type_key == type_keys.Value.NUMPY_OBJ: binary_data = common.data_to_binary(obj, np.save) elif type_key == type_keys.Value.STRING: binary_data = obj.encode(common.ENCODE) elif type_key == type_keys.Value.NULL: binary_data = b"" elif type_key == type_keys.Value.PARAMETER_VECTOR: binary_data = common.data_to_binary(obj, _write_parameter_vec) elif type_key == type_keys.Value.PARAMETER: binary_data = common.data_to_binary(obj, _write_parameter) elif type_key == type_keys.Value.PARAMETER_EXPRESSION: binary_data = common.data_to_binary(obj, _write_parameter_expression) else: raise exceptions.QpyError( f"Serialization for {type_key} is not implemented in value I/O.") return type_key, binary_data
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
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)