Trim (qiskit_addon_sqd.trim)¶
Trim SQD, a schedule that screens more configurations than it diagonalizes.
diagonalize_fermionic_hamiltonian() diagonalizes each
subsampled batch and keeps the best result. Trim SQD instead treats the batches as
candidates to be screened: each is diagonalized, trimmed down to the configurations
carrying the largest weight, and the survivors of all the batches are merged and
diagonalized together. The energy of that merged diagonalization is what the iteration
reports, and its own trimmed output seeds the next one.
The point is that screening is cheaper than diagonalizing. Each batch is roughly the size of the merged subspace, so a set of candidates several times larger than the affordable subspace can be ranked for the cost of a few extra diagonalizations of that size.
This is expressed as a SubspacePolicy, so it describes
the schedule and leaves the diagonalizations themselves to whatever sci_solver the
caller passes.
- class TrimPolicy(*, trim_ratio=0.1, carryover_threshold=0.0001, carryover_ratio=0.1, max_strings_per_trim=None, max_carryover=None)[source]¶
Bases:
objectA
SubspacePolicythat screens disjoint batches.Each iteration diagonalizes every batch, keeps the highest-weight CI strings of each, merges them, and performs one further diagonalization over the merged subspace. That diagonalization’s energy is what the iteration reports, and its own trimmed CI strings seed the next one.
Pass an instance as the
policyargument ofdiagonalize_fermionic_hamiltonian():result = diagonalize_fermionic_hamiltonian( hcore, eri, bit_array, samples_per_batch=300, norb=norb, nelec=nelec, num_batches=5, policy=TrimPolicy(trim_ratio=0.1), )
The cost of an iteration is
num_batches + 1diagonalizations rather thannum_batches, and the merged subspace is bounded by what the batches retain.The batches are drawn as one pool of
samples_per_batch * num_batchesbitstrings divided among them, so that no bitstring appears in more than one. Screening selects among the batches, so it is only as useful as the batches differ: batches drawn independently would overlap heavily, which shrinks the pool of distinct candidates and gives a bitstring appearing in several batches several chances to survive the trim. Because that follows from what this schedule does, it is not something to configure.What this makes disjoint is the configurations. The per-spin CI string arrays derived from them can still share strings between batches, since two configurations may agree on one of their halves.
Note
A subspace here is spanned by the Cartesian product of a spin-alpha and a spin-beta CI string array, so trimming to a given number of configurations retains close to that many strings in each spin sector, whose product is larger.
max_strings_per_trimandmax_carryoverbound the strings per sector, and themax_dimargument ofdiagonalize_fermionic_hamiltonian()bounds the subspace that the next iteration builds from them.Note
Whether screening improves the result depends on the system and the scale. It is worth comparing against a run without it, which is what passing
num_batches=1amounts to: the single batch is diagonalized, trimmed and diagonalized again, with no cross-batch selection. Screening has the most to offer when the sampled configurations greatly outnumber what can be diagonalized at once, and the least when a subspace of the affordable size already captures most of the wavefunction.Initialize the policy.
This policy performs two kinds of trim, and they are bounded separately. The screening trims shrink each batch of the first round, once per batch; the carryover trim shrinks the merged subspace to what seeds the next iteration. The carryover applies the same amplitude cutoff as
StandardPolicy, then a fraction of what survives it.- Parameters:
trim_ratio (float) – The fraction of each batch’s CI strings, per spin sector, that survive screening and enter the merged subspace. Ranked by summed squared amplitude over the other spin sector.
carryover_threshold (float) – Amplitude cutoff for the CI strings that seed the next iteration, applied exactly as
StandardPolicyapplies it, with the same default. This bounds the weight discarded rather than the number of strings kept.carryover_ratio (float) – The fraction of the strings surviving
carryover_thresholdthat seed the next iteration, ranked by summed squared amplitude over the other spin sector. The cutoff runs first and the fraction narrows what it left, so the two bound different things: the cutoff the weight discarded, the fraction the count.max_strings_per_trim (int | None) –
Ceiling on the number of CI strings, per spin sector, that any one screening trim retains. Where it binds it lowers the effective ratio, so a trim keeps
min(ceil(trim_ratio * len(strings)), max_strings_per_trim)strings in each sector. Defaults toNone, leavingtrim_ratioto decide.Reach for it when a ratio would retain more than intended:
symmetrize_spinmerges the two spin sectors into a single list and so roughly doubles what each batch offers, and a largesamples_per_batchdoes the same.This is not a bound on a subspace. It applies once per batch, and the contributions are merged, so the merged subspace can hold up to
num_batchestimes as many strings per sector – in practice close to that, since the batches have little in common. Themax_dimargument ofdiagonalize_fermionic_hamiltonian()is what bounds a subspace.max_carryover (int | None) – Ceiling on the number of CI strings, per spin sector, that seed the next iteration, applied together with
carryover_ratioto the marginal-weight ranking of whatever survivedcarryover_threshold. Unlikemax_strings_per_trimthis governs a single trim of the merged subspace, so it bounds the carryover as a whole.
Note
Neither ceiling constrains a solver that selects its own carryover through
carryover, whose selection is used as given.- Raises:
ValueError – A ratio was not in
(0, 1], or a ceiling was less than one.- Parameters:
- prepare_subspaces(request)[source]¶
Divide one pool of bitstrings among the batches, so that they are disjoint.
- Parameters:
request (SubspaceRequest)
- Return type:
- refine(results, round_index)[source]¶
Merge what the batches retained, then stop after diagonalizing it.
The screening round’s results are trimmed to their highest-weight CI strings and merged into a single subspace, which the loop diagonalizes as the second round.
- select_carryover(result, *, symmetrize_spin=False)[source]¶
Carry over the highest-weight CI strings of the merged diagonalization.
The amplitude cutoff is applied exactly as
StandardPolicyapplies it, with the same default, andcarryover_ratioandmax_carryoverthen bound the count, which the cutoff alone does not. The treatment ofsymmetrize_spinis the same too: it ranks the two sectors together before merging them.