more work

This commit is contained in:
Laurent Perron
2025-03-06 15:15:47 +01:00
parent e179143414
commit daf04c8ed6
3 changed files with 37 additions and 5 deletions

View File

@@ -131,6 +131,25 @@ void SetCoverInvariant::LoadSolution(const SubsetBoolVector& solution) {
consistency_level_ = CL::kCostAndCoverage;
}
void SetCoverInvariant::LoadTraceAndCoverage(
const std::vector<SetCoverDecision>& trace,
const ElementToIntVector& coverage) {
ClearRemovabilityInformation();
is_selected_.assign(model_->num_subsets(), false);
trace_ = trace;
coverage_ = coverage;
cost_ = 0.0;
for (const SetCoverDecision& decision : trace) {
if (decision.decision()) {
const SubsetIndex subset(decision.subset());
is_selected_[subset] = true;
cost_ += model_->subset_costs()[subset];
}
}
consistency_level_ = CL::kCostAndCoverage;
DCHECK(CheckConsistency(CL::kCostAndCoverage));
}
bool SetCoverInvariant::NeedToRecompute(ConsistencyLevel cheched_consistency,
ConsistencyLevel target_consistency) {
return consistency_level_ < cheched_consistency &&

View File

@@ -165,6 +165,15 @@ class SetCoverInvariant {
// Loads the solution and recomputes the data in the invariant.
void LoadSolution(const SubsetBoolVector& solution);
// Loads the trace and the coverage. When both the trace and the coverage are
// loaded, the invariant is consistent at level kCostAndCoverage.
// It's also faster than to load a solution and recompute the cost and
// coverage. The trace and the coverage are expected to be consistent,
// otherwise the behavior is undefined (i.e. the invariant is not consistent,
// unless the code is run in DEBUG mode).
void LoadTraceAndCoverage(const std::vector<SetCoverDecision>& trace,
const ElementToIntVector& coverage);
// Checks the consistency of the invariant at the given consistency level.
bool CheckConsistency(ConsistencyLevel consistency) const;

View File

@@ -96,6 +96,7 @@ class KnightsCover {
const SetCoverInvariant::ConsistencyLevel consistency, int row, int col,
int radius, SetCoverInvariant* inv) const {
std::vector<SubsetIndex> cleared_subsets;
cleared_subsets.reserve((2 * radius + 1) * (2 * radius + 1));
for (int r = row - radius; r <= row + radius; ++r) {
for (int c = col - radius; c <= col + radius; ++c) {
if (!IsOnBoard(r, c)) continue;
@@ -408,7 +409,8 @@ TEST(SetCoverTest, KnightsCoverElementDegreeRadiusClear) {
SetCoverModel model = knights.model();
SetCoverInvariant inv(&model);
Cost best_cost = std::numeric_limits<Cost>::max();
SubsetBoolVector best_choices;
std::vector<SetCoverDecision> best_trace;
ElementToIntVector best_coverage;
int iteration = 0;
for (int radius = 7; radius >= 1; --radius) {
for (int row = 0; row < BoardSize; ++row) {
@@ -422,11 +424,13 @@ TEST(SetCoverTest, KnightsCoverElementDegreeRadiusClear) {
if (inv.cost() < best_cost) {
best_cost = inv.cost();
best_choices = inv.is_selected();
inv.CompressTrace();
best_trace = inv.trace();
best_coverage = inv.coverage();
LOG(INFO) << "Best cost: " << best_cost
<< " at iteration = " << iteration;
} else {
inv.LoadSolution(best_choices);
inv.LoadTraceAndCoverage(best_trace, best_coverage);
}
knights.ClearSubsetWithinRadius(CL::kCostAndCoverage, row, col, radius,
&inv);
@@ -434,8 +438,8 @@ TEST(SetCoverTest, KnightsCoverElementDegreeRadiusClear) {
}
}
}
inv.LoadSolution(best_choices);
knights.DisplaySolution(best_choices);
inv.LoadTraceAndCoverage(best_trace, best_coverage);
knights.DisplaySolution(inv.is_selected());
LOG(INFO) << "RadiusClear cost: " << best_cost;
// The best solution found until 2023-08 has a cost of 350.
// http://www.contestcen.com/kn50.htm