diff --git a/.gitignore b/.gitignore index 02e7aa9d..6f8887db 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,6 @@ build*/ *.epd # Other common folders books/* + +# Spsa output for script usage +spsa_out*.txt \ No newline at end of file diff --git a/scripts/spsa_out_replace.py b/scripts/spsa_out_replace.py new file mode 100644 index 00000000..7955b0a0 --- /dev/null +++ b/scripts/spsa_out_replace.py @@ -0,0 +1,72 @@ +import re + +# Change config as needed +VALUES_FILE = "spsa_out_140k_stc.txt" +HEADER_FILE = "src/tuned.hpp" +OUTPUT_FILE = "src/tuned.hpp" + +PREFIX_TO_STRIP = "tune_" + +def load_values(path): + values = {} + with open(path, "r") as f: + for line in f: + line = line.strip() + if not line or line.startswith("#"): + continue + + name, value = line.split(",", 1) + name = name.strip() + value = value.strip() + + if name.startswith(PREFIX_TO_STRIP): + name = name[len(PREFIX_TO_STRIP):] + + values[name] = value + + return values + + +def replace_macro_values(text, values): + macro_re = re.compile( + r""" + (?PTUNE|NO_TUNE) # macro name + \( + (?P\s*[\w\d_]+)\s*, # parameter name + (?P\s*[^,]+)\s*, # value to replace (2nd arg) + """, + re.VERBOSE, + ) + + def repl(match): + name = match.group("name").strip() + old_value = match.group("value") + + if name not in values: + return match.group(0) + + new_value = values[name] + + return ( + f"{match.group('macro')}(" + f"{match.group('name')}, " + f"{new_value}," + ) + + return macro_re.sub(repl, text) + + +def main(): + values = load_values(VALUES_FILE) + + with open(HEADER_FILE, "r") as f: + original = f.read() + + updated = replace_macro_values(original, values) + + with open(OUTPUT_FILE, "w") as f: + f.write(updated) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/src/search.cpp b/src/search.cpp index f03bda9d..6f122f03 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -27,12 +27,18 @@ static Value mated_in(i32 ply) { return -VALUE_MATED + ply; } -static constexpr i32 stat_bonus(Depth bonus_depth) { +static i32 stat_bonus(Depth bonus_depth) { return std::min(tuned::stat_bonus_max, tuned::stat_bonus_quad * bonus_depth * bonus_depth + tuned::stat_bonus_lin * bonus_depth - tuned::stat_bonus_sub); } +static i32 stat_malus(Depth malus_depth) { + return std::min(tuned::stat_malus_max, tuned::stat_malus_quad * malus_depth * malus_depth + + tuned::stat_malus_lin * malus_depth + - tuned::stat_malus_sub); +} + std::ostream& operator<<(std::ostream& os, const PV& pv) { for (Move m : pv.m_pv) { os << m << ' '; @@ -765,7 +771,7 @@ Value Worker::search( ply + 1, !cutnode); if (quiet && (value <= alpha || value >= beta)) { m_td.history.update_cont_hist(pos, m, ply, ss, - value <= alpha ? -stat_bonus(new_depth) + value <= alpha ? -stat_malus(new_depth) : stat_bonus(new_depth)); } } @@ -822,18 +828,19 @@ Value Worker::search( if (best_value >= beta) { i32 bonus_depth = depth + (best_value >= beta + 100); const i32 bonus = stat_bonus(bonus_depth); + const i32 malus = stat_malus(bonus_depth); if (quiet_move(best_move)) { ss->killer = best_move; m_td.history.update_quiet_stats(pos, best_move, ply, ss, bonus); for (Move quiet : quiets_played) { - m_td.history.update_quiet_stats(pos, quiet, ply, ss, -bonus); + m_td.history.update_quiet_stats(pos, quiet, ply, ss, -malus); } } else { m_td.history.update_noisy_stats(pos, best_move, bonus); } for (Move noisy : noisies_played) { - m_td.history.update_noisy_stats(pos, noisy, -bonus); + m_td.history.update_noisy_stats(pos, noisy, -malus); } } diff --git a/src/tuned.hpp b/src/tuned.hpp index bc4d70ab..2107b9c0 100644 --- a/src/tuned.hpp +++ b/src/tuned.hpp @@ -12,7 +12,7 @@ namespace Clockwork::tuned { #define CLOCKWORK_TUNABLES(TUNE, NO_TUNE) \ \ /* RFP Values */ \ - TUNE(rfp_margin, 147, 40, 160, 4, 0.002) \ + TUNE(rfp_margin, 144, 40, 160, 4, 0.002) \ NO_TUNE(rfp_depth, 7, 4, 10, .5, 0.002) \ \ /* NMP Values */ \ @@ -20,84 +20,90 @@ namespace Clockwork::tuned { NO_TUNE(nmp_base_r, 3, 1, 10, .5, 0.002) \ NO_TUNE(nmp_verif_min_depth, 14, 1, 40, .5, 0.002) \ TUNE(nmp_beta_margin, 30, 10, 60, 3, 0.002) \ - TUNE(nmp_beta_diff, 400, 200, 800, 38, 0.002) \ + TUNE(nmp_beta_diff, 428, 200, 800, 38, 0.002) \ \ /* ProbCut Values */ \ - TUNE(probcut_margin, 300, 100, 500, 10, 0.002) \ - TUNE(probcut_see, 100, 0, 200, 10, 0.002) \ + TUNE(probcut_margin, 332, 100, 500, 10, 0.002) \ + TUNE(probcut_see, 108, 0, 200, 10, 0.002) \ NO_TUNE(probcut_min_depth, 5, 1, 20, 0.5, 0.002) \ \ /* SEE Values */ \ - TUNE(quiesce_see_threshold, 0, -1000, 100, 20, 0.002) \ - TUNE(movepicker_see_capthist_divisor, 48, 16, 192, 10, 0.002) \ + TUNE(quiesce_see_threshold, 18, -1000, 100, 20, 0.002) \ + TUNE(movepicker_see_capthist_divisor, 54, 16, 192, 10, 0.002) \ \ /* Stat Bonus */ \ - TUNE(stat_bonus_max, 1896, 948, 3792, 142, 0.002) \ + TUNE(stat_bonus_max, 1828, 948, 3792, 142, 0.002) \ TUNE(stat_bonus_quad, 4, 2, 8, .5, 0.002) \ - TUNE(stat_bonus_lin, 120, 60, 240, 9, 0.002) \ - TUNE(stat_bonus_sub, 120, 60, 240, 9, 0.002) \ + TUNE(stat_bonus_lin, 118, 60, 240, 9, 0.002) \ + TUNE(stat_bonus_sub, 123, 60, 240, 9, 0.002) \ + \ + /* Stat Malus */ \ + TUNE(stat_malus_max, 1627, 948, 3792, 142, 0.002) \ + TUNE(stat_malus_quad, 4, 2, 8, .5, 0.002) \ + TUNE(stat_malus_lin, 137, 60, 240, 9, 0.002) \ + TUNE(stat_malus_sub, 111, 60, 240, 9, 0.002) \ \ /* Search Params */ \ - TUNE(asp_window_delta, 50, 25, 100, 4, 0.002) \ + TUNE(asp_window_delta, 32, 25, 100, 4, 0.002) \ NO_TUNE(razor_depth, 7, 1, 20, 0.5, 0.002) \ - TUNE(razor_margin, 707, 353, 1414, 53, 0.002) \ + TUNE(razor_margin, 681, 353, 1414, 53, 0.002) \ NO_TUNE(lmp_depth_mult, 3, 1, 20, 0.5, 0.002) \ \ /* Futility Pruning */ \ - TUNE(ffp_margin_base, 500, 250, 1000, 38, 0.002) \ - TUNE(ffp_margin_mult, 100, 50, 200, 8, 0.002) \ - TUNE(ffp_hist_div, 32, 16, 64, 3, 0.002) \ + TUNE(ffp_margin_base, 437, 250, 1000, 38, 0.002) \ + TUNE(ffp_margin_mult, 89, 50, 200, 8, 0.002) \ + TUNE(ffp_hist_div, 25, 16, 64, 3, 0.002) \ NO_TUNE(ffp_depth, 8, 1, 20, 0.5, 0.002) \ \ /* Quiet History Pruning */ \ NO_TUNE(qhp_depth, 4, 1, 20, 0.5, 0.002) \ - TUNE(qhp_threshold, -2048, -4096, -1024, 154, 0.002) \ + TUNE(qhp_threshold, -2183, -4096, -1024, 154, 0.002) \ \ /* SEE PVS */ \ - TUNE(see_pvs_quiet, -67, -134, -33, 5, 0.002) \ - TUNE(see_pvs_noisy_quad, -22, -44, -11, 2, 0.002) \ - TUNE(see_pvs_hist_mult, 20, 10, 40, 2, 0.002) \ + TUNE(see_pvs_quiet, -65, -134, -33, 5, 0.002) \ + TUNE(see_pvs_noisy_quad, -20, -44, -11, 2, 0.002) \ + TUNE(see_pvs_hist_mult, 16, 10, 40, 2, 0.002) \ \ /* Singular Extensions */ \ NO_TUNE(sing_min_depth, 6, 1, 20, 0.5, 0.002) \ NO_TUNE(sing_depth_margin, 3, 1, 20, 0.5, 0.002) \ TUNE(sing_beta_margin, 5, 2, 10, 1, 0.002) \ TUNE(dext_margin, 40, 20, 80, 3, 0.002) \ - TUNE(dext_hist_div, 512, 256, 1024, 39, 0.002) \ - TUNE(triext_margin, 120, 60, 240, 9, 0.002) \ - TUNE(triext_hist_div, 512, 256, 1024, 39, 0.002) \ + TUNE(dext_hist_div, 491, 256, 1024, 39, 0.002) \ + TUNE(triext_margin, 126, 60, 240, 9, 0.002) \ + TUNE(triext_hist_div, 573, 256, 1024, 39, 0.002) \ \ /* LMR */ \ - TUNE(lmr_quiet_base, 788, 394, 1576, 59, 0.002) \ - TUNE(lmr_quiet_div, 208, 104, 416, 16, 0.002) \ - TUNE(lmr_noisy_base, 256, 128, 512, 20, 0.002) \ - TUNE(lmr_noisy_div, 197, 98, 394, 15, 0.002) \ - TUNE(lmr_pv_node_red, 1024, 512, 2048, 77, 0.002) \ - TUNE(lmr_alpha_raise_red, 512, 256, 1024, 38, 0.002) \ - TUNE(lmr_not_improving_red, 512, 256, 1024, 38, 0.002) \ - TUNE(lmr_in_check_red, 1024, 512, 2048, 77, 0.002) \ - TUNE(lmr_cutnode_red, 1024, 512, 2048, 77, 0.002) \ - TUNE(lmr_no_tt_red, 1024, 512, 2048, 77, 0.002) \ - TUNE(lmr_ttpv_red, 1024, 512, 2048, 77, 0.002) \ - TUNE(lmr_tt_capture_red, 1024, 512, 2048, 77, 0.002) \ - TUNE(lmr_fail_high_red, 1024, 512, 2048, 77, 0.002) \ - TUNE(lmr_quiet_hist_base, 1024, 512, 2048, 77, 0.002) \ - TUNE(lmr_hist_div, 8, 4, 16, 2, 0.002) \ - TUNE(lmr_fut_red_base, 500, 250, 1000, 38, 0.002) \ - TUNE(lmr_fut_red_mult, 100, 50, 200, 8, 0.002) \ - TUNE(lmr_fut_red, 1024, 512, 2048, 77, 0.002) \ - TUNE(lmr_max_red, 3072, 1536, 6144, 231, 0.002) \ + TUNE(lmr_quiet_base, 638, 394, 1576, 59, 0.002) \ + TUNE(lmr_quiet_div, 164, 104, 416, 16, 0.002) \ + TUNE(lmr_noisy_base, 258, 128, 512, 20, 0.002) \ + TUNE(lmr_noisy_div, 193, 98, 394, 15, 0.002) \ + TUNE(lmr_pv_node_red, 1207, 512, 2048, 77, 0.002) \ + TUNE(lmr_alpha_raise_red, 514, 256, 1024, 38, 0.002) \ + TUNE(lmr_not_improving_red, 520, 256, 1024, 38, 0.002) \ + TUNE(lmr_in_check_red, 1021, 512, 2048, 77, 0.002) \ + TUNE(lmr_cutnode_red, 1087, 512, 2048, 77, 0.002) \ + TUNE(lmr_no_tt_red, 997, 512, 2048, 77, 0.002) \ + TUNE(lmr_ttpv_red, 1097, 512, 2048, 77, 0.002) \ + TUNE(lmr_tt_capture_red, 968, 512, 2048, 77, 0.002) \ + TUNE(lmr_fail_high_red, 980, 512, 2048, 77, 0.002) \ + TUNE(lmr_quiet_hist_base, 940, 512, 2048, 77, 0.002) \ + TUNE(lmr_hist_div, 12, 4, 16, 2, 0.002) \ + TUNE(lmr_fut_red_base, 562, 250, 1000, 38, 0.002) \ + TUNE(lmr_fut_red_mult, 99, 50, 200, 8, 0.002) \ + TUNE(lmr_fut_red, 864, 512, 2048, 77, 0.002) \ + TUNE(lmr_max_red, 2985, 1536, 6144, 231, 0.002) \ \ /* TIME MANAGEMENT */ \ - TUNE(time_hard_limit, 256, 128, 512, 19, 0.002) \ - TUNE(time_soft_limit, 51, 25, 100, 3, 0.002) \ - TUNE(time_soft_increment, 512, 256, 1024, 38, 0.002) \ - TUNE(nodetm_min_factor, 512, 256, 1024, 38, 0.002) \ - TUNE(nodetm_avg_factor, 2048, 1024, 4096, 153, 0.002) \ - TUNE(nodetm_frac_factor, 1895, 948, 3792, 142, 0.002) \ - TUNE(d1plexity_base, 788, 394, 1576, 59, 0.002) \ - TUNE(d1plexity_max_complexity, 200, 100, 400, 15, 0.002) \ - TUNE(d1plexity_divisor, 386, 193, 772, 29, 0.002) \ + NO_TUNE(time_hard_limit, 256, 128, 512, 19, 0.002) \ + NO_TUNE(time_soft_limit, 51, 25, 100, 3, 0.002) \ + NO_TUNE(time_soft_increment, 512, 256, 1024, 38, 0.002) \ + NO_TUNE(nodetm_min_factor, 512, 256, 1024, 38, 0.002) \ + NO_TUNE(nodetm_avg_factor, 2048, 1024, 4096, 153, 0.002) \ + NO_TUNE(nodetm_frac_factor, 1895, 948, 3792, 142, 0.002) \ + NO_TUNE(d1plexity_base, 788, 394, 1576, 59, 0.002) \ + NO_TUNE(d1plexity_max_complexity, 200, 100, 400, 15, 0.002) \ + NO_TUNE(d1plexity_divisor, 386, 193, 772, 29, 0.002) \ \ /* End of Tunables */