solver: replace cell DFS with skyline search
Represent partial placements as column heights and branch on the narrowest local valley. This removes the board-area cell state and makes first-solution search substantially smaller for feasible orders. Expose direct-search and candidate-order benchmark controls so the skyline core can be measured independently of odd-order construction. Document the completeness argument and the 10/11 test-tier decision. Tests: Release, Debug, ASan, and UBSan CTest (10 passed each) Refs: #4
This commit was merged in pull request #23.
This commit is contained in:
+36
-9
@@ -26,26 +26,29 @@ namespace {
|
||||
double construction_seconds;
|
||||
};
|
||||
|
||||
auto solve(std::uint64_t order, bool instrument, SearchCounters &counters)
|
||||
auto solve(std::uint64_t order, bool instrument,
|
||||
CandidateOrder candidate_order, bool direct_search,
|
||||
SearchCounters &counters)
|
||||
-> TimedSolution {
|
||||
auto const predecessor_order =
|
||||
uses_odd_construction(order) ? order - 1 : order;
|
||||
!direct_search && uses_odd_construction(order) ? order - 1 : order;
|
||||
auto const search_begin = Clock::now();
|
||||
auto predecessor =
|
||||
instrument
|
||||
? search_solution_instrumented(predecessor_order, counters)
|
||||
: search_solution(predecessor_order);
|
||||
? search_solution_instrumented(predecessor_order, counters,
|
||||
candidate_order)
|
||||
: search_solution(predecessor_order, candidate_order);
|
||||
auto const search_end = Clock::now();
|
||||
|
||||
auto const construction_begin = Clock::now();
|
||||
auto result = uses_odd_construction(order)
|
||||
auto result = !direct_search && uses_odd_construction(order)
|
||||
? construct_odd_solution(order, std::move(predecessor))
|
||||
: std::move(predecessor);
|
||||
auto const construction_end = Clock::now();
|
||||
return {
|
||||
std::move(result),
|
||||
seconds(search_begin, search_end),
|
||||
uses_odd_construction(order)
|
||||
!direct_search && uses_odd_construction(order)
|
||||
? seconds(construction_begin, construction_end)
|
||||
: 0.0,
|
||||
};
|
||||
@@ -90,8 +93,9 @@ namespace {
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 3) {
|
||||
std::cerr << "usage: partridge_benchmark ORDER counters|plain\n";
|
||||
if (argc < 3 || argc > 5) {
|
||||
std::cerr << "usage: partridge_benchmark ORDER counters|plain "
|
||||
"[ascending|descending] [public|direct]\n";
|
||||
return 2;
|
||||
}
|
||||
auto const order = static_cast<std::uint64_t>(std::strtoull(argv[1], nullptr, 10));
|
||||
@@ -100,9 +104,26 @@ int main(int argc, char **argv) {
|
||||
std::cerr << "counter mode must be counters or plain\n";
|
||||
return 2;
|
||||
}
|
||||
auto const candidate_order =
|
||||
argc < 4 || std::string_view(argv[3]) == "ascending"
|
||||
? CandidateOrder::ascending
|
||||
: CandidateOrder::descending;
|
||||
if (argc >= 4 && std::string_view(argv[3]) != "ascending" &&
|
||||
std::string_view(argv[3]) != "descending") {
|
||||
std::cerr << "candidate order must be ascending or descending\n";
|
||||
return 2;
|
||||
}
|
||||
auto const direct_search =
|
||||
argc == 5 && std::string_view(argv[4]) == "direct";
|
||||
if (argc == 5 && std::string_view(argv[4]) != "public" &&
|
||||
std::string_view(argv[4]) != "direct") {
|
||||
std::cerr << "search route must be public or direct\n";
|
||||
return 2;
|
||||
}
|
||||
|
||||
SearchCounters counters;
|
||||
auto timed = solve(order, instrument, counters);
|
||||
auto timed =
|
||||
solve(order, instrument, candidate_order, direct_search, counters);
|
||||
|
||||
auto const validation_begin = Clock::now();
|
||||
auto const validation_ok = valid(order, timed.result);
|
||||
@@ -120,6 +141,12 @@ int main(int argc, char **argv) {
|
||||
<< "{\"schema_version\":1"
|
||||
<< ",\"order\":" << order
|
||||
<< ",\"instrumented\":" << boolean(instrument)
|
||||
<< ",\"candidate_order\":\""
|
||||
<< (candidate_order == CandidateOrder::ascending ? "ascending"
|
||||
: "descending")
|
||||
<< "\""
|
||||
<< ",\"search_route\":\""
|
||||
<< (direct_search ? "direct" : "public") << "\""
|
||||
<< ",\"solved\":" << boolean(!timed.result.squares().empty())
|
||||
<< ",\"valid\":" << boolean(validation_ok)
|
||||
<< ",\"timing_seconds\":{\"solve\":" << timed.search_seconds
|
||||
|
||||
Reference in New Issue
Block a user