Repository navigation
Klondike: weight cleanup and a Draw 3 stock-alignment term in the IDA* heuristic - #4
Merged
Merged
Conversation
Remove DEADLOCK_PENALTY (unused) and the three secondary priorities that only ever applied as a constant offset inside their own ordering bucket: PRIORITY_EMPTY_COL_BONUS, PRIORITY_STOCK_ADVANCE and PRIORITY_STOCK_RECYCLE. The successor order is unchanged; a new test pins the ordering keys of the single-kind buckets. Rewrite the heuristic comments: heuristic_cost is informative, not admissible, and the weights may be tuned for search speed. Clamp the heuristic at zero, fix the HIDDEN_DEPTH_DIVISOR formula comment and drop two redundant casts.
…ion count The adoption threshold was 3% of |start_score| clamped per phase. Since progress_score is dominated by 1300 points per foundation card, that was ~39 points per card, and only one end of each clamp was ever reached (150 early, 1000 mid, 500 late). Replace ADOPT_RELATIVE_PCT and the clamp pairs with an explicit slope (ADOPT_PER_FOUNDATION_CARD) and the three reachable bounds, computed by CheckpointPolicy::adopt_threshold(fc). The start score no longer affects the threshold; the non-foundation signals it carried shifted it by at most ~150 points mid-game. Tests pin the threshold at each phase edge.
BoardEval::from_board_fast now counts the next foundation cards sitting in the remaining stock at a position the current pass skips: offset from the pile card not a multiple of the draw size, last card excluded since it is always exposed at the end of the pass. heuristic_cost adds MISALIGNED_TARGET_COST = 2 per such card while hidden cards remain. The scan is at most 24 cards and only runs for draw > 1, so Draw 1 is unchanged by construction. First unseeded Draw 3 run: 75.20% (was 70.00%), with more games solved in the first chunk, but average duration rose 31%. A seeded pair with the cost at 0 vs 2 is still needed to isolate the term; results and caveats are in docs/results/KlondikeDraw3_results_20261014_220504.csv.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three commits on the Klondike weights: two behaviour-preserving refactors that make
weights.rssay what the solver actually does, and one new heuristic term for Draw 3 that charges the next foundation cards the current stock pass cannot reach. No change to the FFI surface or to Draw 1 results.main(64f4c9a), 500 games unseeded (12 Oct)MISALIGNED_TARGET_COSTin the Draw 3 heuristicChanges
Drop inert weights and stale heuristic comments (d4f1197)
A review of
weights.rsagainst its two consumers found constants that could not change any result:DEADLOCK_PENALTYhad no references.PRIORITY_EMPTY_COL_BONUS,PRIORITY_STOCK_ADVANCEandPRIORITY_STOCK_RECYCLEwere constant offsets inside a bucket ofsuccessor_bucketthat holds only moves of their own kind, so they never reordered anything. Pure stock advances are never generated since the stock macros, and there is at most one recycle per node.PRIORITY_SAFE_FOUNDATIONstays: a safe foundation move that reveals a card competes inside the reveal bucket.local_secondary_prioritylost those branches and itsfrom_boardparameter. A new test,single_kind_buckets_carry_no_base_secondary_priority, pins the ordering keys of an emptying move and a recycle.The heuristic comments claimed admissibility. They were wrong: the depth, blocked-King, waste and imbalance terms all overestimate the remaining move count, and the solver gave up optimality long ago with checkpoints and node limits. The comments now say the heuristic is informative, which removes a false constraint on tuning.
heuristic_costis clamped at zero (it could go negative with four empty columns and an almost complete foundation), theHIDDEN_DEPTH_DIVISORformula comment matches the code, and two redundant casts are gone.Checkpoint adoption thresholds by foundation count (516656b)
is_adoptablerequired a progress delta of 3% of|start_score|, clamped per phase. Sinceprogress_scoreis dominated by 1300 points per foundation card, that was about 39 points per card, and only one end of each clamp was ever reached: 150 early, 1000 mid, 500 late.ADOPT_RELATIVE_PCTand the three clamp pairs are replaced byADOPT_PER_FOUNDATION_CARD = 39,ADOPT_EARLY_MIN = 150,ADOPT_MID_MAX = 1000andADOPT_LATE = 500, computed byCheckpointPolicy::adopt_threshold(fc). The start score no longer affects the threshold. The only behavioural difference is that the non-foundation signals in the score (face-up, hidden, autoplay bonus) no longer shift the threshold, by at most ~150 points mid-game. Tests pin the threshold at every phase edge.This makes the threshold slope and the 1000 → 500 drop at 30 foundation cards explicit and tunable; neither was visible before.
Skipped stock targets in the Draw 3 heuristic (bb896ae)
Draw 3 shared every weight with Draw 1 except the node-limit table. The one Draw 3-specific signal,
STOCK_MISALIGNED_TARGET_PENALTY, only enteredprogress_score(checkpoint choice), neverheuristic_cost(IDA* pruning). The search pruned a state whose next target was reachable this pass exactly like one that needed a full recycle.BoardEval::from_board_fastnow countsmisaligned_targets: next foundation cards in the remaining stock whose offset from the pile card is not a multiple of the draw size, excluding the last stock card, which is always exposed at the end of a pass.heuristic_costaddsMISALIGNED_TARGET_COST = 2per such card while hidden cards remain. The scan is at most 24 cards and runs only for draw > 1, so Draw 1 is unchanged by construction. Three tests cover the count against draw 1, the alignment shift whenstock_indexchanges, and the endgame branch, which ignores the term.First 500-game run: 75.20% (was 70.00%), with 251 games solved without a checkpoint (211 before) and 0.35 checkpoints per won game (0.43 before). Notes and caveats are in
docs/results/KlondikeDraw3_results_20261014_220504.csv.Open issues
MISALIGNED_TARGET_COSTat 0 vs 2 on this build isolates the term from its time cost.MISALIGNED_TARGET_COSTin {1, 3}; counting waste targets misaligned for the next pass; applying the term in the endgame branch, where a skipped target is what blocks a Draw 3 win.Testing
cargo testinsolver-core-rs. Benchmarks viasolverlab-tui --headless --game klondike3 --sims 500 --parallel 10.