qlat_utils.ama — All-mode Averaging (AMA) for Multi-accuracy Measurements¶
Source: qlat-utils/qlat_utils/ama.py
Note: Update this document when updating the source file.
Outline¶
AmaVal— container for sloppy value plus accuracy correctionsmk_ama_val— construct an AMA value from a list of measurementsama_extract/ama_extract_ama_val— produce the variance-reduced final estimateama_apply1,ama_apply2,ama_apply— propagate operations through AMA valuesama_list— collect multiple AMA values into a listama_msc_mult,ama_msc_add— arithmetic helpers used byAmaVal.__mul__and__add__merge_description_dict— merge source-specification dictionaries
Overview¶
All-mode Averaging (AMA) is a variance-reduction technique used in lattice
QCD. Measurements are taken at multiple accuracy levels (e.g. sloppy,
fine, ultra-fine) with known sampling probabilities. The ama module
provides a container, AmaVal, that stores the sloppy result together
with all correction pairs (value, description_dict) and propagates
arbitrary binary operations through all valid correction combinations.
ama_extract then combines them into a single unbiased estimate.
The description dictionary maps each source_specification key to a
tuple (accuracy_level, probability) and ensures that corrections from
different sources are only combined when their specifications are
compatible.
Detailed Sections¶
AmaVal¶
class AmaVal:
val # sloppy result (may be None after operations)
corrections # [(value, {source_spec: (level, prob), ...}), ...]
Supports +, * with scalars or other AmaVal instances. The
operators delegate to ama_msc_add and ama_msc_mult which in turn
call ama_apply2.
Constructing AMA Values¶
mk_ama_val(val, source_specification, val_list, rel_acc_list, prob_list):
val— the sloppy result (must equalval_list[0])source_specification— hashable key uniquely identifying the propagator source, e.g.("point", (12, 2, 3, 4))val_list— list of measurements at increasing accuracy;Noneentries are skippedrel_acc_list— integer accuracy levels (0 = sloppy, 1 = fine, …)prob_list— probability of each accuracy level being sampled
If only one non-None value is provided the function returns the plain
value (no wrapping).
Applying Operations¶
Function |
Description |
|---|---|
|
Apply unary |
|
Apply binary |
|
N-ary version; collects args via |
When both operands are AmaVal, the correction dictionaries are merged
with merge_description_dict: dictionaries are compatible iff all shared
keys map to the same (level, prob) pair.
Extracting the Final Result¶
ama_extract(x, *, is_sloppy=False):
If
xis not anAmaVal, returnsxunchanged.If
is_sloppy=True, returns only the sloppy component.Otherwise, recursively computes the correction sum:
result = sloppy
for each source key k:
for accuracy level i >= 1:
diff = val(level_i) - val(level_{i-1})
result += diff / prob_i
This yields an unbiased estimate with reduced variance compared to the sloppy measurement alone.
Merging Description Dictionaries¶
merge_description_dict(d1, d2) returns a merged dictionary if
compatible, or None if any shared key has conflicting values.
Compatibility ensures that two correction terms can be combined
(e.g. when multiplying AMA values from different sources).
Utility¶
ama_counts(x) returns the number of correction terms (1 for plain
values). Useful for estimating computational cost.
Examples¶
Basic AMA construction and extraction¶
import qlat_utils as q
# Sloppy measurement = 1.0, fine = 1.01, ultra-fine = 1.011
v = q.mk_ama_val(
1.0,
("point", (0, 0, 0, 0)),
[1.0, 1.01, 1.011],
[0, 1, 2],
[1.0, 0.1, 0.02],
)
# v is an AmaVal; extract the corrected result
result = q.ama_extract(v)
Arithmetic on AMA values¶
import qlat_utils as q
v1 = q.mk_ama_val(
1.0, "src_a",
[1.0, 1.01], [0, 1], [1.0, 0.1],
)
v2 = q.mk_ama_val(
2.0, "src_b",
[2.0, 2.01], [0, 1], [1.0, 0.1],
)
# Operations propagate through corrections automatically
v_sum = v1 + v2
v_prod = v1 * v2
print(q.ama_extract(v_sum)) # corrected sum
print(q.ama_extract(v_prod)) # corrected product
Mixed AMA and plain values¶
import qlat_utils as q
v = q.mk_ama_val(
1.0, "src",
[1.0, 1.01], [0, 1], [1.0, 0.1],
)
# Multiplying by a plain scalar works transparently
scaled = v * 3.0
print(q.ama_extract(scaled))
Extracting the sloppy-only result¶
import qlat_utils as q
v = q.mk_ama_val(
1.0, "src",
[1.0, 1.01, 1.011], [0, 1, 2], [1.0, 0.1, 0.02],
)
sloppy = q.ama_extract(v, is_sloppy=True)
print("Sloppy only:", sloppy) # 1.0
Counting correction terms¶
import qlat_utils as q
plain = 3.14
print(q.ama_counts(plain)) # 1
v = q.mk_ama_val(1.0, "src", [1.0, 1.01, 1.011], [0, 1, 2], [1.0, 0.1, 0.02])
print(q.ama_counts(v)) # 3