High-performance implementation of the Normalized Advantage Function (NAF) Reinforcement Learning family with Prioritized Experience Replay (PER-NAF), Clipped Double Q-Learning (NAF2), and their combination (PER-NAF2).
- Original NAF paper (Gu et al., ICML 2016): https://arxiv.org/abs/1603.00748
- Prioritized Experience Replay (Schaul et al., ICLR 2016): https://arxiv.org/abs/1511.05952
- PRAB 2020 CERN Accelerator Control paper (V. Kain, S. Hirlaender et al.): https://journals.aps.org/prab/abstract/10.1103/PhysRevAccelBeams.23.124801
- FERMI FEL NAF2 & Bayesian Ensembling paper (S. Hirlaender, N. Bruchon, 2020): https://arxiv.org/abs/2012.09737
- Originally based on: https://github.com/carpedm20/NAF-tensorflow/ and OpenAI Baselines
replay_buffer.py
Thanks OpenAI and Kim!
- Normalize the state and action space as well as the reward is a good practice
- Visualise as much as possible to get an intuition about the method as possible bugs
- If it does not make sense it is a bug with very high probability
The codebase has been completely refactored and accelerated using a hybrid JAX XLA + Numba LLVM + PyTorch 2.x stack:
-
Numba
@njit(fastmath=True)BinarySumTree&MinTree(pernaf/pernaf/buffers.py):- Replaces Python list-of-tuples and recursive
SegmentTreemethods with contiguousfloat32ring buffers and LLVM-compiled tree traversal (34.6x faster prioritized batch sampling + priority updates; 6.1x faster transition storage). - Automatic empirical priority scale calibration (
_calibrated_scale) and mini-batch max-weight normalization ($w_i / \max_{j \in B} w_j \in (0, 1]$ ) so environments with small reward scales ($|r| \ll 1$ ) never suffer from priority inversion or step-size shrinkage.
- Replaces Python list-of-tuples and recursive
-
Compiled JAX XLA
@jax.jit+ Optax Updater (pernaf/pernaf/jax_naf.py):- Fuses the forward pass, Cholesky advantage projection
$A(s,a) = -\frac{1}{2}|L(s)^T(a - \mu(s))|_2^2$ , Huber/MSE TD loss, backward pass, global norm clipping,optax.adamstep, and Polyak target update into a single compiled XLA kernel (10.6x faster end-to-end updates than the original loop-based PyTorch implementation).
- Fuses the forward pass, Cholesky advantage projection
-
Zero-Loop Vectorized PyTorch
QNetwork(pernaf/pernaf/networks.py):- Eliminates the nested Python
for i in range(act_dim): for j in range(i):loop and$O(B d_a^3)$ P = L @ L^Tmatrix multiplication via precomputed lower-triangular gather indices (index_select) in$O(B d_a^2)$ . - Bounds the log-Cholesky diagonal with
tanhto preventexp(l_entries)overflow and provides fast pathsforward_mu(x),forward_v(x), andforward_q(x, a).
- Eliminates the nested Python
-
Automatic Affine Action & Observation Scaling (
pernaf/pernaf/agent.py):- Automatically maps
[-1, 1]network outputs to arbitrarygymnasium.spaces.Boxbounds (e.g.[-2, 2]onPendulum-v1) and separates true MDP termination (terminated) from time-limit or aperture truncation (truncated).
- Automatically maps
-
Install dependencies:
pip install -r requirements.txt
-
Install the package in editable mode:
pip install -e pernaf
Models the 10 horizontal/vertical dipole correctors (MCA) and 10 beam position monitors (BPM) from MAD-X Twiss optics (InfrastructuralData/electron_tt43.out), as studied in Phys. Rev. Accel. Beams 23, 124801 (2020), Sec. III & VI.
Models the 16-corrector / 16-BPM trajectory steering problem in the CERN Linac4 (L4T) transfer line using the measured 16x16 response matrix (InfrastructuralData/linac4_rm.pcl) with configurable nonlinear perturbation and shot-to-shot noise (PRAB 2020, Sec. IV).
python3 train_pendulum_benchmark.py
python3 benchmark_comparison.pyRuns the complete 2x2 factorial ablation (NAF, NAF2, PER-NAF, PER-NAF2) across BPM sensor noise levels, magnet nonlinearities, and degrees of freedom (3 to 16 DOF):
python3 run_critical_experiments.pyTo launch a 50-seed factorial sweep across all environments and
sbatch scc/submit_pernaf_scc.slurm
# After array completion, aggregate into summary CSVs and ANOVA tables:
python3 scc/run_cluster_job.py --aggregate --out-dir scc/outputsNAF enables Q-learning in continuous action spaces by decomposing the Q-function into a state-value term
-
Analytic Greedy Action:
$\arg\max_a Q(s,a) = \mu(s)$ , eliminating the need for a separate actor network.
Incorporates two independent NAF networks
Samples transitions from a binary SumTree with probability proportional to TD error:
Combines Clipped Double Q-Learning with Prioritized Experience Replay using the joint TD error
- Sample-efficient reinforcement learning for CERN accelerator control Verena Kain, Simon Hirlaender, Brennan Goddard, Francesco Maria Velotti, Giovanni Zevi Della Porta, Niky Bruchon, and Gianluca Valentino. Phys. Rev. Accel. Beams 23, 124801 (2020) — https://journals.aps.org/prab/abstract/10.1103/PhysRevAccelBeams.23.124801
- Model-free and Bayesian Ensembling Model-based Deep Reinforcement Learning for Particle Accelerator Control Demonstrated on the FERMI FEL Simon Hirlaender, Niky Bruchon (2020) — https://arxiv.org/abs/2012.09737






