def _read_custom_operations(file_obj, version, vectors): custom_operations = {} custom_definition_header = formats.CUSTOM_CIRCUIT_DEF_HEADER._make( struct.unpack( formats.CUSTOM_CIRCUIT_DEF_HEADER_PACK, file_obj.read(formats.CUSTOM_CIRCUIT_DEF_HEADER_SIZE), )) if custom_definition_header.size > 0: for _ in range(custom_definition_header.size): if version < 5: data = formats.CUSTOM_CIRCUIT_INST_DEF._make( struct.unpack( formats.CUSTOM_CIRCUIT_INST_DEF_PACK, file_obj.read(formats.CUSTOM_CIRCUIT_INST_DEF_SIZE), )) else: data = formats.CUSTOM_CIRCUIT_INST_DEF_V2._make( struct.unpack( formats.CUSTOM_CIRCUIT_INST_DEF_V2_PACK, file_obj.read(formats.CUSTOM_CIRCUIT_INST_DEF_V2_SIZE), )) name = file_obj.read(data.gate_name_size).decode(common.ENCODE) type_str = data.type definition_circuit = None if data.custom_definition: def_binary = file_obj.read(data.size) if version < 3 or not name.startswith( r"###PauliEvolutionGate_"): definition_circuit = common.data_from_binary( def_binary, read_circuit, version=version) elif name.startswith(r"###PauliEvolutionGate_"): definition_circuit = common.data_from_binary( def_binary, _read_pauli_evolution_gate, version=version, vectors=vectors) if version < 5: data_payload = (type_str, data.num_qubits, data.num_clbits, definition_circuit) else: base_gate = file_obj.read(data.base_gate_size) data_payload = ( type_str, data.num_qubits, data.num_clbits, definition_circuit, data.num_ctrl_qubits, data.ctrl_state, base_gate, ) custom_operations[name] = data_payload return custom_operations
def loads_value(type_key, binary_data, version, vectors): """Deserialize input binary data to value object. Args: type_key (ValueTypeKey): Type enum information. binary_data (bytes): Data to deserialize. version (int): QPY version. vectors (dict): ParameterVector in current scope. Returns: any: Deserialized value object. Raises: QpyError: Serializer for given format is not ready. """ # pylint: disable=too-many-return-statements if isinstance(type_key, bytes): type_key = type_keys.Value(type_key) if type_key == type_keys.Value.INTEGER: return struct.unpack("!q", binary_data)[0] if type_key == type_keys.Value.FLOAT: return struct.unpack("!d", binary_data)[0] if type_key == type_keys.Value.COMPLEX: return complex(*struct.unpack(formats.COMPLEX_PACK, binary_data)) if type_key == type_keys.Value.NUMPY_OBJ: return common.data_from_binary(binary_data, np.load) if type_key == type_keys.Value.STRING: return binary_data.decode(common.ENCODE) if type_key == type_keys.Value.NULL: return None if type_key == type_keys.Value.PARAMETER_VECTOR: return common.data_from_binary(binary_data, _read_parameter_vec, vectors=vectors) if type_key == type_keys.Value.PARAMETER: return common.data_from_binary(binary_data, _read_parameter) if type_key == type_keys.Value.PARAMETER_EXPRESSION: if version < 3: return common.data_from_binary(binary_data, _read_parameter_expression) else: return common.data_from_binary(binary_data, _read_parameter_expression_v3, vectors=vectors) raise exceptions.QpyError( f"Serialization for {type_key} is not implemented in value I/O.")
def loads_value(type_key, binary_data, version, vectors): """Deserialize input binary data to value object. Args: type_key (ValueTypeKey): Type enum information. binary_data (bytes): Data to deserialize. version (int): QPY version. vectors (dict): ParameterVector in current scope. Returns: any: Deserialized value object. Raises: QpyError: Serializer for given format is not ready. """ if isinstance(type_key, bytes): type_key = TypeKey(type_key) if type_key == TypeKey.INTEGER: obj = struct.unpack("!q", binary_data)[0] elif type_key == TypeKey.FLOAT: obj = struct.unpack("!d", binary_data)[0] elif type_key == TypeKey.COMPLEX: obj = complex(*struct.unpack(formats.COMPLEX_PACK, binary_data)) elif type_key == TypeKey.NUMPY_OBJ: obj = common.data_from_binary(binary_data, np.load) elif type_key == TypeKey.STRING: obj = binary_data.decode(ENCODE) elif type_key == TypeKey.NULL: obj = None elif type_key == TypeKey.PARAMETER_VECTOR: obj = common.data_from_binary(binary_data, _read_parameter_vec, vectors=vectors) elif type_key == TypeKey.PARAMETER: obj = common.data_from_binary(binary_data, _read_parameter) elif type_key == TypeKey.PARAMETER_EXPRESSION: if version < 3: obj = common.data_from_binary(binary_data, _read_parameter_expression) else: obj = common.data_from_binary(binary_data, _read_parameter_expression_v3, vectors=vectors) else: raise exceptions.QpyError( f"Serialization for {type_key} is not implemented in value I/O.") return obj
def _loads_operand(type_key, data_bytes, version): if type_key == type_keys.ScheduleOperand.WAVEFORM: return common.data_from_binary(data_bytes, _read_waveform, version=version) if type_key == type_keys.ScheduleOperand.SYMBOLIC_PULSE: return common.data_from_binary(data_bytes, _read_symbolic_pulse, version=version) if type_key == type_keys.ScheduleOperand.CHANNEL: return common.data_from_binary(data_bytes, _read_channel, version=version) return value.loads_value(type_key, data_bytes, version, {})
def _read_instruction_parameter(file_obj, version, vectors): type_key, bin_data = common.read_instruction_param(file_obj) if type_key == common.ProgramTypeKey.CIRCUIT: param = common.data_from_binary(bin_data, read_circuit, version=version) elif type_key == common.ContainerTypeKey.RANGE: data = formats.RANGE._make(struct.unpack(formats.RANGE_PACK, bin_data)) param = range(data.start, data.stop, data.step) elif type_key == common.ContainerTypeKey.TUPLE: param = tuple( common.sequence_from_binary( bin_data, _read_instruction_parameter, version=version, vectors=vectors, )) elif type_key == common.ValueTypeKey.INTEGER: # TODO This uses little endian. Should be fixed in the next QPY version. param = struct.unpack("<q", bin_data)[0] elif type_key == common.ValueTypeKey.FLOAT: # TODO This uses little endian. Should be fixed in the next QPY version. param = struct.unpack("<d", bin_data)[0] else: param = value.loads_value(type_key, bin_data, version, vectors) return param
def _loads_instruction_parameter(type_key, data_bytes, version, vectors): if type_key == type_keys.Program.CIRCUIT: param = common.data_from_binary(data_bytes, read_circuit, version=version) elif type_key == type_keys.Container.RANGE: data = formats.RANGE._make( struct.unpack(formats.RANGE_PACK, data_bytes)) param = range(data.start, data.stop, data.step) elif type_key == type_keys.Container.TUPLE: param = tuple( common.sequence_from_binary( data_bytes, _loads_instruction_parameter, version=version, vectors=vectors, )) elif type_key == type_keys.Value.INTEGER: # TODO This uses little endian. Should be fixed in the next QPY version. param = struct.unpack("<q", data_bytes)[0] elif type_key == type_keys.Value.FLOAT: # TODO This uses little endian. Should be fixed in the next QPY version. param = struct.unpack("<d", data_bytes)[0] else: param = value.loads_value(type_key, data_bytes, version, vectors) return param
def _read_parameter_expression_v3(file_obj, vectors): data = formats.PARAMETER_EXPR( *struct.unpack(formats.PARAMETER_EXPR_PACK, file_obj.read(formats.PARAMETER_EXPR_SIZE))) from sympy.parsing.sympy_parser import parse_expr if _optional.HAS_SYMENGINE: import symengine expr = symengine.sympify( parse_expr(file_obj.read(data.expr_size).decode(common.ENCODE))) else: expr = parse_expr(file_obj.read(data.expr_size).decode(common.ENCODE)) symbol_map = {} for _ in range(data.map_elements): elem_data = formats.PARAM_EXPR_MAP_ELEM_V3(*struct.unpack( formats.PARAM_EXPR_MAP_ELEM_V3_PACK, file_obj.read(formats.PARAM_EXPR_MAP_ELEM_V3_SIZE), )) symbol_key = type_keys.Value(elem_data.symbol_type) if symbol_key == type_keys.Value.PARAMETER: symbol = _read_parameter(file_obj) elif symbol_key == type_keys.Value.PARAMETER_VECTOR: symbol = _read_parameter_vec(file_obj, vectors) else: raise exceptions.QpyError( "Invalid parameter expression map type: %s" % symbol_key) elem_key = type_keys.Value(elem_data.type) binary_data = file_obj.read(elem_data.size) if elem_key == type_keys.Value.INTEGER: value = struct.unpack("!q", binary_data) elif elem_key == type_keys.Value.FLOAT: value = struct.unpack("!d", binary_data) elif elem_key == type_keys.Value.COMPLEX: value = complex(*struct.unpack(formats.COMPLEX_PACK, binary_data)) elif elem_key in (type_keys.Value.PARAMETER, type_keys.Value.PARAMETER_VECTOR): value = symbol._symbol_expr elif elem_key == type_keys.Value.PARAMETER_EXPRESSION: value = common.data_from_binary(binary_data, _read_parameter_expression_v3, vectors=vectors) else: raise exceptions.QpyError( "Invalid parameter expression map type: %s" % elem_key) symbol_map[symbol] = value return ParameterExpression(symbol_map, expr)
def _read_waveform(file_obj, version): header = formats.WAVEFORM._make( struct.unpack( formats.WAVEFORM_PACK, file_obj.read(formats.WAVEFORM_SIZE), )) samples_raw = file_obj.read(header.data_size) samples = common.data_from_binary(samples_raw, np.load) name = value.read_value(file_obj, version, {}) return library.Waveform( samples=samples, name=name, epsilon=header.epsilon, limit_amplitude=header.amp_limited, )
def _read_pauli_evolution_gate(file_obj, version, vectors): pauli_evolution_def = formats.PAULI_EVOLUTION_DEF._make( struct.unpack(formats.PAULI_EVOLUTION_DEF_PACK, file_obj.read(formats.PAULI_EVOLUTION_DEF_SIZE))) if pauli_evolution_def.operator_size != 1 and pauli_evolution_def.standalone_op: raise ValueError( "Can't have a standalone operator with {pauli_evolution_raw[0]} operators in the payload" ) operator_list = [] for _ in range(pauli_evolution_def.operator_size): op_elem = formats.SPARSE_PAULI_OP_LIST_ELEM._make( struct.unpack( formats.SPARSE_PAULI_OP_LIST_ELEM_PACK, file_obj.read(formats.SPARSE_PAULI_OP_LIST_ELEM_SIZE), )) op_raw_data = common.data_from_binary(file_obj.read(op_elem.size), np.load) operator_list.append(SparsePauliOp.from_list(op_raw_data)) if pauli_evolution_def.standalone_op: pauli_op = operator_list[0] else: pauli_op = operator_list time = value.loads_value( common.ValueTypeKey(pauli_evolution_def.time_type), file_obj.read(pauli_evolution_def.time_size), version=version, vectors=vectors, ) synth_data = json.loads( file_obj.read(pauli_evolution_def.synth_method_size)) synthesis = getattr(evo_synth, synth_data["class"])(**synth_data["settings"]) return_gate = library.PauliEvolutionGate(pauli_op, time=time, synthesis=synthesis) return return_gate