diff --git a/wmis/app/branch_reduce.cpp b/wmis/app/branch_reduce.cpp index 1cea034..3d95718 100644 --- a/wmis/app/branch_reduce.cpp +++ b/wmis/app/branch_reduce.cpp @@ -93,7 +93,7 @@ int main(int argn, char **argv) { branch_and_reduce_algorithm reducer(G, mis_config); reducer.run_branch_reduce(); - NodeWeight MWIS_weight = reducer.get_current_is_weight(); + NodeWeight MWIS_weight = reducer.get_is_weight(); auto end = std::chrono::system_clock::now(); diff --git a/wmis/app/weighted_ls.cpp b/wmis/app/weighted_ls.cpp index 4c178a8..39c79d4 100644 --- a/wmis/app/weighted_ls.cpp +++ b/wmis/app/weighted_ls.cpp @@ -81,7 +81,7 @@ NodeWeight perform_reduction(std::unique_ptr& reduc exit(1); } - NodeWeight is_weight = reducer->get_current_is_weight(); + NodeWeight is_weight = reducer->get_is_weight(); return is_weight; } diff --git a/wmis/lib/mis/kernel/branch_and_reduce_algorithm.cpp b/wmis/lib/mis/kernel/branch_and_reduce_algorithm.cpp index 7249ab3..ebe8260 100644 --- a/wmis/lib/mis/kernel/branch_and_reduce_algorithm.cpp +++ b/wmis/lib/mis/kernel/branch_and_reduce_algorithm.cpp @@ -728,19 +728,19 @@ void branch_and_reduce_algorithm::restore_best_local_solution() { void branch_and_reduce_algorithm::restore_best_global_solution() { status = std::move(global_status); - status.modified_queue.pop_back(); + status.modified_queue.pop_back(); while (!status.modified_queue.empty()) { NodeID node = status.modified_queue.back(); - status.modified_queue.pop_back(); + status.modified_queue.pop_back(); if (status.node_status[node] == IS_status::folded) { auto type = status.folded_queue.back(); - status.folded_queue.pop_back(); - status.reductions[global_reduction_map[type]]->apply(this); + status.folded_queue.pop_back(); + status.reductions[global_reduction_map[type]]->apply(this); } else { - status.graph.restore_node(node); + status.graph.restore_node(node); } } } @@ -749,6 +749,11 @@ NodeWeight branch_and_reduce_algorithm::get_current_is_weight() const { return global_status.is_weight + global_status.reduction_offset; } +NodeWeight branch_and_reduce_algorithm::get_is_weight() const { + // after restoring global best solution, global status was moved to status + return status.is_weight + status.reduction_offset; +} + void branch_and_reduce_algorithm::build_global_graph_access() { global_mapping.resize(global_status.remaining_nodes, 0); std::swap(status, global_status); diff --git a/wmis/lib/mis/kernel/branch_and_reduce_algorithm.h b/wmis/lib/mis/kernel/branch_and_reduce_algorithm.h index b0309b4..2e9695e 100755 --- a/wmis/lib/mis/kernel/branch_and_reduce_algorithm.h +++ b/wmis/lib/mis/kernel/branch_and_reduce_algorithm.h @@ -194,6 +194,8 @@ class branch_and_reduce_algorithm { void disable_cout(); void enable_cout(); + NodeWeight get_current_is_weight() const; + public: branch_and_reduce_algorithm(graph_access& G, const MISConfig& config, bool called_from_fold = false); @@ -203,7 +205,7 @@ class branch_and_reduce_algorithm { static size_t run_ils(const MISConfig& config, graph_access& G, sized_vector& tmp_buffer, size_t max_swaps); static void greedy_initial_is(graph_access& G, sized_vector& tmp_buffer); - NodeWeight get_current_is_weight() const; + NodeWeight get_is_weight() const; void reverse_reduction(graph_access & G, graph_access & reduced_G, std::vector & reverse_mapping); void apply_branch_reduce_solution(graph_access & G); diff --git a/wmis/lib/mis/kernel/reductions.cpp b/wmis/lib/mis/kernel/reductions.cpp index 83befc5..b5a135e 100644 --- a/wmis/lib/mis/kernel/reductions.cpp +++ b/wmis/lib/mis/kernel/reductions.cpp @@ -396,24 +396,36 @@ void fold2_reduction::restore(branch_and_reduce_algorithm* br_alg) { } void fold2_reduction::apply(branch_and_reduce_algorithm* br_alg) { - auto& status = br_alg->status; - auto nodes = restore_vec.back().nodes; - auto main_status = status.node_status[nodes.main]; - restore(br_alg); - - if (main_status == IS_status::included) { - status.node_status[nodes.main] = IS_status::excluded; - status.node_status[nodes.rest[0]] = IS_status::included; - status.node_status[nodes.rest[1]] = IS_status::included; - - status.is_weight += status.weights[nodes.rest[0]] + status.weights[nodes.rest[1]]; - } else { - status.node_status[nodes.main] = IS_status::included; - status.node_status[nodes.rest[0]] = IS_status::excluded; - status.node_status[nodes.rest[1]] = IS_status::excluded; - - status.is_weight += status.weights[nodes.main]; - } +#ifndef NDEBUG + NodeWeight previous_is_weight = br_alg->status.is_weight + br_alg->status.reduction_offset; +#endif + + auto& status = br_alg->status; + auto nodes = restore_vec.back().nodes; + auto main_status = status.node_status[nodes.main]; + restore(br_alg); + + if (main_status == IS_status::included) { + status.node_status[nodes.main] = IS_status::excluded; + status.node_status[nodes.rest[0]] = IS_status::included; + status.node_status[nodes.rest[1]] = IS_status::included; + + // weight of folded vertex was added to is_weight while reducing: + // status.is_weight += status.weights[nodes.rest[0]] + status.weights[nodes.rest[1]] - status.weights[nodes.main] + // only need to add status.weights[nodes.main] to is_weight + status.is_weight += status.weights[nodes.main]; + // old: status.is_weight += status.weights[nodes.rest[0]] + status.weights[nodes.rest[1]]; + } else { + status.node_status[nodes.main] = IS_status::included; + status.node_status[nodes.rest[0]] = IS_status::excluded; + status.node_status[nodes.rest[1]] = IS_status::excluded; + + status.is_weight += status.weights[nodes.main]; + } +#ifndef NDEBUG + // invariant that has to hold + ASSERT_TRUE(br_alg->status.is_weight + br_alg->status.reduction_offset == previous_is_weight); +#endif } bool clique_reduction::reduce(branch_and_reduce_algorithm* br_alg) { @@ -780,7 +792,7 @@ bool generalized_neighborhood_reduction::reduce(branch_and_reduce_algorithm* br_ continue; } - if (status.weights[v] >= neighborhood_br_alg.get_current_is_weight()) + if (status.weights[v] >= neighborhood_br_alg.get_is_weight()) br_alg->set(v, IS_status::included); } } @@ -845,7 +857,7 @@ bool generalized_fold_reduction::reduce(branch_and_reduce_algorithm* br_alg) { continue; } - NodeWeight MWIS_weight = neighborhood_br_alg.get_current_is_weight(); + NodeWeight MWIS_weight = neighborhood_br_alg.get_is_weight(); NodeWeight min_MWIS_neighbor_weight = std::numeric_limits::max(); if (status.weights[v] >= MWIS_weight) { @@ -889,7 +901,7 @@ bool generalized_fold_reduction::reduce(branch_and_reduce_algorithm* br_alg) { std::cerr << "%generalized_fold_reduction br_call loop time out" << std::endl; check_failed = true; } - else if (neighborhood_br_alg.get_current_is_weight() >= status.weights[v]) { + else if (neighborhood_br_alg.get_is_weight() >= status.weights[v]) { check_failed = true; } @@ -942,7 +954,7 @@ bool generalized_fold_reduction::reduce(branch_and_reduce_algorithm* br_alg) { } else { // if the weight of every MWIS in N(v) which contains "node" is smaller than w(v) then we can remove "node" - remove_node = neighborhood_br_alg.get_current_is_weight() + status.weights[node] <= status.weights[v]; + remove_node = neighborhood_br_alg.get_is_weight() + status.weights[node] <= status.weights[v]; } for (const NodeID neighbor : status.graph[node]) { @@ -1058,6 +1070,9 @@ void generalized_fold_reduction::restore(branch_and_reduce_algorithm* br_alg) { } void generalized_fold_reduction::apply(branch_and_reduce_algorithm* br_alg) { +#ifndef NDEBUG + NodeWeight previous_is_weight = br_alg->status.is_weight + br_alg->status.reduction_offset; +#endif auto& status = br_alg->status; auto nodes = restore_vec.back().nodes; auto MWIS_weight = restore_vec.back().MWIS_weight; @@ -1071,7 +1086,8 @@ void generalized_fold_reduction::apply(branch_and_reduce_algorithm* br_alg) { status.node_status[node] = IS_status::included; } - status.is_weight += MWIS_weight; + status.is_weight += status.weights[nodes.main]; // for details see fold2::apply + // wrong: status.is_weight += MWIS_weight; } else { status.node_status[nodes.main] = IS_status::included; @@ -1081,4 +1097,8 @@ void generalized_fold_reduction::apply(branch_and_reduce_algorithm* br_alg) { status.is_weight += status.weights[nodes.main]; } +#ifndef NDEBUG + // invariant that has to hold + ASSERT_TRUE(br_alg->status.is_weight + br_alg->status.reduction_offset == previous_is_weight); +#endif }