3 #ifndef FES_BRANCHING_HPP
4 #define FES_BRANCHING_HPP
8 #include "utils/graph_typedefs.hpp"
9 #include "utils/graph_utils.hpp"
12 #include "utils/scaffolding_utils.hpp"
13 #include "degree_branching.hpp"
16 #define BRIDGE_THRESHOLD 1
18 #define PP_EACH_DEPTH 2
20 #define MIN_FES_TO_PARALLELIZE 8
21 #define MAX_NUM_THREADS 16
26 pthread_mutex_t thread_lock;
27 size_t num_threads = 0;
30 void FES_solve_recursively(Instance<Graph>&, DynProgSolution<>*&,
size_t depth = 0 );
43 void* FES_solve_rec_parallel(
void* _data){
45 DEBUG1(std::cout <<
"thread "<<pthread_self()<<
" starting..."<<std::endl);
46 FES_solve_recursively(*data->I, data->S, data->depth);
47 DEBUG1(std::cout <<
"thread "<<pthread_self()<<
" finishing..."<<std::endl);
49 pthread_mutex_lock(&thread_lock);
51 pthread_mutex_unlock(&thread_lock);
59 template<
class FGraph,
class Graph>
60 void get_FES_branches_for_vertex(
const Instance<Graph>& I,
const FGraph& fg,
const Vertex<FGraph>& v, std::vector<Branch<Graph> >& branches){
63 branches.reserve(degree(v, fg));
65 branches.emplace_back(DeleteBranch);
67 for(AdjIterRange<FGraph> r = adjacent_vertices(v, fg); r.first != r.second; ++r.first)
68 if(v != I.matched_with(*r.first)) {
69 const VertexPair<Graph> p(v, *r.first);
71 branches.emplace_back(TakeBranch, p);
73 branches.front().edges.emplace_back(p);
78 template<
class FGraph,
class Graph>
79 Vertex<Graph> get_best_branching_vertex(
const FGraph& fg,
const Graph& g){
80 VertexIterRange<Graph> r = vertices(g);
82 assert(r.first != r.second);
83 VertexIter<Graph> max_v = r.first;
84 size_t max_deg_fg = degree(*max_v, fg);
85 size_t max_deg_g = degree(*max_v, g);
87 for(; r.first != r.second; ++r.first){
88 const Vertex<Graph>& v = *r.first;
89 const size_t deg_fg = degree(v, fg);
90 if(deg_fg >= max_deg_fg){
91 const size_t deg_g = degree(v, g);
92 if((deg_fg == max_deg_fg) ? (deg_g > max_deg_g) :
true){
103 template<
class Graph>
104 void branch_to_get_min_sol(Instance<Graph>& I, std::vector<Branch<Graph> >& branches, DynProgSolution<>& min_sol,
const size_t depth){
105 const size_t bnum = branches.size();
106 Instance<Graph>* instances[bnum];
107 DynProgSolution<>* solutions[bnum];
108 pthread_data_block<Graph>* pthread_data_blocks[bnum];
109 pthread_t threads[bnum];
112 pthread_attr_init(&attr);
113 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
114 size_t threads_created = 0;
117 for(
size_t i = 0; i < bnum; ++i){
119 solutions[i] =
new DynProgSolution<>(I);
120 instances[i] = copy_and_apply_branch(I, branches[i], solutions[i]);
123 for(
size_t i = 0; i < bnum; ++i){
125 DEBUG3(std::cout <<
"depth "<<depth<<
":"<<std::endl<<
"branching: "<< BranchAndGraph<Graph>(branches[i], *I.g)<<std::endl);
128 bool create_parallel =
false;
129 if(I.infos.FES() > MIN_FES_TO_PARALLELIZE){
131 pthread_mutex_lock(&thread_lock);
132 create_parallel = (num_threads < MAX_NUM_THREADS);
133 if(create_parallel) ++num_threads;
134 pthread_mutex_unlock(&thread_lock);
135 if(!create_parallel) std::cout <<
"not creating new thread since we have already "<<num_threads<<
" of them"<<std::endl;
139 pthread_data_blocks[threads_created] =
new pthread_data_block<Graph>(instances[i], solutions[i], depth + 1);
141 int pt_err = pthread_create(&threads[threads_created], &attr, FES_solve_rec_parallel<Graph>, (
void*)pthread_data_blocks[threads_created]);
143 std::cerr <<
"error "<<pt_err<<
" while creating thread"<<std::endl;
147 }
else FES_solve_recursively(*(instances[i]), solutions[i], depth + 1);
149 DEBUG1(
if(depth == 0) std::cout << (i+1)*100/bnum <<
"% done" << std::endl);
153 pthread_attr_destroy(&attr);
154 for(
size_t i = 0; i < threads_created; ++i){
155 int pt_err = pthread_join(threads[i], NULL);
157 std::cerr <<
"error "<<pt_err<<
" while joining threads"<<std::endl;
160 delete pthread_data_blocks[i];
164 for(
size_t i = 0; i < bnum; ++i){
165 if(!solutions[i]->no_solutions()) min_sol.combine_min_of_two(*(solutions[i]));
204 template<
class Graph>
205 void FES_solve_recursively(Instance<Graph>& I, DynProgSolution<>*& S,
size_t depth = 0){
206 DEBUG3(std::cout <<
"depth "<< depth<<
": solving instance with " << num_vertices(*I.g) <<
" vertices and "<<num_edges(*I.g)<<
" edges." << std::endl);
207 DEBUG5(write_adj_list_graph(std::cout, *I.g); std::cout << std::endl);
210 if(depth % PP_EACH_DEPTH == 0)
211 while(preprocess::pp_matching_pendant(I, S)) {};
214 Instance<Graph> *J = I.split_off_instance();
217 DEBUG3(std::cout <<
"splitting into components of size "<<num_vertices(*I.g)<<
" and "<<num_vertices(*J->g)<<std::endl);
218 DynProgSolution<>* solJ =
new DynProgSolution<>(*J);
219 FES_solve_recursively(I, S, depth);
220 if(!S->no_solutions()){
221 FES_solve_recursively(*J, solJ, depth);
224 DEBUG3(std::cout <<
"depth "<<depth<<
": rejoining solutions for components"<<std::endl);
226 if(!solJ->no_solutions()){
228 S->combine_disjoint_union(*solJ);
233 if(S->no_solutions() || solJ->no_solutions()){
241 if(I.max_deg_two()) {
242 DEBUG3(std::cout <<
"it's already max-deg 2, getting all sub-solutions"<<std::endl);
247 DEBUG3(std::cout <<
"it's a tree, getting all sub-solutions"<<std::endl);
253 std::vector<Branch<Graph> > branches;
254 const size_t I_FES = I.infos.FES();
255 typename BridgeMap<Graph>::const_iterator best_b = I.get_best_bridge();
257 if( (best_b != I.infos.bridges.end()) ? ((best_b->second > BRIDGE_THRESHOLD) && (best_b->second < I_FES - BRIDGE_THRESHOLD)) :
false){
259 std::pair<Edge<Graph>,
bool> e = edge(best_b->first.first, best_b->first.second, *I.g);
261 DEBUG4(std::cout <<
"branching on bridge: "<< VertexPairAndGraph<Graph>(best_b->first, *I.g)<<
" splitting away an FES of "<<best_b->second<<
"/"<<I_FES<<std::endl);
262 branches.emplace_back(TakeBranch, e.first, *I.g);
263 branches.emplace_back(DeleteBranch, e.first, *I.g);
267 typedef VP_double_contained_filter<Graph, BridgeMap<Graph>, Matching<Graph> > BridgeFilter;
268 typedef filtered_graph<Graph, BridgeFilter> FGraph;
269 BridgeFilter bfilter(&I.infos.bridges, &I.matched, I.g,
true);
270 FGraph fg(*I.g, bfilter);
272 const Vertex<Graph> v = get_best_branching_vertex(fg, *I.g);
273 DEBUG4(std::cout <<
"branching on vertex: "<< VertexAndGraph<Graph>(v, *I.g)<<std::endl);
275 get_FES_branches_for_vertex(I, fg, v, branches);
278 DEBUG1(
if(depth == 0) std::cout <<
"starting with solution "<<std::endl<<*S<<std::endl);
280 DynProgSolution<> min_sol(I);
281 branch_to_get_min_sol(I, branches, min_sol, depth);
283 if(min_sol.no_solutions()) S->invalidate();
else S->destructive_append(min_sol);
284 DEBUG3(std::cout <<
"returning from depth "<<depth<<
" with ";
if(S->no_solutions()) std::cout <<
"no solutions"<<std::endl;
else std::cout <<
"solutions: "<<*S<<std::endl;);
Definition: read_adj_list.hpp:22
Definition: FES_branching.hpp:34