Skip to content

Triumviratus - 6.0

Latest

Choose a tag to compare

@Tors3 Tors3 released this 16 Jul 18:27

Triumviratus 6.0 — release notes

A strong UCI chess engine in C++ — NNUE evaluation · SPSA-tuned alpha-beta search · Syzygy
tablebases. GPLv3, by Francesco Torsello, in collaboration with Maurizio Platino.

Every number below is measured, not estimated. Full development log, footnotes and corrections:
DEVELOPMENT_6.0.md · network
training: NETWORKS.md · source:
github.com/Tors3/Triumviratus.

Headline

+52.98 ± 12.25 Elo over 5.1 — 40+0.4, 760 games, LOS 100%, nElo +108.57, SPRT [0,5] passed
(LLR 2.95). Release binary vs release binary (AVX-512), each loading its own network
(6.0 → rubicon-alea-v3, 5.1 → rubicon-alea-v1), 1 thread, 256 MB, UHO 2024 book, resign/draw
adjudication on. Score 57.6%, pentanomial [0, 47, 173, 158, 2], pairs ratio 3.40.

This gate was run on the shipped binaries, at the longest time control used anywhere in this
release, and it includes every change listed below. Roughly half of the margin is search work, half
the network.

An earlier gate measured +33.18 ± 9.86 at 20+0.2 with 64 MB on 2026-07-16. It predates eight
further changes and is superseded, not contradicted — the two are separate measurements at
different time controls and hash sizes. The incremental gains listed further down are not
additive
: each is measured against the state immediately before it, and they overlap.

Verification: bench on the shipped binary prints 205566 nodes.


What's new over 5.1

New network architecture — TRANN1

The inference machinery is Stockfish's SFNNv13 (GPLv3), extended with two input feature blocks
SFNNv13 does not have:

  • PawnPair (4560 features) — pawn-structure geometry: phalanxes, chains, doubled and isolated
    pawns, which threat features cannot see (two pawns side by side attack nothing). This feature
    design is not ours
    : it is shared with Stormphrax, Viridithas and Pawnocchio, and is credited to
    them. Our implementation and weights are our own.
  • PassedPawns (96 features) — one per passed pawn. Deciding "is this pawn passed" means combining
    the enemy pawn configuration across three files, which the king-relative HalfKAv2_hm input cannot
    express directly. This one is original to this project.

Both fold into the existing threat accumulator, so they add no new SIMD path and cost essentially
nothing at inference. The net format is consequently not SFNNv13; the reader still loads v2-format
nets (zero-filling the passed-pawn segment), so one binary can gate v2 against v3.

New network — nn-rubicon-alea-v3

Own-lineage weights, trained by the project from its own data pipeline — no Stockfish network used as
a seed. Each block is grafted onto the previous net with zero-initialised columns, so the graft is
bit-identical to its parent before training and learning adds signal instead of relearning it.

Measured net-isolated — same binary on both sides, only the network changes:

Comparison Elo LOS Games TC
v2 vs v1 — adds PawnPair, plus own self-play data +18.27 ± 9.94 99.98% 1104 20+0.2
v3 vs v2 — adds PassedPawns +6.96 ± 6.56 98.1% 2596 15+0.15
v3 vs v1 — cumulative +15.14 ± 7.69 99.99% 1998 20+0.2

Network gains shrink at longer time controls — a deeper search recovers part of what the evaluation
already knows — which is why the 15+0.15 row is not additive with the others.

Search and time management

  • SPSA mega co-tune of ~50 search parameters, tuned as a block and baked into the compiled
    defaults: +15.8 ± 10.9.
  • TMv2 time management — multiplicative, stateless: stability, eval-trend, node-count and
    predicted-move factors, SPSA-tuned. +23.8 ± 18.2. It originally shipped behind a 15 s base-time
    threshold after a −22.9 Elo measurement at 10+0.1; a later re-measurement found that cliff no
    longer reproduces at any tested time control, and the threshold was removed. TMv2 now runs whenever
    the game has an increment.
  • Two time-management safety stops were re-enabled at zero increment. The increment gate above
    also governs the allocation factors, which assume an increment pool — but it had been switching
    off two things that allocate nothing: stopping when the root has a single legal move (thinking
    longer cannot change the move) and stopping once a mate score has held for several consecutive
    iterations. Neither depends on an increment, and both can only stop earlier, never overspend.
    They were nonetheless inactive at increment zero — which is how CCRL 40/4 and CEGT are played.
    Byte-identical whenever an increment is present, so no measurement above is affected. Verified in
    the shipped binary: with one legal move and no increment it now replies in 165 ms instead of
    consuming its allocated time.
  • The unconditional check extension was removed (+8.0 ± 8.1 at 30+0.3): the search used to
    extend one ply on every check at any depth, a technique Stockfish dropped years ago. The old
    behaviour is still reachable with CheckExtDepth=30.
  • The quiescence search was rebuilt in two steps. Its move cap had been 1, so outside of check it
    examined a single move per node — a chain rather than a tree; raising it to 3 gained
    +5.21 ± 6.47. With that cap lifted, removing quiet checks from quiescence then gained
    +9.71 ± 5.99 (LOS 99.93%, SPRT bound closed over 3294 games at 20+0.2) — the largest single
    search gain in this release, and one that had been hidden: under the old cap, quiet checks competed
    with captures for the only slot available, and an earlier measurement had therefore concluded they
    were useful.
  • Continuation-history rework (+13.97 ± 6.43), killer-move staleness fix (+12.15 ± 5.97),
    en-passant hash correction, fine-grained SMP tree diversification, and a king-shield-pawn ordering
    malus ported from Reckless (+3.53 ± 3.42).
  • A final pre-release audit compared the search mechanism by mechanism against Stockfish master,
    Reckless, Stormphrax and Integral, and fixed seven latent defects — most consequentially a
    ProbCut child node that left four per-ply stacks uninitialised, so history bonuses were being
    credited to the wrong move class. Gated as a non-regression check: +2.18 ± 6.31.

New UCI options

MultiPV and go searchmoves (analysis), SyzygyProbeDepth, SyzygyProbeLimit,
Syzygy50MoveRule, and UCI_ShowWDL.

Shipped option set: Hash, Threads, MultiPV, UCI_ShowWDL, Clear Hash, Move Overhead,
EvalFile, SyzygyPath, SyzygyProbeDepth, Syzygy50MoveRule, SyzygyProbeLimit,
UCI_EngineAbout. Tuning and diagnostic parameters are hidden in release builds.


Incremental gains over 5.1

Each row is measured against the state immediately before that change — they are not additive,
they overlap. 1 thread, 64 MB, UHO 2024 book, no score-based adjudication.

Change TC Games Elo LOS
SPSA mega co-tune (~50 params) 10+0.1 1058 +15.8 ± 10.9 99.8%
TMv2 time management 20+0.2 380 +23.8 ± 18.2 99.5%
v2 network + search re-tune + large-pages NPS 20+0.2 394 +38.1 ± 17.1 100%
Unconditional check extension removed 30+0.3 1654 +8.0 ± 8.1 97.3%
Fine-grained SMP tree diversification 16+0.16 1700 +4.91 ± 7.97 88.6%
Continuation history (CorrHistCont + MathFix) 16+0.16 2862 +13.97 ± 6.43 100%
KillerReset (anti-stale killer moves) 16+0.16 3290 +12.15 ± 5.97 100%
King-shield-pawn ordering malus 12+0.12 10k+ +3.53 ± 3.42 97.85%
Seven latent-defect fixes (final audit) 8+0.08 3190 +2.18 ± 6.31 75.1%
QSMoveCap 1 → 3 (quiescence searched one move per node) 15+0.15 2868 +5.21 ± 6.47 94.3%
Quiet checks removed from quiescence 20+0.2 3294 +9.71 ± 5.99 99.93%

The last three rows, measured together: +19.51 ± 10.48, LOS 99.99%, 1016 games at 20+0.2. They
sum to about +25 individually and are worth +20 as a block — a concrete illustration of why this
table must not be added up: all three act on the same quiescence and evaluation circuit and their
gains overlap. The test reproduced the previous state on the same binary through UCI options, so
both sides shared a compiler and build flags.

One change did not survive: a correction-history-plus-ordering bundle measured +10.43 ± 5.57 at
10+0.1 and was baked, but at 20+0.2 the same bundle measured −6.89 ± 9.01. Its weakest member
(CorrMaterial, a material-keyed eval correction) was removed and ships off; the other two
members remain. Short time controls inflate this class of patch, and we would rather record the
retraction than the original number.


Files

File
Triumviratus_6.0_avx512.exe Windows x64, AVX-512 + VNNI (Zen 4, Ice Lake and newer)
Triumviratus_6.0_avx2.exe Windows x64, AVX2 + BMI2 — use this if AVX-512 is unavailable
triumviratus_linux_avx512, triumviratus_linux_avx2 Linux x64
triumviratus_android, triumviratus_android_dotprod Android arm64
nn-rubicon-alea-v3.nnue the network — provided separately, but not required: see below
SHA256SUMS.txt checksums (LF line endings)

The network is embedded in every binary — each executable runs on its own, with no .nnue file
present (verified: a binary alone in an empty directory benches 205566). The .nnue is shipped
separately only so you can override it: a file of the same name beside the executable takes
precedence, and EvalFile accepts any path. So a single executable is a complete engine.

AVX-512 is measured +6.78% faster than AVX2 at identical node counts on Zen 4. All Windows
binaries are ThinLTO + profile-guided, trained on real searches over book positions at five different
move times rather than at fixed depth.

One further +2.6% NPS comes from not computing move-ordering masks that are multiplied by a
disabled term — byte-identical, verified node-for-node over 48 million nodes and confirmed in both
measurement orders.

Credits and license

GPLv3 — see COPYING. Only the NNUE inference code derives from Stockfish; the search and the
rest of the engine are the project's own, and the shipped network was trained here. Syzygy probing
uses Fathom (MIT); the move generator descends from BBC by Maksim Korzh. Search and ordering
ideas were studied from Reckless, Caissa, Alexandria, Pawnocchio, Viridithas, Berserk, Obsidian,
Ethereal and Stormphrax. The PawnPair feature design belongs to Stormphrax, Viridithas and
Pawnocchio, not to us
— only its implementation here and the trained weights are ours. Because the
engine incorporates Stockfish's GPL code, the whole project is distributed under GPLv3 with
Stockfish's copyright notices preserved.

Testing and search tuning throughout development: Maurizio Platino, who also runs the engine
against curated hard positions at long time controls — the project's only systematic qualitative
strength testing — and contributed hardware for the long tuning runs.

Full credits: see the Credits section in the README.