Skip to content

Feat: private instructions - #217

Open
ThomasB-Colibri wants to merge 18 commits into
devfrom
feat-private-instructions
Open

Feat: private instructions#217
ThomasB-Colibri wants to merge 18 commits into
devfrom
feat-private-instructions

Conversation

@ThomasB-Colibri

Copy link
Copy Markdown
Collaborator

Make instructions list from QCircuit private

@ThomasB-Colibri ThomasB-Colibri self-assigned this Sep 1, 2026
@github-actions github-actions Bot added the enhancement New feature or request label Sep 1, 2026
@ThomasB-Colibri ThomasB-Colibri changed the title feat: private instructions Feat: private instructions Sep 1, 2026
@ThomasB-Colibri
ThomasB-Colibri marked this pull request as ready for review September 2, 2026 09:59

@ThomasB-Colibri ThomasB-Colibri left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed against c2f4aa3d. I found one provider-dependent correctness regression and three state/API regressions that should be addressed before merge. The GitHub Actions runs for this commit are currently action_required and contain no jobs, so no CI result was available to validate the changes. GitHub does not allow the PR author to submit a formal “request changes” review, so these are submitted as review comments.

Comment thread mpqp/translation/cirq.py

for instruction in circuit.instructions + circuit.measurements:
instructions = circuit._instructions # pyright: ignore[reportPrivateUsage]
for instruction in instructions:

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Keep measurements terminal across provider translations

_instructions preserves insertion order, so iterating it directly changes the circuit semantics when a measurement is followed by another circuit or gate. For example, QCircuit([X(0), BasisMeasure([0], shots=1)]) + QCircuit([X(0)]) used to translate as X, X, measure; this code now emits X, measure, X for Cirq (and the same change exists in Braket), while the Qiskit translator still skips measurements in its first pass and appends all of them at the end. The same MPQP circuit can therefore produce a different distribution or be rejected depending on the provider. Please keep the previous terminal-measurement normalization in every translator, or enforce terminal measurements at the QCircuit boundary and add cross-provider tests for composed circuits.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done 91d7910

Comment thread mpqp/core/circuit.py Outdated
A copy is returned so the circuit cannot be modified by mutating this
list directly. Use :meth:`add` to add instructions to the circuit.
"""
return self._instructions.copy()

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Preserve the public instructions contract

Before this PR, instructions contained non-measurement instructions and measurements exposed measurements separately; circuit.instructions + circuit.measurements was the established pattern used throughout MPQP. Returning the unified backing list here changes that public contract and makes the same expression duplicate every measurement for downstream callers. If the goal is encapsulation, please return a shallow filtered list of non-measurement instructions and expose an explicitly named all-instructions view if needed. Otherwise this needs an intentional compatibility/deprecation plan and migration coverage rather than landing as a side effect of privatizing storage.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done 9737817

Comment thread mpqp/core/circuit.py
"""
if isinstance(instructions, Instruction):
index = self._instructions.index(instructions)
self._pop_instruction(index)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Recompute dynamic circuit dimensions after removal

_pop_instruction() updates the measurement/variable indexes but never recomputes _nb_cbits or _nb_qubits. This is observable for dynamically sized circuits: after c = QCircuit([BasisMeasure([0])]); c.remove(c.measurements[0]); c.add(BasisMeasure([0])), the second measurement starts at classical bit 1 and the circuit grows to two classical bits because the removed measurement left _nb_cbits == 1. Removing the only highest-target gate similarly leaves extra qubits. Please recompute dimensions from the remaining components when the corresponding user-defined size is None, while preserving explicitly fixed sizes, and cover both measurement and gate removal.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done 9737817

Comment thread mpqp/core/circuit.py Outdated
if isinstance(param, Expr):
params.update(param.free_symbols)
return params
return set(self._variables)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Avoid caching variables across mutable instruction objects

The circuit stores the exact instruction object passed to add, and the new instructions property also returns those same mutable elements. Consequently the cache can diverge without any circuit method being called: gate = Rx(theta, 0); c = QCircuit([gate]); gate.parameters[0] = phi; c.variables() still returns {theta} although the stored gate now references phi. The previous implementation scanned the current instructions and stayed coherent. Please either make/copy contained instructions so external mutation is impossible, provide a complete invalidation mechanism, or continue computing variables on demand; add a regression test using a retained gate reference.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done 9737817

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant