Repository navigation
Fix device.run() fails for QuantumCircuit subclasses (e.g. bound qiskit-nature UCCSD): "Alias 'qiskit' is already registered with a different type" - #1483
Conversation
…it-nature UCCSD): "Alias 'qiskit' is already registered with a different type" Fixes qBraid#1480.
Argus reviewAuto-review is off for this repo. Tick the box below to run a review on this PR.
Estimated cost
Tip: you can also comment |
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Document the QuantumCircuit subclass ProgramSpec fix and reorder the qbraid.programs import in device.py so QPROGRAM_REGISTRY comes first.
Resolve the CHANGELOG conflict by keeping the new qBraid#1490 and qBraid#1486 entries alongside this PR's qBraid#1483 entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve the CHANGELOG conflict by keeping the new qBraid#1490 and qBraid#1486 entries alongside this PR's qBraid#1483 entry.
9637af8 to
402e566
Compare
ryanhill1
left a comment
There was a problem hiding this comment.
Thanks for the fix. The subclass case works, and the other two new tests fail if the production change is reverted. Two things to change before this merges, both inline.
| if self._target_spec is not None and self._options.get("transpile") is True: | ||
| run_input_alias = get_program_type_alias(run_input, safe=True) | ||
| run_input_spec = ProgramSpec(type(run_input), alias=run_input_alias) | ||
| program_type = QPROGRAM_REGISTRY[run_input_alias] if run_input_alias else type(run_input) |
There was a problem hiding this comment.
QPROGRAM_REGISTRY[run_input_alias] raises a bare KeyError if the resolved alias has been unregistered. get_program_type_alias returns the metatype's alias (qasm2, qasm3, ionq, ...) without checking the registry, and unregister_program_type is public API. tests/transpiler/test_conversion_graph.py:521 calls it, for example.
Repro:
from qbraid.programs import QPROGRAM_REGISTRY, get_program_type_alias, unregister_program_type
unregister_program_type("qasm2")
alias = get_program_type_alias('OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg q[1];\nh q[0];\n') # "qasm2"
QPROGRAM_REGISTRY[alias] # KeyError: 'qasm2'Before this PR, ProgramSpec(str, alias="qasm2") just re-registered the alias, so apply_runtime_profile on a QASM 2 string with transpile=True worked. Now it fails with a KeyError, which callers catching ProgramConversionError/ProgramTypeError won't handle. Falling back to the old behavior keeps the subclass fix:
| program_type = QPROGRAM_REGISTRY[run_input_alias] if run_input_alias else type(run_input) | |
| program_type = ( | |
| QPROGRAM_REGISTRY.get(run_input_alias, type(run_input)) | |
| if run_input_alias | |
| else type(run_input) | |
| ) |
The same expression is in qbraid/programs/program.py:79:
program_type = QPROGRAM_REGISTRY.get(alias, type(program)) if alias else type(program)| assert alias == "qiskit" | ||
|
|
||
| # The fix: use the registered type, not type(circuit) | ||
| program_type = QPROGRAM_REGISTRY[alias] if alias else type(circuit) |
There was a problem hiding this comment.
This test copies the fix expression instead of calling the code it's meant to cover, so it still passes if the change in device.py or program.py is reverted. I checked: with both production changes reverted, the other two tests in this class fail and this one passes.
Calling get_spec makes it test the real path:
def test_program_spec_from_subclass_uses_registered_type(self):
"""get_spec on a subclass should record the registered parent type."""
pytest.importorskip("qiskit", reason="qiskit not installed")
from qiskit import QuantumCircuit
from qbraid.programs.program import QuantumProgram
class MyCircuit(QuantumCircuit):
"""Custom QuantumCircuit subclass."""
spec = QuantumProgram.get_spec(MyCircuit(2))
assert spec.program_type is QuantumCircuit
assert spec.alias == "qiskit"Or add assert spec.program_type is QuantumCircuit to test_get_spec_with_subclass, which currently checks only the alias, and drop this test.
Fixes #1480.
What changed
Summary
Root Cause
When
QuantumDevice.run()is called with aQuantumCircuitsubclass (e.g., qiskit-nature'sUCCSD,TwoLocal,EfficientSU2), the code was usingtype(run_input)to create aProgramSpec. Sinceget_program_type_alias()returns"qiskit"for anyQuantumCircuitsubclass (viaisinstance), butProgramSpec(type(run_input), alias="qiskit")tried to register the subclass under the"qiskit"alias, it collided with the already-registeredQuantumCircuittype, raising:Changes
1.
qbraid/runtime/device.py(line ~466)apply_runtime_profile(): Changed fromProgramSpec(type(run_input), alias=run_input_alias)toProgramSpec(QPROGRAM_REGISTRY[run_input_alias], alias=run_input_alias)when the alias is known.2.
qbraid/programs/program.py(line ~79)QuantumProgram.get_spec(): Same fix — useQPROGRAM_REGISTRY[alias]instead oftype(program).Test Added
Added
TestQuantumCircuitSubclassclass intests/runtime/test_device.pywith 3 tests:test_apply_runtime_profile_with_quantum_circuit_subclass— Verifiesapply_runtime_profile()works with a customQuantumCircuitsubclasstest_get_spec_with_subclass— VerifiesQuantumProgram.get_spec()works with subclassestest_program_spec_from_subclass_uses_registered_type— Verifies the fix logic directlyHow it was verified
tests/runtime/test_device.pyThis was worked on in conjunction with AI tools.