homodyne.optimization.cmc.reparameterization¶
The reparameterization module transforms correlated physics parameters
into an orthogonal sampling space for MCMC, then converts back to physics
parameters for output. This improves NUTS sampling efficiency by reducing
posterior correlations between parameters that span different scales
(e.g., D₀ ~ 10⁴ and γ̇₀ ~ 10⁻³).
Note
Reparameterized values are computed after the time grid is constructed,
since t_ref = sqrt(dt × t_max) depends on the data. core.py calls
compute_t_ref() and falls back to t_ref=1.0 if inputs are invalid.
ReparamConfig¶
Configuration dataclass controlling which parameters are reparameterized.
- class homodyne.optimization.cmc.reparameterization.ReparamConfig[source]
Bases:
objectConfiguration for internal reparameterization.
- enable_d_ref
Enable D_ref reparameterization (D0, alpha → log_D_ref, alpha).
- Type:
- enable_gamma_ref
Sample log(gamma_ref) where gamma_ref = gamma_dot_t0 * t_ref^beta.
- Type:
- t_ref
Reference time for reparameterization (geometric mean of time range).
- Type:
- enable_d_ref: bool = True
- enable_gamma_ref: bool = True
- t_ref: float = 1.0
- property enable_d_total: bool
Backward-compatible alias for enable_d_ref.
- property enable_log_gamma: bool
Backward-compatible alias for enable_gamma_ref.
- __init__(enable_d_ref=True, enable_gamma_ref=True, t_ref=1.0)
Parameter Transformations¶
The following transforms are applied when reparameterization is enabled:
Physics Parameter |
Sampling Parameter |
Transform |
|---|---|---|
|
|
|
|
|
|
|
|
|
The prior on D_offset_ratio is TruncatedNormal(low=-1+ε). The lower
bound enforces D_ref + D_offset > 0 at t_ref (non-negative total
diffusion coefficient at the reference time). Negative values of
D_offset_ratio in the range (-1, 0) correspond to jammed/arrested
systems where D_offset < 0 physically reduces diffusion.
The back-transform is exact: D_offset = D_ref × D_offset_ratio.
compute_t_ref¶
- homodyne.optimization.cmc.reparameterization.compute_t_ref(dt, t_max, *, fallback_value=None)[source]
Compute reference time as geometric mean of time range.
- Parameters:
- Returns:
Reference time t_ref = sqrt(dt * t_max), or fallback_value if inputs invalid.
- Return type:
- Raises:
ValueError – If dt or t_max are non-positive or non-finite and fallback_value is None.
transform_nlsq_to_reparam_space¶
- homodyne.optimization.cmc.reparameterization.transform_nlsq_to_reparam_space(nlsq_values, nlsq_uncertainties, t_ref)[source]
Transform NLSQ estimates to reference-time reparameterized space.
Computes D_ref, log_D_ref, gamma_ref, log_gamma_ref from NLSQ physics parameters, with delta-method uncertainty propagation.
- Parameters:
- Returns:
(reparam_values, reparam_uncertainties) in the reparameterized space. Keys: “log_D_ref”, “D_offset_ratio”, “log_gamma_ref” (when available).
- Return type:
transform_to_sampling_space¶
- homodyne.optimization.cmc.reparameterization.transform_to_sampling_space(params, config)[source]
Transform physics params → sampling params.
transform_to_physics_space¶
- homodyne.optimization.cmc.reparameterization.transform_to_physics_space(samples, config)[source]
Transform sampling params → physics params (vectorized).
Usage Examples¶
NLSQ warm-start to reparameterized priors¶
from homodyne.optimization.cmc.reparameterization import (
compute_t_ref,
transform_nlsq_to_reparam_space,
ReparamConfig,
)
# From data: dt=0.001s, t_max=0.1s
t_ref = compute_t_ref(dt=0.001, t_max=0.1) # sqrt(0.001 * 0.1) ≈ 0.01
nlsq_values = {"D0": 19231.0, "alpha": 1.5, "D_offset": 100.0,
"gamma_dot_t0": 0.003, "beta": 0.8}
nlsq_uncert = {"D0": 500.0, "alpha": 0.1, "D_offset": 20.0,
"gamma_dot_t0": 0.001, "beta": 0.05}
reparam_vals, reparam_unc = transform_nlsq_to_reparam_space(
nlsq_values, nlsq_uncert, t_ref
)
# reparam_vals contains: log_D_ref, D_offset_ratio, log_gamma_ref, alpha, beta
Converting MCMC samples back to physics¶
from homodyne.optimization.cmc.reparameterization import (
transform_to_physics_space,
ReparamConfig,
)
import numpy as np
config = ReparamConfig(enable_d_ref=True, enable_gamma_ref=True, t_ref=0.01)
# Batched MCMC samples (e.g., from 4 chains × 1000 samples)
samples = {
"log_D_ref": np.random.normal(-2.0, 0.1, size=4000),
"alpha": np.random.normal(1.5, 0.05, size=4000),
"D_offset_ratio": np.random.normal(0.05, 0.1, size=4000), # D_offset / D_ref
"log_gamma_ref": np.random.normal(-5.5, 0.2, size=4000),
"beta": np.random.normal(0.8, 0.03, size=4000),
}
physics = transform_to_physics_space(samples, config)
# physics contains: D0, alpha, D_offset, gamma_dot_t0, beta
Internal reparameterization for CMC sampling.
Transforms correlated parameters to orthogonal sampling space, then converts back to physics parameters for output.
Reparameterizations (v2.23.0, reference-time): - D0, D_offset → log_D_ref, D_offset_ratio (decorrelates D0/alpha via observable) - gamma_dot_t0 → log_gamma_ref (decorrelates gamma_dot_t0/beta via observable)
- Theory:
For f(t) = A × t^α, the value at a reference time f_ref = A × t_ref^α is well-constrained by data. Sampling (f_ref, α) instead of (A, α) decorrelates them because f_ref relates to observables while α controls the shape.
t_ref = √(dt × t_max) is the geometric mean of the time range.
- D_offset reparameterization (v2.23.0):
D_offset_ratio = D_offset / D_ref is a simple linear map that handles negative D_offset (jammed/arrested systems) without singularity. The old D_offset_frac = D_offset / (D_ref + D_offset) had a pole at D_offset = -D_ref and was restricted to [0, 0.5], silently clipping negative NLSQ warm-starts. D_offset_ratio uses a Normal prior (unbounded).