solver: add optional component-area pruning
Full-height skyline columns partition the remaining board. Add sound gcd and bounded subset-sum checks for the resulting component areas, with boundary-event and periodic benchmark schedules. Keep the rules disabled by default because their small tree reductions do not recover their measured cost. Record the rejected default and scheduling evidence so it can be revisited only with new data. Tests: Debug CTest (14 passed) Tests: ASan+UBSan CTest (14 passed) Refs: #13
This commit was merged in pull request #28.
This commit is contained in:
+62
-7
@@ -30,6 +30,8 @@ namespace {
|
||||
SearchPolicy policy, bool direct_search,
|
||||
SymmetryBreaking symmetry,
|
||||
Pruning pruning,
|
||||
ComponentPruning component_pruning,
|
||||
ComponentSchedule component_schedule,
|
||||
SearchCounters &counters)
|
||||
-> TimedSolution {
|
||||
auto const predecessor_order =
|
||||
@@ -38,8 +40,11 @@ namespace {
|
||||
auto predecessor =
|
||||
instrument
|
||||
? search_solution_instrumented(predecessor_order, counters,
|
||||
policy, symmetry, pruning)
|
||||
: search_solution(predecessor_order, policy, symmetry, pruning);
|
||||
policy, symmetry, pruning,
|
||||
component_pruning,
|
||||
component_schedule)
|
||||
: search_solution(predecessor_order, policy, symmetry, pruning,
|
||||
component_pruning, component_schedule);
|
||||
auto const search_end = Clock::now();
|
||||
|
||||
auto const construction_begin = Clock::now();
|
||||
@@ -103,13 +108,30 @@ namespace {
|
||||
assert(false);
|
||||
return "none";
|
||||
}
|
||||
|
||||
auto component_pruning_name(ComponentPruning const pruning) -> char const * {
|
||||
switch (pruning) {
|
||||
case ComponentPruning::disabled: return "none";
|
||||
case ComponentPruning::gcd: return "gcd";
|
||||
case ComponentPruning::subset_sum: return "subset-sum";
|
||||
}
|
||||
assert(false);
|
||||
return "none";
|
||||
}
|
||||
|
||||
auto component_schedule_name(ComponentSchedule const schedule)
|
||||
-> char const * {
|
||||
return schedule == ComponentSchedule::boundary ? "boundary"
|
||||
: "periodic-8";
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 3 || argc > 7) {
|
||||
if (argc < 3 || argc > 9) {
|
||||
std::cerr << "usage: partridge_benchmark ORDER counters|plain "
|
||||
"[ascending|descending|best-fit] [public|direct] "
|
||||
"[d4|none] [all|valley-capacity|large-square|none]\n";
|
||||
"[d4|none] [all|valley-capacity|large-square|none] "
|
||||
"[subset-sum|gcd|none] [boundary|periodic-8]\n";
|
||||
return 2;
|
||||
}
|
||||
auto const order = static_cast<std::uint64_t>(std::strtoull(argv[1], nullptr, 10));
|
||||
@@ -141,7 +163,7 @@ int main(int argc, char **argv) {
|
||||
argc < 6 || std::string_view(argv[5]) == "d4"
|
||||
? SymmetryBreaking::d4_unit_square
|
||||
: SymmetryBreaking::disabled;
|
||||
if (argc == 6 && std::string_view(argv[5]) != "d4" &&
|
||||
if (argc >= 6 && std::string_view(argv[5]) != "d4" &&
|
||||
std::string_view(argv[5]) != "none") {
|
||||
std::cerr << "symmetry mode must be d4 or none\n";
|
||||
return 2;
|
||||
@@ -154,7 +176,7 @@ int main(int argc, char **argv) {
|
||||
: std::string_view(argv[6]) == "large-square"
|
||||
? Pruning::large_square
|
||||
: Pruning::disabled;
|
||||
if (argc == 7 && std::string_view(argv[6]) != "all" &&
|
||||
if (argc >= 7 && std::string_view(argv[6]) != "all" &&
|
||||
std::string_view(argv[6]) != "valley-capacity" &&
|
||||
std::string_view(argv[6]) != "large-square" &&
|
||||
std::string_view(argv[6]) != "none") {
|
||||
@@ -162,11 +184,32 @@ int main(int argc, char **argv) {
|
||||
"large-square, or none\n";
|
||||
return 2;
|
||||
}
|
||||
auto const component_pruning =
|
||||
argc < 8 || std::string_view(argv[7]) == "none"
|
||||
? ComponentPruning::disabled
|
||||
: std::string_view(argv[7]) == "gcd"
|
||||
? ComponentPruning::gcd
|
||||
: ComponentPruning::subset_sum;
|
||||
if (argc >= 8 && std::string_view(argv[7]) != "subset-sum" &&
|
||||
std::string_view(argv[7]) != "gcd" &&
|
||||
std::string_view(argv[7]) != "none") {
|
||||
std::cerr << "component pruning mode must be subset-sum, gcd, or none\n";
|
||||
return 2;
|
||||
}
|
||||
auto const component_schedule =
|
||||
argc < 9 || std::string_view(argv[8]) == "boundary"
|
||||
? ComponentSchedule::boundary
|
||||
: ComponentSchedule::periodic_eight;
|
||||
if (argc == 9 && std::string_view(argv[8]) != "boundary" &&
|
||||
std::string_view(argv[8]) != "periodic-8") {
|
||||
std::cerr << "component schedule must be boundary or periodic-8\n";
|
||||
return 2;
|
||||
}
|
||||
|
||||
SearchCounters counters;
|
||||
auto timed =
|
||||
solve(order, instrument, policy, direct_search, symmetry, pruning,
|
||||
counters);
|
||||
component_pruning, component_schedule, counters);
|
||||
|
||||
auto const validation_begin = Clock::now();
|
||||
auto const validation_ok = valid(order, timed.result);
|
||||
@@ -196,6 +239,10 @@ int main(int argc, char **argv) {
|
||||
<< "\""
|
||||
<< ",\"pruning\":\""
|
||||
<< pruning_name(pruning) << "\""
|
||||
<< ",\"component_pruning\":\""
|
||||
<< component_pruning_name(component_pruning) << "\""
|
||||
<< ",\"component_schedule\":\""
|
||||
<< component_schedule_name(component_schedule) << "\""
|
||||
<< ",\"solved\":" << boolean(!timed.result.squares().empty())
|
||||
<< ",\"valid\":" << boolean(validation_ok)
|
||||
<< ",\"timing_seconds\":{\"solve\":" << timed.search_seconds
|
||||
@@ -216,6 +263,14 @@ int main(int argc, char **argv) {
|
||||
<< counters.large_square_checks
|
||||
<< ",\"large_square_prunes\":"
|
||||
<< counters.large_square_prunes
|
||||
<< ",\"component_area_checks\":"
|
||||
<< counters.component_area_checks
|
||||
<< ",\"component_area_prunes\":"
|
||||
<< counters.component_area_prunes
|
||||
<< ",\"component_gcd_prunes\":"
|
||||
<< counters.component_gcd_prunes
|
||||
<< ",\"component_subset_prunes\":"
|
||||
<< counters.component_subset_prunes
|
||||
<< ",\"generated_tasks\":" << counters.generated_tasks
|
||||
<< ",\"completed_tasks\":" << counters.completed_tasks << "}}\n";
|
||||
return validation_ok ? 0 : 1;
|
||||
|
||||
Reference in New Issue
Block a user