#include "internal.hpp"
#include "util.hpp"
#include <string>
namespace CaDiCaL {
void Internal::recompute_tier () {
if (!opts.recomputetier)
return;
++stats.tierecomputed;
const int64_t delta =
stats.tierecomputed >= 16 ? 1u << 16 : (1u << stats.tierecomputed);
lim.recompute_tier = stats.conflicts + delta;
LOG ("rescheduling in %" PRId64 " at %" PRId64 " (conflicts at %" PRId64
")",
delta, lim.recompute_tier, stats.conflicts);
#ifndef NDEBUG
uint64_t total_used = 0;
for (auto u : stats.used[stable])
total_used += u;
assert (total_used == stats.bump_used[stable]);
#endif
if (!stats.bump_used[stable]) {
tier1[stable] = opts.reducetier1glue;
tier2[stable] = opts.reducetier2glue;
LOG ("tier1 limit = %d", tier1[stable]);
LOG ("tier2 limit = %d", tier2[stable]);
return;
} else {
uint64_t accumulated_tier1_limit =
stats.bump_used[stable] * opts.tier1limit / 100;
uint64_t accumulated_tier2_limit =
stats.bump_used[stable] * opts.tier2limit / 100;
tier1[stable] = 1;
tier2[stable] = 1;
uint64_t accumulated_used = stats.used[stable][0];
size_t glue = 1;
for (; glue < stats.used[stable].size (); ++glue) {
const uint64_t u = stats.used[stable][glue];
accumulated_used += u;
if (accumulated_used >= accumulated_tier1_limit) {
tier1[stable] = glue;
break;
}
}
for (; glue < stats.used[stable].size (); ++glue) {
const uint64_t u = stats.used[stable][glue];
accumulated_used += u;
if (accumulated_used >= accumulated_tier2_limit) {
tier2[stable] = glue;
break;
}
}
}
assert (tier1[stable] > 0);
assert (tier1[stable]);
assert (tier2[stable]);
if (tier1[stable] < opts.tier1minglue) {
LOG ("tier1 limit of %d is too low, setting %d instead", tier1[stable],
opts.tier1minglue);
tier1[stable] = opts.tier1minglue;
}
if (tier2[stable] < opts.tier2minglue) {
LOG ("tier2 limit of %d is too low, setting %d instead", tier2[stable],
opts.tier2minglue);
tier2[stable] = opts.tier2minglue;
}
if (tier1[stable] >= tier2[stable])
tier2[stable] = tier1[stable] + 1;
assert (tier2[stable] > tier1[stable]);
PHASE ("retiered", stats.tierecomputed,
"tier1 limit = %d in %s mode, tier2 limit = %d in %s mode",
tier1[stable], stable ? "stable" : "focused", tier2[stable],
stable ? "stable" : "focused");
}
void Internal::print_tier_usage_statistics () {
recompute_tier ();
for (auto stable : {false, true}) {
unsigned total_used = 0;
for (size_t glue = 0; glue < stats.used[stable].size (); ++glue)
total_used += stats.used[stable][glue];
const std::string mode = stable ? "stable" : "focused";
const size_t tier1 = internal->tier1[stable];
const size_t tier2 = internal->tier2[stable];
if (tier1 > tier2 && opts.reducetier1glue > opts.reducetier2glue) {
MSG ("tier1 > tier 2 due to the options, giving up");
break;
}
assert (tier1 <= tier2);
unsigned prefix, suffix;
unsigned span = tier2 - tier1 + 1;
const unsigned max_printed = 5;
assert (max_printed & 1), assert (max_printed / 2 > 0);
if (span > max_printed) {
prefix = tier1 + max_printed / 2 - 1;
suffix = tier2 - max_printed / 2 + 1;
} else
prefix = UINT_MAX, suffix = 0;
uint64_t accumulated_middle = 0;
int glue_digits = 1, clauses_digits = 1;
for (unsigned glue = 0; glue <= stats.used[stable].size (); glue++) {
if (glue < tier1)
continue;
uint64_t used = stats.used[stable][glue];
int tmp_glue = 0, tmp_clauses = 0;
if (glue <= prefix || suffix <= glue) {
tmp_glue = glue;
tmp_clauses = used;
} else {
accumulated_middle += used;
if (glue + 1 == suffix) {
tmp_glue = (prefix + 1) + (glue) + 1;
tmp_clauses = (accumulated_middle);
}
}
if (tmp_glue > glue_digits)
glue_digits = tmp_glue;
if (tmp_clauses > clauses_digits)
clauses_digits = tmp_clauses;
if (glue == tier2)
break;
}
accumulated_middle = 0;
uint64_t accumulated = 0;
std::string output;
for (unsigned glue = 0; glue <= stats.used[stable].size (); glue++) {
uint64_t used = stats.used[stable][glue];
accumulated += used;
if (glue < tier1)
continue;
if (glue <= prefix || suffix <= glue + 1) {
output += mode + " glue ";
}
if (glue <= prefix || suffix <= glue) {
std::string glue_str = std::to_string (glue);
output += glue_str;
output += " used " + std::to_string (used);
output +=
" clauses " +
std::to_string (percent (used, total_used)).substr (0, 5) + "%";
output += " accumulated " +
std::to_string (percent (accumulated, total_used))
.substr (0, 5) +
"%";
if (glue == tier1)
output += " tier1";
if (glue == tier2)
output += " tier2";
MSG ("%s", output.c_str ());
output.clear ();
} else {
accumulated_middle += used;
if (glue + 1 == suffix) {
std::string glue_str = std::to_string (prefix + 1) + "-" +
std::to_string (suffix - 1);
output +=
glue_str + " used " + std::to_string (accumulated_middle);
output +=
" clauses " +
std::to_string (percent (accumulated_middle, total_used))
.substr (0, 5) +
"%";
output += " accumulated " +
std::to_string (percent (accumulated, total_used))
.substr (0, 5) +
"%";
MSG ("%s", output.c_str ());
output.clear ();
}
}
if (glue == tier2)
break;
}
LINE ();
}
}
}