solver: prune insufficient valley capacity

A selected valley cannot admit a square wider than itself until it reaches the lower neighbouring rim. Reject states whose remaining narrow-square area cannot fill that strip, including width-one and width-two gaps.

Keep an unpruned benchmark mode and dedicated counters so the rule remains independently measurable. Record the soundness argument and the measured default-on improvement.

Tests: Debug CTest (12 passed)

Tests: ASan+UBSan CTest (12 passed)

Refs: #10
This commit was merged in pull request #26.
This commit is contained in:
Codex instance
2026-07-31 08:11:30 +01:00
parent f37e08768d
commit e27427d231
6 changed files with 234 additions and 26 deletions
+23 -5
View File
@@ -29,6 +29,7 @@ namespace {
auto solve(std::uint64_t order, bool instrument,
SearchPolicy policy, bool direct_search,
SymmetryBreaking symmetry,
Pruning pruning,
SearchCounters &counters)
-> TimedSolution {
auto const predecessor_order =
@@ -37,8 +38,8 @@ namespace {
auto predecessor =
instrument
? search_solution_instrumented(predecessor_order, counters,
policy, symmetry)
: search_solution(predecessor_order, policy, symmetry);
policy, symmetry, pruning)
: search_solution(predecessor_order, policy, symmetry, pruning);
auto const search_end = Clock::now();
auto const construction_begin = Clock::now();
@@ -94,10 +95,10 @@ namespace {
}
int main(int argc, char **argv) {
if (argc < 3 || argc > 6) {
if (argc < 3 || argc > 7) {
std::cerr << "usage: partridge_benchmark ORDER counters|plain "
"[ascending|descending|best-fit] [public|direct] "
"[d4|none]\n";
"[d4|none] [valley-capacity|none]\n";
return 2;
}
auto const order = static_cast<std::uint64_t>(std::strtoull(argv[1], nullptr, 10));
@@ -134,10 +135,20 @@ int main(int argc, char **argv) {
std::cerr << "symmetry mode must be d4 or none\n";
return 2;
}
auto const pruning =
argc < 7 || std::string_view(argv[6]) == "valley-capacity"
? Pruning::valley_capacity
: Pruning::disabled;
if (argc == 7 && std::string_view(argv[6]) != "valley-capacity" &&
std::string_view(argv[6]) != "none") {
std::cerr << "pruning mode must be valley-capacity or none\n";
return 2;
}
SearchCounters counters;
auto timed =
solve(order, instrument, policy, direct_search, symmetry, counters);
solve(order, instrument, policy, direct_search, symmetry, pruning,
counters);
auto const validation_begin = Clock::now();
auto const validation_ok = valid(order, timed.result);
@@ -165,6 +176,9 @@ int main(int argc, char **argv) {
<< ",\"symmetry_breaking\":\""
<< (symmetry == SymmetryBreaking::d4_unit_square ? "d4" : "none")
<< "\""
<< ",\"pruning\":\""
<< (pruning == Pruning::valley_capacity ? "valley-capacity" : "none")
<< "\""
<< ",\"solved\":" << boolean(!timed.result.squares().empty())
<< ",\"valid\":" << boolean(validation_ok)
<< ",\"timing_seconds\":{\"solve\":" << timed.search_seconds
@@ -177,6 +191,10 @@ int main(int argc, char **argv) {
<< ",\"backtracks\":" << counters.backtracks
<< ",\"prune_checks\":" << counters.prune_checks
<< ",\"prune_hits\":" << counters.prune_hits
<< ",\"valley_capacity_checks\":"
<< counters.valley_capacity_checks
<< ",\"valley_capacity_prunes\":"
<< counters.valley_capacity_prunes
<< ",\"generated_tasks\":" << counters.generated_tasks
<< ",\"completed_tasks\":" << counters.completed_tasks << "}}\n";
return validation_ok ? 0 : 1;