summaryrefslogtreecommitdiff
path: root/src/search.c
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-10-25 10:16:16 -0700
committerScott Gasch <[email protected]>2026-10-25 10:16:16 -0700
commit3927a4cac6ec254a8e34a5e864300f75c3efc9f3 (patch)
treed34d06481bd57276b3ef50bc5513f5bd65950a74 /src/search.c
parent874ef0478078ef4eb436af7d2b68a353f61f4d70 (diff)
Make the FH% regression model the default; remove data.c's retired tables
Flips FH_USE_REGRESSION_MODEL from an opt-in safety toggle to the only behavior: fhmodel.c's quantized logistic regressions are now always used, with no build-time choice left between them and the old histogram tables. Removes g_uJointFHThousandths/g_uBetaFHThousandths and their _NNUE counterparts from data.c (4085 lines), their extern declarations from chess.h, and the now-dead _JointTablePredictedFHThousandths/_BetaTablePredictedFHThousandths lookup functions and their supporting bucket helpers (HangCpBucket/GapCpBucket/MoveNumBucket/DepthBucket/ImproveBucket/ GapBetaBucket/_ShipDepthBucket/_ShipLateBucket) from searchsup.c, along with the uRawDepthB/uRawImproveB plumbing that only existed to feed them (search.c, split.c, SearchOneMove's parameter list). Also drops the beta-side static-nullmove skip threshold's provisional- 96000 #else branch -- 99000 is now simply the default, confirmed (not provisional) by docs/REGRESSION.md's trust-audit sweep (+291 Elo over 96000 at 200 games, LOWER95=0.79). Verified: clean release build, clean DEBUG=1 TEST=1 self-test run (no asserts), and a fresh head_reference/ checkpoint (head-reference-20261025 -> 874ef04's regression-model binary) with sd10/sn5000000 solve counts on the three curated suites essentially matching the previous table-based checkpoint (70/191 vs 71/191 sd10, 93/191 vs 96/191 sn5M). Co-Authored-By: Claude Sonnet 5 <[email protected]>
Diffstat (limited to 'src/search.c')
-rw-r--r--src/search.c75
1 files changed, 24 insertions, 51 deletions
diff --git a/src/search.c b/src/search.c
index dc0fdc0..395a301 100644
--- a/src/search.c
+++ b/src/search.c
@@ -116,14 +116,12 @@ extern FLAG g_fCanSplit[MAX_PLY_PER_SEARCH];
// purely to minimize the original diff against HEAD's LMR. The move
// loop below now just calls GetLMRReduction once and uses its result.
//
-// EstimateHangingMaterialCp/HangCpBucket/GapCpBucket/MoveNumBucket/
-// DepthBucket moved there too but are no longer file-static -- the
-// measurement/collection block further below (gated on
-// fMoveIsPruneReduceEligible alone, independent of the LMR decision -- this
-// is what's still generating the next round of g_uJointFHThousandths
-// data) still needs them, so they're declared in chess.h and called
-// from here unchanged in behavior, just by their new (un-underscored)
-// public names.
+// EstimateHangingMaterialCp moved there too but is no longer
+// file-static. 2026-10-25: the bucket helpers mentioned above
+// (HangCpBucket/GapCpBucket/MoveNumBucket/DepthBucket) and the
+// data.c-table lookups they fed are gone entirely -- see
+// docs/REGRESSION.md -- replaced by fhmodel.c's quantized logistic
+// regressions.
#ifdef JOINT_EXTRA_VERIFY
@@ -449,7 +447,6 @@ Search(IN SEARCHER_THREAD_CONTEXT *ctx,
BITBOARD bbMinorAttacksSnapshot[2];
BITBOARD bbRookAttacksSnapshot[2];
FLAG fMoveIsPruneReduceEligible = FALSE;
- ULONG uRawDepthB;
#ifdef MP
FLAG fNodeSplitEligible;
#endif
@@ -637,7 +634,6 @@ Search(IN SEARCHER_THREAD_CONTEXT *ctx,
{
iImprovement = (iEval - ctx->sPlyInfo[ctx->uPly - 2].iEval);
}
- ULONG uRawImproveB = ImproveBucket(iImprovement);
SCORE iEnemyImprovement = 0;
if (ctx->uPly > 2)
{
@@ -670,8 +666,7 @@ Search(IN SEARCHER_THREAD_CONTEXT *ctx,
iBeta,
uDepth,
iImprovement,
- iEnemyImprovement,
- uRawImproveB);
+ iEnemyImprovement);
// One call, regardless of which (or neither) of the iEval>iBeta /
// iEval<=iAlpha branches below ends up applying -- FhCollectNodeEntry
@@ -694,7 +689,6 @@ Search(IN SEARCHER_THREAD_CONTEXT *ctx,
((pos->uNonPawnMaterial[WHITE] - VALUE_KING) +
(pos->uNonPawnMaterial[BLACK] - VALUE_KING)));
-#ifdef FH_USE_REGRESSION_MODEL
// HOISTED node-level precompute:
FHM_NODE_BASE sFhAlphaNodeBase = (iEval <= iAlpha) ?
FhModelAlphaNodeBaseQ16(iEval,
@@ -706,7 +700,6 @@ Search(IN SEARCHER_THREAD_CONTEXT *ctx,
(pos->uNonPawnMaterial[BLACK] - VALUE_KING)),
eNodeTypeGuessParent) :
(FHM_NODE_BASE)FHM_MATE_GATED;
-#endif
// If the Eval call above was a full eval (i.e. not lazy or super
// lazy), there are usable attack bitboards. We'll consult them
@@ -819,44 +812,32 @@ Search(IN SEARCHER_THREAD_CONTEXT *ctx,
INC(ctx->sCounters.tree.u64QuickNullMoves);
#ifndef FH_REGRESSION_COLLECTION
// A collection build must NOT take this shortcut -- it
- // would skip the real move loop based on the CURRENTLY
- // LOADED (soon-to-be-replaced) data.c table, censoring
- // exactly the population FhCollectNodeEntry/NodeExit
- // (above/below) are trying to measure. Same reasoning as
+ // would skip the real move loop before FhCollectNodeEntry/
+ // NodeExit (above/below) get a chance to log the
+ // population they're trying to measure. Same reasoning as
// the LMP disable in searchsup.c. uNodeLocalFH was already
// computed above by _RefineNodeTypeGuess via this exact
- // same _BetaTablePredictedFHThousandths lookup (same
- // depth/gap/improve bucket inputs, gated by the same
- // iEval > iBeta branch) -- reuse it instead of consulting
- // the table again.
-#ifdef FH_USE_REGRESSION_MODEL
+ // same fhmodel.c beta-regression call (same iEval > iBeta
+ // branch) -- reuse it instead of consulting the model
+ // again.
+ //
+ // 99000 is the confirmed default (docs/REGRESSION.md's
+ // trust-audit section): a direct 200-game sweep against a
+ // looser 96000 threshold settled this decisively
+ // (LOWER95=0.79, +291 Elo) -- 96000 fires this shortcut
+ // ~2x as often as the old table did on real search trees
+ // (calibration is honest at both; this was a firing-
+ // frequency gap, not an accuracy one) and cost real
+ // strength. A 99500 follow-up sweep against 99000 came
+ // back inconclusive, so there's no case yet for moving
+ // off 99000.
static ULONG uBetaSkipThreshold = 0;
if (0 == uBetaSkipThreshold)
{
CHAR *pszThresh = getenv("FH_BETA_SKIP_THRESHOLD");
- // 2026-10-24: provisional default, NOT yet confirmed by
- // match-play -- see docs/REGRESSION.md's "Static-nullmove
- // shortcut firing-rate" section. 96000 (matching the old
- // table's nominal threshold) empirically fires the
- // shortcut ~2x as often as the table did on real search
- // trees (calibration is honest at both; this is a
- // firing-frequency gap, not an accuracy one) and costs a
- // large chunk of ECM solve rate. 99000 recovers ECM
- // parity. Per DEEPER_PRUNING.md's Category A/B framework,
- // ECM is the WRONG instrument to pick this value with --
- // this is a Category B (deliberately-unsound,
- // cluster-tested) pruning decision, and only
- // match_play.py's LOWER95 gate can say whether the more
- // aggressive 96000 is actually a net real-game win
- // despite losing ECM solves. That sweep has not been run
- // yet. 99000 is chosen here only as the closest-to-known-
- // safe (table-matched) stand-in until it is.
uBetaSkipThreshold = (pszThresh && atol(pszThresh) > 0) ?
(ULONG)atol(pszThresh) : 99000;
}
-#else
- #define uBetaSkipThreshold 96000
-#endif
ULONG uBetaPredictedFHThousandths = uNodeLocalFH;
if ((uBetaPredictedFHThousandths != 0xFFFF) &&
(uBetaPredictedFHThousandths > uBetaSkipThreshold))
@@ -868,9 +849,6 @@ Search(IN SEARCHER_THREAD_CONTEXT *ctx,
iBestScore = iBeta;
goto end;
}
-#ifndef FH_USE_REGRESSION_MODEL
- #undef uBetaSkipThreshold
-#endif
#endif
}
else if (iEval <= iAlpha)
@@ -1041,7 +1019,6 @@ Search(IN SEARCHER_THREAD_CONTEXT *ctx,
}
}
uStage++;
- uRawDepthB = DepthBucket(uDepth / ONE_PLY);
#ifdef MP
// See fNodeSplitEligible's declaration comment -- same
// four conditions the move loop used to re-check on
@@ -1231,13 +1208,9 @@ Search(IN SEARCHER_THREAD_CONTEXT *ctx,
fIsLeftoverMove,
fThreat,
(iBestScore == -INFINITY_SCORE),
- uRawDepthB,
- uRawImproveB,
bbMinorAttacksSnapshot,
bbRookAttacksSnapshot,
-#ifdef FH_USE_REGRESSION_MODEL
sFhAlphaNodeBase,
-#endif
#ifdef MOVE_ORDERING_EVIDENCE_COLLECTION
fThisMoveIsCountermoveMatch,
uCMEvidenceBucket,