refactor(circuit)!: build UCJ from an ffsim UCJ operator - #322
Open
mrossinek wants to merge 1 commit into
Open
Conversation
The UCJ gate reimplemented how the ansatz tensors are *obtained* (double factorization of the t2 amplitudes, interaction-pair masking, and the parameter-vector packing) alongside the part that is actually this package's concern: turning those tensors into a mapper-agnostic fermionic circuit. The first half duplicated ffsim, which is where the ansatz math belongs, so this narrows the gate to the second half and takes the ffsim operator directly. The duplication was verified, not assumed. Against ffsim 0.0.84, the removed `num_parameters`/`from_parameters`/`to_parameters` agreed elementwise with `n_params`/`from_parameters`/`to_parameters` for all three spin variants and both `with_final_orbital_rotation` settings, and the tensor layouts and dtypes were already identical, so passing the operator through changes no numerics. What it gains is what ffsim has and this package never implemented: the compressed (`optimize=True`) double factorization and `from_cisd_vec`. What remains is the part with no ffsim equivalent: the OrbitalRotation and Evolution decomposition, and in particular the closed-form circle-method edge coloring that hands Evolution a pre-grouped FermionOperator so each group synthesizes as one parallel layer. That is what makes the gate lowerable through any fermion-to-qubit encoding, which ffsim's JW-hardcoded `UCJOpSpinBalancedJW` cannot do, and it is unchanged: a 2-repetition balanced ansatz still expands to 10 OrbitalRotation plus 2 Evolution gates. Two consequences worth naming. ffsim is now the gate's input type rather than an accelerator with a fallback, so UCJ is constructible only where ffsim installs, which excludes Windows; that is documented with a WSL pointer rather than worked around. Since the class docstring's example now needs ffsim, it is gated with `.. skip: start if(not HAS_FFSIM)`, which required registering Sybil's `SkipParser` in python/conftest.py; docs/conftest.py already had it, so this is the same pattern the guides use, and the example stays executed and verified wherever ffsim is installed. And `UCJOpSpinless` is read as a single norb-mode register, since a gate fixes its width at construction while ffsim resolves spin at apply time from `nelec`; the two-register reading remains expressible as a `UCJOpSpinBalanced` with a zeroed alpha-beta block, which is the same operator. `UCJAnglesOpSpinBalanced` is deliberately not accepted: it stores gate rotation angles rather than tensors, so it is already a Jordan-Wigner decomposition of the ansatz and sits below the encoding-agnostic layer this gate occupies. The LUCJ guide's transpiled phase-gate count moves from 16 to 14. ffsim's factorization returns orbital rotations differing from the previous ones by a per-column phase gauge; the operators are physically identical (same state vector to machine precision) but the gauge phases surface as PhaseGates during Givens synthesis. The VQE outer-loop guide is removed here rather than ported, since it was built entirely on the parameter API that is now ffsim's. Refs #318 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
mrossinek
force-pushed
the
ucj-from-ffsim-op
branch
from
September 4, 2026 15:41
5a9574b to
85d266c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The UCJ gate reimplemented how the ansatz tensors are obtained (double factorization of the t2 amplitudes, interaction-pair masking, and the parameter-vector packing) alongside the part that is actually this package's concern: turning those tensors into a mapper-agnostic fermionic circuit. The first half duplicated ffsim, which is where the ansatz math belongs, so this narrows the gate to the second half and takes the ffsim operator directly.
The duplication was verified, not assumed. Against ffsim 0.0.84, the removed
num_parameters/from_parameters/to_parametersagreed elementwise withn_params/from_parameters/to_parametersfor all three spin variants and bothwith_final_orbital_rotationsettings, and the tensor layouts and dtypes were already identical, so passing the operator through changes no numerics. What it gains is what ffsim has and this package never implemented: the compressed (optimize=True) double factorization andfrom_cisd_vec.What remains is the part with no ffsim equivalent: the OrbitalRotation and Evolution decomposition, and in particular the closed-form circle-method edge coloring that hands Evolution a pre-grouped FermionOperator so each group synthesizes as one parallel layer. That is what makes the gate lowerable through any fermion-to-qubit encoding, which ffsim's JW-hardcoded
UCJOpSpinBalancedJWcannot do, and it is unchanged: a 2-repetition balanced ansatz still expands to 10 OrbitalRotation plus 2 Evolution gates.Two consequences worth naming. ffsim is now the gate's input type rather than an accelerator with a fallback, so UCJ is constructible only where ffsim installs, which excludes Windows; that is documented with a WSL pointer rather than worked around. And
UCJOpSpinlessis read as a single norb-mode register, since a gate fixes its width at construction while ffsim resolves spin at apply time fromnelec; the two-register reading remains expressible as aUCJOpSpinBalancedwith a zeroed alpha-beta block, which is the same operator.UCJAnglesOpSpinBalancedis deliberately not accepted: it stores gate rotation angles rather than tensors, so it is already a Jordan-Wigner decomposition of the ansatz and sits below the encoding-agnostic layer this gate occupies.The LUCJ guide's transpiled phase-gate count moves from 16 to 14. ffsim's factorization returns orbital rotations differing from the previous ones by a per-column phase gauge; the operators are physically identical (same state vector to machine precision) but the gauge phases surface as PhaseGates during Givens synthesis. The VQE outer-loop guide is removed here rather than ported, since it was built entirely on the parameter API that is now ffsim's.
Refs #318