9 #include "utils/graph_typedefs.hpp"
13 #define HANDLE_SOLUTION(x) x
16 typedef std::list<EdgeName> EdgeNameList;
19 typedef std::shared_ptr<global_list> SharedGList;
20 typedef std::list<SharedGList> ListGList;
21 typedef std::shared_ptr<ListGList> SharedListGList;
23 #define NO_EDGE ((EdgeName){NONAME, NONAME})
29 SharedGList left, right;
31 global_list(
const EdgeName& _e,
const SharedGList& _left =
nullptr): e(_e), left(_left), right(
nullptr) {};
32 global_list(
const SharedGList& _left,
const SharedGList _right): e(NO_EDGE), left(_left), right(_right) {};
46 MatrixEntry(
const size_t _weight = SIZE_MAX): weight(_weight), edges(
nullptr) {}
47 MatrixEntry(
const EdgeName& e,
const size_t _weight = SIZE_MAX): weight(_weight), edges(std::make_shared<global_list>(e)) {}
49 bool is_undefined()
const {
return weight == SIZE_MAX; }
50 void set_undefined() { weight = SIZE_MAX; }
53 return edges ==
nullptr;
61 void append_edge(
const EdgeName& e,
const size_t _weight = 0)
65 if(edges !=
nullptr) {
67 edges = std::make_shared<global_list>(e, edges);
70 edges = std::make_shared<global_list>(e);
81 edges = std::make_shared<global_list>(edges, ME.edges);
89 EdgeNameList get_edges()
const
93 std::stack<SharedGList> el_stack;
95 while(!el_stack.empty()){
96 SharedGList top_el = el_stack.top(); el_stack.pop();
97 const EdgeName& e = top_el->e;
98 if(e != NO_EDGE) result.push_back(e);
99 if(top_el->left !=
nullptr) el_stack.push(top_el->left);
100 if(top_el->right !=
nullptr) el_stack.push(top_el->right);
103 }
else return EdgeNameList();
111 HANDLE_SOLUTION(edges = ME.edges;)
129 template<
typename Index,
typename Matrix,
class Compare = std::less<
size_t> >
130 bool update_if_worse(Matrix& m,
const Index& index,
MatrixEntry* ME)
132 const Compare is_better;
134 const typename Matrix::iterator ME_i = m.find(index);
136 m.emplace(index, ME);
140 if(is_better(ME->weight, ME_i->second->weight)) {
165 template<
typename Index,
typename Matrix,
class Compare = std::less<
size_t> >
168 const Compare is_better;
170 const typename Matrix::iterator ME_i = m.find(index);
174 m.emplace(index, ME);
178 if(is_better(E.weight + cE.weight, ME.weight)){
190 template<
class Compare = std::less<
size_t> >
194 typedef unordered_map<PathsAndCycles, MatrixEntry*> entries_t;
200 const Compare is_better;
205 PCMinMatrix(
const unsigned paths,
const unsigned cycles): max(paths, cycles), entries(
new entries_t()), is_better() {}
209 entries(
new entries_t()),
211 best_index(m.best_index)
213 if(!m.entries->empty()){
214 const MatrixEntry*
const best_ME = m.entries->at(best_index);
215 size_t best_weight = best_ME->weight;
216 entries->emplace(best_index,
new MatrixEntry(*best_ME));
217 for(
auto& ME: *m.entries)
218 if( !(best_index <= ME.first) || is_better(ME.second->weight, best_weight))
219 entries->emplace(ME.first,
new MatrixEntry(*ME.second));
224 for(
auto& ME: *entries)
delete ME.second;
232 if(index > max)
return false;
234 const bool was_empty = entries->empty();
235 const size_t best_weight = was_empty ? SIZE_MAX : entries->at(best_index)->weight;
236 const size_t weight = ME->weight;
238 if(was_empty || !(best_index <= index) || is_better(weight, best_weight)){
239 DEBUG5(std::cout <<
"trying to put entry at "<<index<<
"..."<<std::flush);
240 if(!update_if_worse<PathsAndCycles, entries_t, Compare>(*entries, index, ME))
return false;
241 DEBUG5(std::cout <<
"success, now updating best_index ("<<best_index.p<<
","<<best_index.c<<
") if "<<was_empty<<
" || Compare("<<weight<<
","<<best_weight<<
")"<<std::endl);
243 if(index != best_index){
244 if(!was_empty && (index < best_index) && is_better(weight, best_weight)){
245 const typename entries_t::iterator min_i = entries->find(best_index);
246 assert(min_i != entries->end());
247 delete min_i->second;
248 entries->erase(min_i);
250 if(was_empty || is_better(weight, best_weight)) best_index = index;
252 DEBUG5(std::cout <<
"new best_index is ("<<best_index.p<<
","<<best_index.c<<
")"<<std::flush<<
" with weight "<<entries->at(best_index)->weight<<std::endl);
266 bool put(
const PathsAndCycles& index,
const EdgeName& e,
const size_t weight)
275 template<
class Graph>
279 for(EdgeIterRange<Graph> er = boost::edges(g); er.first != er.second; ++er.first){
280 const Edge<Graph>& e = *er.first;
281 const size_t weight = boost::get(boost::edge_weight, g, e);
282 ME->append_edge(get_edge_name(e, g), weight);
284 if(!put(index, ME)) {
310 assert(index <= max);
312 const size_t sum_weight = E.weight + cE.weight;
313 const bool was_empty = entries->empty();
314 const size_t best_weight = was_empty ? SIZE_MAX : entries->at(best_index)->weight;
316 if(was_empty || !(best_index <= index) || is_better(sum_weight, best_weight)){
317 if(!update_if_worse<PathsAndCycles, entries_t, Compare>(*entries, index, E, cE))
return false;
319 if(index != best_index){
320 if(!was_empty && (index <= best_index) && is_better(sum_weight, best_weight)) entries->erase(best_index);
321 if(was_empty || is_better(sum_weight, best_weight)) best_index = index;
328 void add_to_all(
const EdgeName& e,
const size_t weight)
330 for(
auto& ME : *entries) ME.second->append_edge(e, weight);
336 assert(index <= max);
337 return *(entries->at(index));
341 return get({
paths, cycles});
347 const MatrixEntry& at(
const unsigned paths,
const unsigned cycles)
const
351 std::pair<entries_t::const_iterator, entries_t::const_iterator> get_entries()
const
353 return std::pair<entries_t::const_iterator, entries_t::const_iterator>(entries->begin(), entries->end());
359 DEBUG6(std::cout <<
"destructively merging "<<pc.entries->size()<<
" entries into our "<<size()<<
" entries"<<std::endl);
360 for(
auto ME = pc.entries->begin(); ME != pc.entries->end(); ME = pc.entries->erase(ME)){
362 if(!put(ME->first, ME->second)){
373 const entries_t::iterator i = entries->find(key);
374 assert(i != entries->end());
377 return put(key + pc, ME);
385 entries_t* old_entries = entries;
386 entries =
new entries_t;
387 for(
auto& ME: *old_entries) put(ME.first + pc, ME.second);
396 size_t best_weight = SIZE_MAX;
398 for(
auto E : *entries){
400 const entries_t::const_iterator mE = m.entries->find(pc - Epc);
401 if(mE != m.entries->end()){
402 if(is_better(E.second->weight + mE->second->weight, best_weight)){
403 best_weight = E.second->weight + mE->second->weight;
414 size_t best_weight = SIZE_MAX;
416 for(
unsigned mp = 0; (mp <= pc.p) && (mp <= m.max.p); ++mp)
417 for(
unsigned mc = 0; (mc <= pc.c) && (mc <= m.max.c); ++mc){
420 const entries_t::const_iterator mE = m.entries->find(current);
422 if(mE != m.entries->end()){
423 const entries_t::const_iterator E = entries->find(diff);
424 if(E != entries->end())
425 if(is_better(mE->second->weight + E->second->weight, best_weight)){
426 best_weight = mE->second->weight + E->second->weight;
437 if(entries->size() < std::min(pc.p * pc.c, m.max.p * m.max.c))
438 return find_min_entry_combination_by_iteration(pc, m);
440 return find_min_entry_combination_by_testing(pc, m);
446 return *(entries->at(best_index));
449 const size_t size()
const
451 return entries->size();
459 for(
auto& i : *entries){
460 if(i.first.p < result.p) result.p = i.first.p;
461 if(i.first.c < result.c) result.c = i.first.c;
467 friend std::ostream& operator<<(std::ostream& os,
const PCMinMatrix& m){
469 os << std::endl<<
" ";
470 for(
unsigned p = 0; p <= m.max.p; ++p) os <<
"\t" << p;
471 os <<
"\t\tbest index = "<<m.best_index<<std::endl;
473 for(
unsigned c = 0; c <= m.max.c; ++c){
474 if(c < 10) os <<
" ";
476 for(
unsigned p = 0; p <= m.max.p; ++p){
477 try{ os << m.at(p, c).weight <<
"\t"; }
catch(...) { os <<
"\t"; };
Definition: min_matrix.hpp:191
unsigned paths
maximum number of paths that a solution graph should consist of
Definition: command_line.hpp:56
unsigned cycles
maximum number of cycles that a solution graph should consist of
Definition: command_line.hpp:58
Definition: read_adj_list.hpp:22
Definition: min_matrix.hpp:36
Definition: min_matrix.hpp:26
Definition: graph_typedefs.hpp:26