Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parameterized circuits can no longer be loaded with qpy. #13720

Open
Guillermo-Mijares-Vilarino opened this issue Jan 22, 2025 · 1 comment · May be fixed by #13727
Open

Parameterized circuits can no longer be loaded with qpy. #13720

Guillermo-Mijares-Vilarino opened this issue Jan 22, 2025 · 1 comment · May be fixed by #13727
Labels
bug Something isn't working

Comments

@Guillermo-Mijares-Vilarino
Copy link
Contributor

Environment

  • Qiskit version: 1.3.2
  • Python version: 3.12.7
  • Operating system: macOS Sequoia 15.1.1

What is happening?

After upgrading qiskit from 1.2.4 to 1.3.2, qpy started failing to load parameterized circuits.

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
Cell In[2], line 10
      7     qpy.dump(fm, file)
      9 with open(\"circuit.qpy\", \"rb\") as file:
---> 10     new_fm = qpy.load(file)[0]

File ~/miniconda3/envs/pqf_function/lib/python3.12/site-packages/qiskit/qpy/interface.py:370, in load(file_obj, metadata_deserializer)
    367 programs = []
    368 for _ in range(data.num_programs):
    369     programs.append(
--> 370         loader(
    371             file_obj,
    372             data.qpy_version,
    373             metadata_deserializer=metadata_deserializer,
    374             use_symengine=use_symengine,
    375         )
    376     )
    377 return programs

File ~/miniconda3/envs/pqf_function/lib/python3.12/site-packages/qiskit/qpy/binary_io/circuits.py:1441, in read_circuit(file_obj, version, metadata_deserializer, use_symengine)
   1439 for declaration in var_segments[type_keys.ExprVarDeclaration.LOCAL]:
   1440     circ.add_uninitialized_var(declaration)
-> 1441 custom_operations = _read_custom_operations(file_obj, version, vectors)
   1442 for _instruction in range(num_instructions):
   1443     _read_instruction(
   1444         file_obj,
   1445         circ,
   (...)
   1451         standalone_var_indices,
   1452     )

File ~/miniconda3/envs/pqf_function/lib/python3.12/site-packages/qiskit/qpy/binary_io/circuits.py:617, in _read_custom_operations(file_obj, version, vectors)
    615 def_binary = file_obj.read(data.size)
    616 if version < 3 or not name.startswith(r\"###PauliEvolutionGate_\"):
--> 617     definition_circuit = common.data_from_binary(
    618         def_binary, read_circuit, version=version
    619     )
    620 elif name.startswith(r\"###PauliEvolutionGate_\"):
    621     definition_circuit = common.data_from_binary(
    622         def_binary, _read_pauli_evolution_gate, version=version, vectors=vectors
    623     )

File ~/miniconda3/envs/pqf_function/lib/python3.12/site-packages/qiskit/qpy/common.py:267, in data_from_binary(binary_data, deserializer, **kwargs)
    265 with io.BytesIO(binary_data) as container:
    266     container.seek(0)
--> 267     obj = deserializer(container, **kwargs)
    268 return obj

File ~/miniconda3/envs/pqf_function/lib/python3.12/site-packages/qiskit/qpy/binary_io/circuits.py:1443, in read_circuit(file_obj, version, metadata_deserializer, use_symengine)
   1441 custom_operations = _read_custom_operations(file_obj, version, vectors)
   1442 for _instruction in range(num_instructions):
-> 1443     _read_instruction(
   1444         file_obj,
   1445         circ,
   1446         out_registers,
   1447         custom_operations,
   1448         version,
   1449         vectors,
   1450         use_symengine,
   1451         standalone_var_indices,
   1452     )
   1454 # Read calibrations
   1455 if version >= 5:

File ~/miniconda3/envs/pqf_function/lib/python3.12/site-packages/qiskit/qpy/binary_io/circuits.py:297, in _read_instruction(file_obj, circuit, registers, custom_operations, version, vectors, use_symengine, standalone_vars)
    295 for _param in range(instruction.num_parameters):
    296     type_key, data_bytes = common.read_generic_typed_data(file_obj)
--> 297     param = _loads_instruction_parameter(
    298         type_key,
    299         data_bytes,
    300         version,
    301         vectors,
    302         registers,
    303         circuit,
    304         use_symengine,
    305         standalone_vars,
    306     )
    307     params.append(param)
    309 # Load Gate object

File ~/miniconda3/envs/pqf_function/lib/python3.12/site-packages/qiskit/qpy/binary_io/circuits.py:201, in _loads_instruction_parameter(type_key, data_bytes, version, vectors, registers, circuit, use_symengine, standalone_vars)
    199 else:
    200     clbits = circuit.clbits if circuit is not None else ()
--> 201     param = value.loads_value(
    202         type_key,
    203         data_bytes,
    204         version,
    205         vectors,
    206         clbits=clbits,
    207         cregs=registers[\"c\"],
    208         use_symengine=use_symengine,
    209         standalone_vars=standalone_vars,
    210     )
    212 return param

File ~/miniconda3/envs/pqf_function/lib/python3.12/site-packages/qiskit/qpy/binary_io/value.py:971, in loads_value(type_key, binary_data, version, vectors, clbits, cregs, use_symengine, standalone_vars)
    964         return common.data_from_binary(
    965             binary_data,
    966             _read_parameter_expression_v3,
    967             vectors=vectors,
    968             use_symengine=use_symengine,
    969         )
    970     else:
--> 971         return common.data_from_binary(
    972             binary_data, _read_parameter_expression_v13, vectors=vectors, version=version
    973         )
    974 if type_key == type_keys.Value.EXPRESSION:
    975     return common.data_from_binary(
    976         binary_data,
    977         _read_expr,
   (...)
    980         standalone_vars=standalone_vars,
    981     )

File ~/miniconda3/envs/pqf_function/lib/python3.12/site-packages/qiskit/qpy/common.py:267, in data_from_binary(binary_data, deserializer, **kwargs)
    265 with io.BytesIO(binary_data) as container:
    266     container.seek(0)
--> 267     obj = deserializer(container, **kwargs)
    268 return obj

File ~/miniconda3/envs/pqf_function/lib/python3.12/site-packages/qiskit/qpy/binary_io/value.py:518, in _read_parameter_expression_v13(file_obj, vectors, version)
    516     symbol = _read_parameter(file_obj)
    517 elif symbol_key == type_keys.Value.PARAMETER_VECTOR:
--> 518     symbol = _read_parameter_vec(file_obj, vectors)
    519 else:
    520     raise exceptions.QpyError(f\"Invalid parameter expression map type: {symbol_key}\")

File ~/miniconda3/envs/pqf_function/lib/python3.12/site-packages/qiskit/qpy/binary_io/value.py:402, in _read_parameter_vec(file_obj, vectors)
    400     vectors[name] = (ParameterVector(name, data.vector_size), set())
    401 vector = vectors[name][0]
--> 402 if vector[data.index].uuid != param_uuid:
    403     vectors[name][1].add(data.index)
    404     vector._params[data.index] = ParameterVectorElement(vector, data.index, uuid=param_uuid)

File ~/miniconda3/envs/pqf_function/lib/python3.12/site-packages/qiskit/circuit/parametervector.py:78, in ParameterVector.__getitem__(self, key)
     77 def __getitem__(self, key):
---> 78     return self.params[key]

IndexError: list index out of range

How can we reproduce the issue?

from qiskit import qpy
from qiskit.circuit.library import PauliFeatureMap

qc = PauliFeatureMap(feature_dimension=5, reps=1)

with open("circuit.qpy", "wb") as fd:
    qpy.dump(qc, fd)

with open("circuit.qpy", "rb") as fd:
    new_qc = qpy.load(fd)[0]

What should happen?

The circuit should be loaded without raising an error, as in qiskit<1.3.0.

Any suggestions?

No response

@Guillermo-Mijares-Vilarino Guillermo-Mijares-Vilarino added the bug Something isn't working label Jan 22, 2025
@ElePT
Copy link
Contributor

ElePT commented Jan 22, 2025

Thanks for reporting this bug! I did a quick investigation and I think the issue is related to the "special" class of circuit of the PauliFeatureMap (which is not a QuantumCircuit but a BlueprintCircuit). We will look more into it, but as an intermediate solution, you can use the new constructor for the pauli feature map which does produce a QuantumCircuit:

from qiskit import qpy
from qiskit.circuit.library import pauli_feature_map

qc = pauli_feature_map(feature_dimension=5, reps=1)

with open("circuit.qpy", "wb") as fd:
    qpy.dump(qc, fd)

with open("circuit.qpy", "rb") as fd:
    new_qc = qpy.load(fd)[0]

@ElePT ElePT linked a pull request Jan 23, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants