Skip to content

refactor: Custom modifiers for Pauli exp - #52

Open
Walden-Killick wants to merge 13 commits into
refactor/hamiltonian_simulationfrom
refactor/pauli_exp
Open

Walden-Killick wants to merge 13 commits into
refactor/hamiltonian_simulationfrom
refactor/pauli_exp

Conversation

@Walden-Killick

@Walden-Killick Walden-Killick commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

Refactors the pauli_exp method to return a Guppy unitary with custom modifiers.

Closes #59

@Walden-Killick
Walden-Killick added this pull request to stack #53 October 1, 2026 10:44
@Walden-Killick Walden-Killick changed the title refactor/pauli exp refactor: Custom modifiers for Pauli exp Oct 1, 2026
@Walden-Killick Walden-Killick self-assigned this Oct 7, 2026
@Walden-Killick
Walden-Killick marked this pull request as ready for review October 8, 2026 13:34
Copilot AI balanced review requested due to automatic review settings October 8, 2026 13:34

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

5 open findings
What changed in this PR

Refactors pauli_exp to return a Guppy unitary gadget (when the provided rz_method supports it), enabling custom modifiers like dagger/controlled, and updates tests/docs accordingly.

Changes:

  • Add unitary-class implementation for pauli_exp (including controlled/daggered variants) and new identity-string behavior.
  • Update tests to validate dagger behavior and treat identity exponentials as no-ops (uncontrolled).
  • Bump guppylang minimum version and adjust example notebook content.
File Description
tests/​primitives/​pauli/​pauli_exp/​test_pauli_exp.py Adds dagger validation and changes identity-string expectations to a no-op unitary.
pyproject.toml Raises minimum guppylang version to pick up needed unitary/modifier functionality.
guppyalgos/​primitives/​pauli/​pauli_exp/​pauli_exp.py Implements unitary gadget path with custom modifiers, plus special handling for identity Pauli strings.
examples/​pauli_exponential/​pauli_exponential.ipynb Removes the RUS rotation swap-in section from the example notebook.

🧠 Review effort: Lite


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Comment on lines +159 to +170
pauli_indices = list(pauli_string.get_dict().keys())

@guppy.comptime
@no_type_check
def pauli_gadget_fn(qreg: array[qubit, n_qubits], angle: angle) -> None:
ladder = cx_ladder()
qubit_subset = [qreg[i] for i in pauli_indices]
if not has_unitary_rz:

basis_change(qreg)
@guppy
@no_type_check
def pauli_gadget_fn(qreg: array[qubit, n_qubits], angle: angle) -> None:
ladder = cx_ladder()
basis_change(qreg)
qubit_subset, borrowed_qreg = _take_pauli_qubits(
qreg, comptime(pauli_indices)
)
Comment on lines +110 to +150
@guppy.unitary
class identity_gadget:
@guppy
@no_type_check
def __call__(qreg: array[qubit, n_qubits], angle: angle) -> None:
pass

@guppy
@no_type_check
def controlled[n_controls: nat](
qreg: array[qubit, n_qubits],
angle: angle,
controls: array[qubit, n_controls],
) -> None:
if n_controls == 1:
rz_method(controls[0], -angle / 2)
else:
phase_qreg = qarray(1)
with control(controls):
rz_method(phase_qreg[0], angle)
discard_array(phase_qreg)

@guppy
@no_type_check
def daggered(qreg: array[qubit, n_qubits], angle: angle) -> None:
pass

@guppy
@no_type_check
def ctrl_daggered[n_controls: nat](
qreg: array[qubit, n_qubits],
angle: angle,
controls: array[qubit, n_controls],
) -> None:
if n_controls == 1:
rz_method(controls[0], angle / 2)
else:
phase_qreg = qarray(1)
with control(controls):
rz_method(phase_qreg[0], -angle)
discard_array(phase_qreg)
Comment thread guppyalgos/primitives/pauli/pauli_exp/pauli_exp.py Outdated
Comment on lines +84 to +91
@guppy
@no_type_check
def main_dagger(state_qreg: array[qubit, n_state_qubits]) -> None:
with dagger:
pauli_g(state_qreg, angle(theta))

dagger_u = get_unitary(main_dagger, n_state_qubits)
assert_allclose_ignorephase(u_mat.conj().T, dagger_u)
Comment thread tests/primitives/pauli/pauli_exp/test_pauli_exp.py Outdated

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Refactor: custom modifiers for Pauli exp

2 participants