57 #ifndef CLIQUE_COVERING_HPP 58 #define CLIQUE_COVERING_HPP 65 #include "ortools/graph/assignment.h" 70 #include <boost/graph/adjacency_matrix.hpp> 71 #include <boost/graph/filtered_graph.hpp> 72 #include <boost/graph/graphviz.hpp> 73 #include <boost/graph/incremental_components.hpp> 74 #include <boost/graph/properties.hpp> 75 #include <boost/pending/disjoint_sets.hpp> 76 #include <boost/tuple/tuple.hpp> 77 #include <boost/version.hpp> 85 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 86 #pragma GCC diagnostic push 87 #pragma GCC diagnostic ignored "-Wsign-compare" 88 #pragma GCC diagnostic ignored "-Wsign-conversion" 90 #pragma GCC diagnostic warning "-Wsign-compare" 91 #pragma GCC diagnostic warning "-Wsign-conversion" 94 #if defined(__clang__) 95 #pragma clang diagnostic push 96 #pragma clang diagnostic ignored "-Wsign-compare" 97 #pragma clang diagnostic ignored "-Wsign-conversion" 100 template <
typename vertex_type>
102 template <
typename vertex_type>
106 template <
typename IIter1,
typename Container,
typename OIter>
109 while(first1 != last1)
111 if(second.find(*first1) == second.end())
122 template <
typename IIter1,
typename Container,
typename OIter>
125 while(first1 != last1)
127 if(second.find(*first1) != second.end())
158 template <
typename VertexType>
187 virtual C_vertex add_vertex(
const VertexType& element,
const std::string& name) = 0;
196 virtual void add_edge(
const VertexType& src,
const VertexType& dest,
int _weight) = 0;
201 virtual size_t num_vertices() = 0;
221 virtual void writeDot(
const std::string&
filename)
const = 0;
228 virtual void add_subpartitions(
size_t id, VertexType v) = 0;
234 virtual void suggest_min_resources(
size_t n_resources) = 0;
240 virtual void suggest_max_resources(
size_t n_resources) = 0;
246 virtual void max_resources(
size_t n_resources) = 0;
252 virtual void min_resources(
size_t n_resources) = 0;
275 void operator()(std::ostream& out,
const boost::graph_traits<cc_compatibility_graph>::edge_descriptor& e)
const 277 out <<
"[label=\"" << g[e].weight <<
"\"]";
299 out <<
"[label=\"" << names.find(v)->second <<
"\"]";
306 template <
typename Graph>
312 using vertex =
typename boost::graph_traits<Graph>::vertex_descriptor;
316 using edge_iterator =
typename boost::graph_traits<Graph>::out_edge_iterator;
333 vertex result = boost::graph_traits<Graph>::null_vertex();
334 THROW_ASSERT(!subg.empty(),
"at least one element should belong to subg");
335 int max_weighted_intersection = -1;
337 for(
auto it = subg.begin(); it != it_end; ++it)
339 int weight_intersection = 0;
341 boost::tie(ei, ei_end) = boost::out_edges(*it, g);
342 for(; ei != ei_end; ++ei)
346 weight_intersection += g[*ei].weight;
349 if(weight_intersection > max_weighted_intersection)
351 max_weighted_intersection = weight_intersection;
355 THROW_ASSERT(max_weighted_intersection >= 0,
"something wrong happened");
362 vertex result = boost::graph_traits<Graph>::null_vertex();
364 THROW_ASSERT(!ext.empty(),
"at least one element should belong to ext");
370 boost::tie(ei, ei_end) = boost::out_edges(*it, g);
371 for(; ei != ei_end; ++ei)
373 cur_weight += g[*ei].weight;
375 if(cur_weight > max_weight)
378 max_weight = cur_weight;
381 THROW_ASSERT(max_weight >= 0,
"something wrong happened");
390 boost::tie(ei, ei_end) = boost::out_edges(q_vertex, g);
391 for(; ei != ei_end; ++ei)
395 result += g[*ei].weight;
404 if(subg.empty() && Q.size() >= Q_max.size())
406 if(Q.size() > Q_max.size() || W_Q > W_Q_max)
409 Q_max.insert(Q.begin(), Q.end());
415 else if(cand.empty())
421 vertex u = get_max_weighted_adiacent_intersection(subg, cand, g);
425 boost::tie(vi, vi_end) = boost::adjacent_vertices(u, g);
428 gamma_u.insert(vi, vi_end);
432 while(!EXT_u.empty())
434 vertex q = get_max_weight_vertex(EXT_u, g);
440 int delta = compute_delta_weight(q, Q, g);
442 boost::tie(vi, vi_end) = boost::adjacent_vertices(q, g);
444 gamma_q.insert(vi, vi_end);
449 expand(subg_q, cand_q, g, upper_bound);
450 if(upper_bound <= W_Q_max)
473 boost::tie(vi, vi_end) = boost::vertices(g);
474 subg.insert(vi, vi_end);
475 cand.insert(vi, vi_end);
476 expand(subg, cand, g, upper_bound);
486 : W_Q(0), W_Q_max(
std::numeric_limits<int>::
min()), names(_names)
494 template <
typename Graph>
500 using vertex =
typename boost::graph_traits<Graph>::vertex_descriptor;
504 using edge_iterator =
typename boost::graph_traits<Graph>::out_edge_iterator;
521 vertex result = boost::graph_traits<Graph>::null_vertex();
522 THROW_ASSERT(!subg.empty(),
"at least one element should belong to subg");
523 int max_weighted_intersection = -1;
525 for(
auto it = subg.begin(); it != it_end; ++it)
527 int weight_intersection = 0;
529 boost::tie(ei, ei_end) = boost::out_edges(*it, g);
530 for(; ei != ei_end; ++ei)
534 weight_intersection += g[*ei].weight;
537 if(weight_intersection > max_weighted_intersection)
539 max_weighted_intersection = weight_intersection;
543 THROW_ASSERT(max_weighted_intersection >= 0,
"something wrong happened");
550 vertex result = boost::graph_traits<Graph>::null_vertex();
552 THROW_ASSERT(!ext.empty(),
"at least one element should belong to ext");
558 boost::tie(ei, ei_end) = boost::out_edges(*it, g);
559 for(; ei != ei_end; ++ei)
561 cur_weight += g[*ei].weight;
563 if(cur_weight > max_weight)
566 max_weight = cur_weight;
569 THROW_ASSERT(max_weight >= 0,
"something wrong happened");
578 boost::tie(ei, ei_end) = boost::out_edges(q_vertex, g);
579 for(; ei != ei_end; ++ei)
583 result += g[*ei].weight;
592 if(subg.empty() && Q.size() >= Q_max.size())
594 if(Q.size() > Q_max.size() || W_Q > W_Q_max)
597 Q_max.insert(Q.begin(), Q.end());
603 else if(cand.empty())
609 vertex u = get_max_weighted_adiacent_intersection(subg, cand, g);
613 boost::tie(vi, vi_end) = boost::adjacent_vertices(u, g);
616 gamma_u.insert(vi, vi_end);
620 while(!EXT_u.empty())
622 vertex q = get_max_weight_vertex(EXT_u, g);
628 int delta = compute_delta_weight(q, Q, g);
631 boost::tie(vi, vi_end) = boost::adjacent_vertices(q, g);
633 gamma_q.insert(vi, vi_end);
638 expand(subg_q, cand_q, g);
663 boost::tie(vi, vi_end) = boost::vertices(g);
664 subg.insert(vi, vi_end);
665 cand.insert(vi, vi_end);
666 expand(subg, cand, g);
671 CustomUnorderedMap<
typename boost::graph_traits<Graph>::vertex_descriptor, std::string>& _names)
672 : W_Q(0), W_Q_max(
std::numeric_limits<int>::
min()), names(_names)
677 template <
typename vertex_type>
683 std::vector<CustomOrderedSet<C_vertex>>
cliques;
687 static const int COMPATIBILITY_ALL_EDGES = ~0;
701 : clique_covering_graph_bulk(nvert), max_level(0), all_edges(_all_edges), vindex(0)
712 THROW_ASSERT(v2uv.find(element) == v2uv.end(),
"vertex already added");
714 v2uv[element] = result =
boost::vertex(vindex, clique_covering_graph_bulk);
722 void add_edge(
const vertex_type& src,
const vertex_type& dest,
int _weight)
override 724 THROW_ASSERT(src != dest,
"autoloops are not allowed in a compatibility graph");
725 THROW_ASSERT(v2uv.find(src) != v2uv.end(),
"src not added");
726 THROW_ASSERT(v2uv.find(dest) != v2uv.end(),
"dest not added");
727 THROW_ASSERT(_weight > 0 && _weight < 32,
"weights from 1 to 31 are allowed " +
STR(_weight));
728 max_level =
std::max(max_level, _weight);
729 C_vertex SRC = v2uv.find(src)->second;
730 C_vertex DEST = v2uv.find(dest)->second;
737 return cliques.size();
744 auto it_end = cur_clique.end();
745 for(
auto it = cur_clique.begin(); it != it_end; ++it)
747 THROW_ASSERT(uv2v.find(*it) != uv2v.end(),
"vertex not added");
748 result.insert(uv2v.find(*it)->second);
754 boost::disjoint_sets<rank_pmap_type, pred_pmap_type>& ds,
758 using conflict_graph = boost::adjacency_matrix<boost::undirectedS>;
759 using cg_vertices_size_type = boost::graph_traits<conflict_graph>::vertices_size_type;
760 using cg_vertex_index_map = boost::property_map<conflict_graph, boost::vertex_index_t>::const_type;
761 boost::iterator_property_map<cg_vertices_size_type*, cg_vertex_index_map, cg_vertices_size_type,
762 cg_vertices_size_type&>
765 std::vector<cg_vertices_size_type> color_vec;
768 using vertex_descriptor_cg = boost::graph_traits<conflict_graph>::vertex_descriptor;
770 std::vector<C_vertex> reverse_map;
772 unsigned int num_vert = 0;
773 cc_compatibility_graph::vertex_iterator vi, vi_end;
774 for(boost::tie(vi, vi_end) = boost::vertices(*filteredCG); vi != vi_end; ++vi)
778 auto* cg =
new conflict_graph(num_vert);
780 unsigned int vertex_index = 0;
784 reverse_map.push_back(v);
787 color_vec.resize(vertex_index);
788 color = boost::iterator_property_map<cg_vertices_size_type*, cg_vertex_index_map, cg_vertices_size_type,
789 cg_vertices_size_type&>(&color_vec.front(),
790 boost::get(boost::vertex_index, *cg));
794 std::vector<C_vertex> neighbors(boost::adjacent_vertices(u, *filteredCG).first,
795 boost::adjacent_vertices(u, *filteredCG).second);
796 std::sort(neighbors.begin(), neighbors.end());
804 if(!std::binary_search(neighbors.begin(), neighbors.end(), v))
806 boost::add_edge(vmap[u], vmap[v], *cg);
813 std::vector<unsigned int> colors(num_colors);
815 for(
unsigned int i = 0; i < num_colors; ++i)
819 for(
unsigned int i = 0; i < vertex_index; ++i)
821 cg_vertices_size_type c = color_vec[i];
828 C_vertex ug_vertex_i = reverse_map[i];
829 C_vertex ug_vertex_c = reverse_map[colors[c]];
830 ds.union_set(ug_vertex_i, ug_vertex_c);
837 boost::disjoint_sets<rank_pmap_type, pred_pmap_type>& ds,
840 auto it_end = support.end();
841 for(
auto it = support.begin(); it != it_end;)
844 C_vertex rep = ds.find_set(*current);
848 if(current_partitions.find(rep) == current_partitions.end())
851 singularity.insert(cur);
852 current_partitions[rep] = singularity;
856 current_partitions.find(rep)->second.insert(cur);
861 if(current_partitions.find(rep) == current_partitions.end())
864 current_partitions[rep] = null_set;
870 #define THRESHOLD_2_SIMPLIFY 200 873 VertexIndex n = boost::num_vertices(clique_covering_graph_bulk);
874 std::vector<VertexIndex> rank_map(n);
875 std::vector<C_vertex> pred_map(n);
876 vertex_index_pmap_t cindex_pmap = boost::get(boost::vertex_index_t(), clique_covering_graph_bulk);
877 rank_pmap_type rank_pmap = boost::make_iterator_property_map(rank_map.begin(), cindex_pmap, rank_map[0]);
878 pred_pmap_type pred_pmap = boost::make_iterator_property_map(pred_map.begin(), cindex_pmap, pred_map[0]);
879 boost::disjoint_sets<rank_pmap_type, pred_pmap_type> ds(rank_pmap, pred_pmap);
880 using u_vertex_iterator = boost::graph_traits<boost_cc_compatibility_graph>::vertex_iterator;
884 boost::initialize_incremental_components(clique_covering_graph_bulk, ds);
886 u_vertex_iterator ui, uiend;
887 for(boost::tie(ui, uiend) = boost::vertices(clique_covering_graph_bulk); ui != uiend; ++ui)
890 all_vertices.insert(*ui);
895 COMPATIBILITY_ALL_EDGES, &clique_covering_graph_bulk),
898 std::map<C_vertex, CustomOrderedSet<C_vertex>> current_partitions;
902 do_clique_covering(completeCG, ds, support, all_vertices, fc);
907 int cur_level = max_level;
908 int selector = 1 << cur_level;
910 clique_covering_graph_bulk,
915 do_clique_covering(filteredCG, ds, support, all_vertices, fc);
917 build_partitions(support, ds, current_partitions);
923 auto cp_it_end = current_partitions.end();
924 for(
auto cp_it = current_partitions.begin(); cp_it != cp_it_end; ++cp_it)
928 auto c_it_end = current_cliques.end();
929 for(
auto c_it = current_cliques.begin(); c_it != c_it_end;)
931 auto current = c_it++;
935 for(boost::tie(ei, ei_end) = boost::out_edges(rep, *completeCG); ei != ei_end; ++ei)
938 if(rep_target != cur)
940 std::vector<C_vertex> neighbors(boost::adjacent_vertices(cur, *completeCG).first,
941 boost::adjacent_vertices(cur, *completeCG).second);
942 std::sort(neighbors.begin(), neighbors.end());
943 if(!std::binary_search(neighbors.begin(), neighbors.end(), rep_target))
945 (*completeCG)[*ei].selector = 0;
948 c_it = current_cliques.begin();
954 for(boost::tie(ei, ei_end) = boost::out_edges(cur, *completeCG); ei != ei_end; ++ei)
957 if(cur_target != rep)
959 std::vector<C_vertex> neighbors(boost::adjacent_vertices(rep, *completeCG).first,
960 boost::adjacent_vertices(rep, *completeCG).second);
961 std::sort(neighbors.begin(), neighbors.end());
962 if(!std::binary_search(neighbors.begin(), neighbors.end(), cur_target))
964 (*completeCG)[*ei].selector = 0;
973 current_partitions.clear();
977 auto it_end = support.end();
978 for(
auto it = support.begin(); it != it_end;)
981 C_vertex rep = ds.find_set(*current);
983 if(rep != cur || boost::out_degree(rep, *completeCG) == 0)
986 support.erase(current);
991 selector = selector | 1 << cur_level;
994 clique_covering_graph_bulk,
996 &clique_covering_graph_bulk),
1000 boost::tie(ui, uiend) = boost::vertices(clique_covering_graph_bulk);
1002 support.insert(ui, uiend);
1005 build_partitions(support, ds, current_partitions);
1007 auto cp_it_end = current_partitions.end();
1008 for(
auto cp_it = current_partitions.begin(); cp_it != cp_it_end; ++cp_it)
1010 cliques.push_back(cp_it->second);
1011 cliques.back().insert(cp_it->first);
1017 std::ofstream f(filename.c_str());
1045 template <
typename vertex_type>
1056 typename boost::disjoint_sets<rank_pmap_type, pred_pmap_type>& ds,
1063 while(!support.empty())
1069 bool removed_vertex =
false;
1073 if(curr_clique.size() > 1)
1077 for(
auto av_it = all_vertices.begin(); av_it != av_it_end; ++av_it)
1079 C_vertex rep = ds.find_set(*av_it);
1080 if(curr_clique.find(rep) != curr_clique.end())
1082 curr_expandend_clique.insert(*av_it);
1091 curr_clique.erase(ds.find_set(vertex_to_be_removed));
1096 removed_vertex =
false;
1098 }
while(removed_vertex);
1101 C_vertex first = *curr_clique.begin();
1108 auto current = support.find(curr_vertex);
1109 THROW_ASSERT(current != support.end(),
"unexpected condition");
1110 if(cc_it != first_cc_it)
1112 ds.union_set(first, curr_vertex);
1114 support.erase(current);
1116 }
while(cc_it != cc_it_end);
1119 auto s_it_end = support.end();
1120 for(
auto s_it = support.begin(); s_it != s_it_end;)
1122 auto current = s_it++;
1123 if(boost::out_degree(*current, *CG) == 0)
1125 support.erase(current);
1129 support.insert(support_copy.begin(), support_copy.end());
1133 template <
typename vertex_type>
1144 typename boost::disjoint_sets<rank_pmap_type, pred_pmap_type>& ds,
1151 while(!support.empty())
1160 bool removed_vertex =
false;
1164 if(curr_clique.size() > 1)
1168 for(
auto av_it = all_vertices.begin(); av_it != av_it_end; ++av_it)
1170 C_vertex rep = ds.find_set(*av_it);
1171 if(curr_clique.find(rep) != curr_clique.end())
1173 curr_expandend_clique.insert(*av_it);
1181 curr_clique.erase(ds.find_set(vertex_to_be_removed));
1186 removed_vertex =
false;
1188 }
while(removed_vertex);
1191 C_vertex first = *curr_clique.begin();
1198 auto current = support.find(curr_vertex);
1199 THROW_ASSERT(current != support.end(),
"unexpected condition");
1200 if(cc_it != first_cc_it)
1202 ds.union_set(first, curr_vertex);
1204 support.erase(current);
1206 }
while(cc_it != cc_it_end);
1209 auto s_it_end = support.end();
1210 for(
auto s_it = support.begin(); s_it != s_it_end;)
1212 auto current = s_it++;
1213 if(boost::out_degree(*current, *CG) == 0)
1215 support.erase(current);
1219 support.insert(support_copy.begin(), support_copy.end());
1223 template <
typename vertex_type>
1230 typename boost::disjoint_sets<rank_pmap_type, pred_pmap_type>& ds,
1240 for(
auto av_it = all_vertices.begin(); av_it != av_it_end; ++av_it)
1242 C_vertex rep = ds.find_set(*av_it);
1243 if(rep == src || rep == tgt)
1245 curr_expandend_clique.insert(*av_it);
1252 #define MAX_EDGE_CONSIDERED 50 1255 typename boost::disjoint_sets<rank_pmap_type, pred_pmap_type>& ds,
1258 size_t h_max_neighbors = 0;
1260 bool first_iter =
true;
1263 for(boost::tie(sei0, sei0_end) = boost::out_edges(source, subgraph); sei0 != sei0_end; ++sei0)
1266 if(is_non_compliant(source, target, subgraph, all_vertices, ds, fc))
1271 size_t h_neighbors = 0, h_del_edges = 0;
1273 size_t src_out_degree = 0, tgt_out_degree = 0;
1276 for(boost::tie(sei, sei_end) = boost::out_edges(source, subgraph); sei != sei_end; ++sei)
1281 for(boost::tie(tei, tei_end) = boost::out_edges(target, subgraph); tei != tei_end; ++tei)
1287 std::inserter(common_neighbors, common_neighbors.end()));
1288 h_neighbors = common_neighbors.size();
1289 h_del_edges = src_out_degree + tgt_out_degree - h_neighbors - 1;
1290 if(first_iter || (h_neighbors > h_max_neighbors) ||
1291 (h_neighbors == h_max_neighbors && h_del_edges < h_min_del_edges))
1294 h_max_neighbors = h_neighbors;
1295 h_min_del_edges = h_del_edges;
1313 typename boost::disjoint_sets<rank_pmap_type, pred_pmap_type>& ds,
1316 size_t h_max_neighbors = 0;
1318 boost::graph_traits<cc_compatibility_graph>::edge_iterator ei, ei_end;
1319 bool first_iter =
true;
1321 for(boost::tie(ei, ei_end) =
boost::edges(subgraph); ei != ei_end; ++ei)
1324 source = boost::source(*ei, subgraph);
1326 if(is_non_compliant(source, target, subgraph, all_vertices, ds, fc))
1331 size_t h_neighbors = 0, h_del_edges = 0;
1333 size_t src_out_degree = 0, tgt_out_degree = 0;
1336 for(boost::tie(sei, sei_end) = boost::out_edges(source, subgraph); sei != sei_end; ++sei)
1341 for(boost::tie(tei, tei_end) = boost::out_edges(target, subgraph); tei != tei_end; ++tei)
1347 std::inserter(common_neighbors, common_neighbors.end()));
1348 h_neighbors = common_neighbors.size();
1349 h_del_edges = src_out_degree + tgt_out_degree - h_neighbors - 1;
1350 if(first_iter || (h_neighbors > h_max_neighbors) ||
1351 (h_neighbors == h_max_neighbors && h_del_edges < h_min_del_edges))
1354 h_max_neighbors = h_neighbors;
1355 h_min_del_edges = h_del_edges;
1379 typename boost::disjoint_sets<rank_pmap_type, pred_pmap_type>& ds,
1385 while(support.size() > 1)
1391 bool res_edge = select_edge(src, tgt, *CG, all_vertices, ds, fc);
1397 std::map<edge_descriptor, int> removed_edges;
1404 neighbors_src.insert(boost::adjacent_vertices(src, *CG).first, adjacent_vertices(src, *CG).second);
1406 neighbors_tgt.insert(boost::adjacent_vertices(tgt, *CG).first, adjacent_vertices(tgt, *CG).second);
1408 for(boost::tie(sei, sei_end) = boost::out_edges(src, *CG); sei != sei_end; ++sei)
1415 if(neighbors_tgt.find(target) == neighbors_tgt.end())
1417 removed_edges[*sei] = (*CG)[*sei].selector;
1418 (*CG)[*sei].selector = 0;
1421 for(boost::tie(sei, sei_end) = boost::out_edges(tgt, *CG); sei != sei_end; ++sei)
1428 if(neighbors_src.find(target) == neighbors_src.end())
1430 removed_edges[*sei] = (*CG)[*sei].selector;
1431 (*CG)[*sei].selector = 0;
1434 ds.union_set(src, tgt);
1436 THROW_ASSERT(rep == src || rep == tgt,
"unexpected condition");
1439 std::swap(src, tgt);
1441 current = support.find(tgt);
1442 THROW_ASSERT(current != support.end(),
"unexpected condition");
1443 support.erase(current);
1444 }
while(select_edge_start(src, tgt, *CG, all_vertices, ds, fc));
1446 current = support.find(src);
1447 THROW_ASSERT(current != support.end(),
"unexpected condition");
1448 support.erase(current);
1449 const auto re_it_end = removed_edges.end();
1450 for(
auto re_it = removed_edges.begin(); re_it != re_it_end; ++re_it)
1452 (*CG)[re_it->first].selector = re_it->second;
1458 auto s_it_end = support.end();
1459 for(
auto s_it = support.begin(); s_it != s_it_end;)
1462 if(boost::out_degree(*current, *CG) == 0)
1464 support.erase(current);
1469 support.insert(support_copy.begin(), support_copy.end());
1473 template <
typename vertex_type>
1481 size_t total_cost = 0;
1482 for(
const auto& clique_val : curr_cliques)
1497 std::vector<CustomOrderedSet<C_vertex>> best_cliques;
1502 for(
unsigned int i = 0; i < iterations; ++i)
1507 if(new_cost < best_cost)
1511 best_cost = new_cost;
1519 template <
typename vertex_type>
1526 std::vector<CustomUnorderedSet<C_vertex>>
cliques;
1540 std::map<size_t, CustomOrderedSet<boost::graph_traits<boost_cc_compatibility_graph>::vertex_descriptor>>
partitions;
1542 static const int COMPATIBILITY_EDGE = 1;
1543 static const int COMPATIBILITY_ALL_EDGES = ~0;
1549 using cg_vertices_size_type = boost::graph_traits<boost_cc_compatibility_graph>::vertices_size_type;
1550 using cg_vertex_index_map = boost::property_map<boost_cc_compatibility_graph, boost::vertex_index_t>::const_type;
1551 boost::iterator_property_map<cg_vertices_size_type*, cg_vertex_index_map, cg_vertices_size_type,
1552 cg_vertices_size_type&>
1555 std::vector<cg_vertices_size_type> color_vec;
1557 size_t n_vertices = boost::num_vertices(CG);
1558 color_vec.resize(n_vertices);
1560 boost::iterator_property_map<cg_vertices_size_type*, cg_vertex_index_map, cg_vertices_size_type,
1561 cg_vertices_size_type&>(&color_vec.front(), boost::get(boost::vertex_index, CG));
1565 size_t max_size = 1;
1566 boost::graph_traits<boost_cc_compatibility_graph>::vertex_iterator ui, uiend;
1567 for(boost::tie(ui, uiend) = boost::vertices(clique_covering_graph_bulk); ui != uiend; ++ui)
1569 cg_vertices_size_type c = color[*ui];
1570 auto p_it = partitions.find(c);
1571 if(p_it == partitions.end())
1574 singularity.insert(*ui);
1575 partitions[c] = singularity;
1579 p_it->second.insert(*ui);
1580 max_size =
std::max(max_size, static_cast<size_t>(p_it->second.size()));
1589 : clique_covering_graph_bulk(nvert),
1590 max_weight(
std::numeric_limits<int>::
min()),
1601 THROW_ASSERT(v2uv.find(element) == v2uv.end(),
"vertex already added");
1603 v2uv[element] = result =
boost::vertex(vindex, clique_covering_graph_bulk);
1611 void add_edge(
const vertex_type& src,
const vertex_type& dest,
int _weight)
override 1613 THROW_ASSERT(src != dest,
"autoloops are not allowed in a compatibility graph");
1614 THROW_ASSERT(v2uv.find(src) != v2uv.end(),
"src not added");
1615 THROW_ASSERT(v2uv.find(dest) != v2uv.end(),
"dest not added");
1616 THROW_ASSERT(_weight > 0,
"weights greater than 0 are allowed");
1617 C_vertex SRC = v2uv.find(src)->second;
1618 C_vertex DEST = v2uv.find(dest)->second;
1619 max_weight =
std::max(max_weight, _weight);
1626 return cliques.size();
1636 THROW_ASSERT(uv2v.find(*it) != uv2v.end(),
"vertex not added");
1637 result.insert(uv2v.find(*it)->second);
1647 num_cols = color_the_cc_compatibility_graph(clique_covering_graph_bulk);
1652 COMPATIBILITY_ALL_EDGES, &clique_covering_graph_bulk),
1657 for(
unsigned int i = 0; i < num_cols; ++i)
1660 cliques.push_back(empty);
1664 std::vector<CustomOrderedSet<boost::graph_traits<boost_cc_compatibility_graph>::vertex_descriptor>>
1666 for(
const auto& p : partitions)
1668 partitionsSorted.push_back(p.second);
1671 partitionsSorted.begin(), partitionsSorted.end(),
1674 return a.size() > b.size();
1676 size_t num_rows = num_cols;
1677 bool restart_bipartite;
1680 restart_bipartite =
false;
1683 for(
const auto& p : partitionsSorted)
1687 operations_research::SimpleLinearSumAssignment assignment;
1688 std::set<unsigned> column_already_assigned;
1689 auto v_it_end = p.end();
1690 auto v_it = p.begin();
1692 for(
unsigned i = 0; i < num_rows && !restart_bipartite; ++i)
1694 if(v_it == v_it_end)
1697 for(
unsigned int y = 0; y < num_cols; ++y)
1699 assignment.AddArcWithCost(static_cast<operations_research::NodeIndex>(i),
1700 static_cast<operations_research::NodeIndex>(y), 1);
1707 bool compatible_exist =
false;
1708 unsigned compatible_column = 0;
1709 for(
unsigned int y = 0; y < num_cols; ++y)
1711 if(cliques[y].find(*v_it) != cliques[y].end())
1715 compatible_exist =
true;
1716 compatible_column = y;
1717 THROW_ASSERT(column_already_assigned.count(y) == 0,
"unexpected condition");
1718 column_already_assigned.insert(y);
1722 if(compatible_exist)
1724 assignment.AddArcWithCost(static_cast<operations_research::NodeIndex>(i),
1725 static_cast<operations_research::NodeIndex>(compatible_column), 1);
1732 bool added_an_element =
false;
1734 for(
unsigned int y = 0; y < num_cols; ++y)
1736 if(column_already_assigned.find(y) == column_already_assigned.end())
1739 const auto& current_clique = cliques.at(y);
1742 bool to_be_removed =
false;
1743 for(
const auto cv : current_clique)
1746 auto edge_check = boost::edge(*v_it, cv, *completeCG);
1747 if(!edge_check.second)
1749 to_be_removed =
true;
1753 if(!to_be_removed && current_clique.size())
1755 curr_expandend_clique.insert(current_clique.begin(), current_clique.end());
1756 curr_expandend_clique.insert(*v_it);
1769 auto clique_cost = 1 + fc.
clique_cost(curr_expandend_clique, uv2v);
1770 assignment.AddArcWithCost(static_cast<operations_research::NodeIndex>(i),
1771 static_cast<operations_research::NodeIndex>(y), clique_cost);
1772 added_an_element =
true;
1780 if(!added_an_element)
1782 restart_bipartite =
true;
1790 if(!restart_bipartite && assignment.Solve() == operations_research::SimpleLinearSumAssignment::OPTIMAL)
1793 for(
unsigned int i = 0; i < num_rows; ++i)
1795 if(v_it != v_it_end)
1797 auto s = assignment.RightMate(i);
1799 cliques[s].insert(*v_it);
1807 THROW_ASSERT(max_num_cols == 0 || max_num_cols > num_cols,
1808 "Module binding does not have a solution\n Current number of resources=" +
STR(num_cols) +
1809 " Maximum number of resources " +
STR(max_num_cols));
1810 for(
unsigned sindex = 0; sindex < 1; ++sindex)
1815 cliques.push_back(empty);
1816 if(max_num_cols != 0 && num_cols == max_num_cols)
1821 for(
auto& cl : cliques)
1825 THROW_ASSERT(max_num_cols == 0 || max_num_cols >= num_cols,
1826 "Module binding does not have a solution\n Current number of resources=" +
STR(num_cols) +
1827 " Maximum number of resources " +
STR(max_num_cols));
1828 restart_bipartite =
true;
1832 }
while(restart_bipartite);
1835 for(
auto itC = cliques.begin(); itC != cliques.end();)
1839 itC = cliques.erase(itC);
1850 std::ofstream f(filename.c_str());
1857 THROW_ASSERT(v2uv.find(v) != v2uv.end(),
"vertex not added");
1858 C_vertex C_v = v2uv.find(v)->second;
1859 partitions[id].insert(C_v);
1860 num_cols =
std::max(static_cast<size_t>(partitions[
id].size()), num_cols);
1865 num_cols =
std::max(num_cols, n_resources);
1870 num_cols =
std::max(num_cols, n_resources);
1879 max_num_cols =
std::max(max_num_cols, n_resources);
1885 template <
typename VertexType>
1915 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 1916 #pragma GCC diagnostic pop 1919 #if defined(__clang__) 1920 #pragma clang diagnostic pop 1923 #endif // TTT_BASED_CLIQUE_COVERING_HPP vertex get_max_weight_vertex(CustomUnorderedSet< vertex > &ext, const Graph &g)
return the vertex of ext having the maximum degree with respect to the graph g
vertex get_max_weighted_adiacent_intersection(const CustomUnorderedSet< vertex > &subg, const CustomUnorderedSet< vertex > &cand, const Graph &g)
return the vertex of subg with the maximum intersection with cand
C_vertex add_vertex(const vertex_type &element, const std::string &name) override
add a vertex
boost::graph_traits< cc_compatibility_graph >::out_edge_iterator C_outEdgeIterator
virtual bool select_candidate_to_remove(const CustomOrderedSet< C_vertex > &candidate_clique, C_vertex &v, const CustomUnorderedMap< C_vertex, vertex_type > &converter, const cc_compatibility_graph &cg) const =0
CustomOrderedSet< vertex_type > get_clique(unsigned int i) override
Returns a clique.
void writeDot(const std::string &filename) const override
Writes a dotty representation of the actual graph.
void add_subpartitions(size_t, vertex_type) override
add subpartitions over which bipartite matching can start on
CustomUnorderedMap< C_vertex, std::string > names
name map for the C_vertex vertices
clique covering based on bipartite matching procedure
std::map< size_t, CustomOrderedSet< boost::graph_traits< boost_cc_compatibility_graph >::vertex_descriptor > > partitions
void exec(const filter_clique< vertex_type > &fc, check_clique< vertex_type > &) override
Abstract method that will execute clique covering algorithm.
compatibility_edge_writer(const boost_cc_compatibility_graph &_g)
Constructor.
typename boost::graph_traits< Graph >::vertex_iterator vertex_iterator
vertex iterator
typename boost::graph_traits< Graph >::out_edge_iterator edge_iterator
out edge iterator
Class computing the maximal weighted clique from a generic graph.
void max_resources(size_t) override
specify the maximum number of resources
property_traits< ColorMap >::value_type dsatur2_coloring(const VertexListGraph &G, ColorMap color)
coloring of a graph following the DSATUR heuristic (version2)
int compute_delta_weight(vertex q_vertex, CustomUnorderedSet< vertex > Q_set, const Graph &g)
compute the delta of the weight by adding q_vertex to the clique
typename boost::graph_traits< Graph >::adjacency_iterator adjacency_iterator
adjacency iterator
exceptions managed by PandA
Boost-based implementation of a heuristic sequential coloring algorithm based on the work of Daniel B...
const CustomOrderedSet< vertex > get_weighted_maximal_cliques(const Graph &g, int upper_bound)
return the weighted maximal clique of a graph g
boost_cc_compatibility_graph clique_covering_graph_bulk
bulk undirected graph
const CustomUnorderedMap< C_vertex, std::string > & names
names of the vertices
Definition of hash function for EdgeDescriptor.
TTT_maximal_weighted_clique_fast(CustomUnorderedMap< typename boost::graph_traits< Graph >::vertex_descriptor, std::string > &_names)
refcount< cc_compatibility_graph > cc_compatibility_graphRef
refcount version of cc_compatibility_graph
Functor used by boost::write_graphviz to write the edge info.
CliqueCovering_Algorithm
Defines all clique covering algorithm.
#define MAX_EDGE_CONSIDERED
OIter unordered_set_intersection(IIter1 first1, IIter1 last1, Container second, OIter result)
unordered_set_intersection
size_t num_cols
number of columns
coloring_based_clique_covering(bool _all_edges, unsigned int nvert)
constructor
redefinition of map to manage ordered/unordered structures
void expand(CustomUnorderedSet< vertex > &subg, CustomUnorderedSet< vertex > &cand, const Graph &g, int upper_bound)
recursive procedure expand defined in first cited paper
boost::iterator_property_map< std::vector< VertexIndex >::iterator, vertex_index_pmap_t > rank_pmap_type
rank property map definition
bool is_non_compliant(C_vertex src, C_vertex tgt, const cc_compatibility_graph &subgraph, const CustomUnorderedSet< C_vertex > &all_vertices, typename boost::disjoint_sets< rank_pmap_type, pred_pmap_type > &ds, const filter_clique< vertex_type > &fc)
CustomOrderedSet< vertex_type > get_clique(unsigned int i) override
Returns a clique.
TS_based_clique_covering(bool _all_edges, unsigned int nvert)
constructor
C_vertex add_vertex(const vertex_type &element, const std::string &name) override
add a vertex
CustomUnorderedMap< vertex_type, C_vertex > v2uv
map between vertex_type and C_vertex
#define STR(s)
Macro which performs a lexical_cast to a string.
bipartite_matching_clique_covering(unsigned int nvert)
constructor
Auxiliary methods for manipulating string.
void do_clique_covering(const cc_compatibility_graphRef CG, typename boost::disjoint_sets< rank_pmap_type, pred_pmap_type > &ds, CustomUnorderedSet< C_vertex > &support, const CustomUnorderedSet< C_vertex > &all_vertices, const filter_clique< vertex_type > &fc) override
size_t color_the_cc_compatibility_graph(const boost_cc_compatibility_graph &CG)
partition the set of vertex in set where each element is in conflict with the others the maximum size...
boost::adjacency_matrix< boost::undirectedS, boost::property< boost::vertex_index_t, std::size_t >, edge_compatibility_selector > boost_cc_compatibility_graph
bulk compatibility graph
Predicate functor object used to select the proper set of edges.
void suggest_max_resources(size_t) override
suggest that the problem have at worst no more than the given number of resources ...
boost::graph_traits< boost_cc_compatibility_graph >::vertices_size_type VertexIndex
vertices index type
int W_Q_max
weight of Q_max
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Functor used to reduce the size of clique: the rationale of filtering is that too many sharing may cr...
size_t max_num_cols
maximum number of columns
TTT_maximal_weighted_clique(CustomUnorderedMap< C_vertex, std::string > &_names)
typename boost::graph_traits< Graph >::adjacency_iterator adjacency_iterator
adjacency iterator
void add_subpartitions(size_t id, vertex_type v) override
add subpartitions over which bipartite matching can start on
typename boost::graph_traits< Graph >::out_edge_iterator edge_iterator
out edge iterator
vertex get_max_weight_vertex(CustomUnorderedSet< vertex > &ext, const Graph &g)
return the vertex of ext having the maximum edge weight with respect to the graph g ...
int max_weight
maximum weight
unsigned map[NUM_VERTICES]
absl::flat_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMap
int compute_delta_weight(vertex q_vertex, CustomUnorderedSet< vertex > Q_set, const Graph &g)
compute the delta of the weight by adding q_vertex to the clique
static refcount< clique_covering< VertexType > > create_solver(CliqueCovering_Algorithm solver, unsigned int nvert)
Creates a reference to desired solver.
CustomUnorderedMap< C_vertex, std::string > & names
CustomUnorderedMap< C_vertex, std::string > & names
redefinition of set to manage ordered/unordered structures
OIter unordered_set_difference(IIter1 first1, IIter1 last1, Container second, OIter result)
unordered_set_difference
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
void expand(CustomUnorderedSet< vertex > &subg, CustomUnorderedSet< vertex > &cand, const Graph &g)
recursive procedure expand defined in first cited paper
TTT_based_clique_covering(bool _all_edges, unsigned int nvert)
constructor
const boost_cc_compatibility_graph & g
reference to graph where the node is stored
void add_edge(const vertex_type &src, const vertex_type &dest, int _weight) override
add an edge
CustomUnorderedMap< C_vertex, std::string > names
name map for the C_vertex vertices
#define THRESHOLD_2_SIMPLIFY
void exec(const filter_clique< vertex_type > &fc, check_clique< vertex_type > &) override
Abstract method that will execute clique covering algorithm.
std::vector< CustomOrderedSet< C_vertex > > cliques
set of maximal clique computed
CustomOrderedSet< vertex > Q_max
set of vertices of the maximum clique found so far
bool select_edge_start(C_vertex source, C_vertex &tgt, const cc_compatibility_graph &subgraph, const CustomUnorderedSet< C_vertex > &all_vertices, typename boost::disjoint_sets< rank_pmap_type, pred_pmap_type > &ds, const filter_clique< vertex_type > &fc)
void operator()(std::ostream &out, const boost::graph_traits< cc_compatibility_graph >::edge_descriptor &e) const
Functor actually called by the boost library to perform the writing.
TTT_based_clique_covering_fast(bool _all_edges, unsigned int nvert)
constructor
Template definition of refcount.
CustomUnorderedSet< vertex > Q
set of vertices of the current clique
void suggest_max_resources(size_t) override
suggest that the problem have at worst no more than the given number of resources ...
std::vector< CustomUnorderedSet< C_vertex > > cliques
set of maximal clique computed
void max_resources(size_t n_resources) override
specify the maximum number of resources
void add_edge(const vertex_type &src, const vertex_type &dest, int _weight) override
add an edge
void operator()(std::ostream &out, const C_vertex &v) const
Functor used to print a node.
CustomUnorderedMap< vertex_type, C_vertex > v2uv
map between vertex_type and C_vertex
boost::property_map< boost_cc_compatibility_graph, boost::vertex_index_t >::type vertex_index_pmap_t
index map type
typename boost::graph_traits< Graph >::vertex_descriptor vertex
vertex object
vertex get_max_weighted_adiacent_intersection(const CustomUnorderedSet< vertex > &subg, const CustomUnorderedSet< vertex > &cand, const Graph &g)
return the vertex of subg with the maximum intersection with cand
void do_clique_covering(const cc_compatibility_graphRef CG, typename boost::disjoint_sets< rank_pmap_type, pred_pmap_type > &ds, CustomUnorderedSet< C_vertex > &support, const CustomUnorderedSet< C_vertex > &all_vertices, const filter_clique< vertex_type > &fc) override
RTS_based_clique_covering(bool _all_edges)
constructor
virtual void do_clique_covering(const cc_compatibility_graphRef filteredCG, boost::disjoint_sets< rank_pmap_type, pred_pmap_type > &ds, CustomUnorderedSet< C_vertex > &, const CustomUnorderedSet< C_vertex > &, const filter_clique< vertex_type > &)
void min_resources(size_t n_resources) override
specify the minimum number of resources
boost_cc_compatibility_graph clique_covering_graph_bulk
bulk undirected graph
void writeDot(const std::string &filename) const override
Writes a dotty representation of the actual graph.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
void build_partitions(CustomUnorderedSet< C_vertex > &support, boost::disjoint_sets< rank_pmap_type, pred_pmap_type > &ds, std::map< C_vertex, CustomOrderedSet< C_vertex >> ¤t_partitions)
build partitions
virtual size_t clique_cost(const CustomOrderedSet< C_vertex > &candidate_clique, const CustomUnorderedMap< C_vertex, vertex_type > &converter) const =0
CustomUnorderedMap< C_vertex, vertex_type > uv2v
map between C_vertex and vertex_type
size_t compute_cost(const std::vector< CustomOrderedSet< C_vertex >> &curr_cliques, const filter_clique< vertex_type > &fc)
bool select_edge(C_vertex &src, C_vertex &tgt, const cc_compatibility_graph &subgraph, const CustomUnorderedSet< C_vertex > &all_vertices, typename boost::disjoint_sets< rank_pmap_type, pred_pmap_type > &ds, const filter_clique< vertex_type > &fc)
Compute the heuristics and return the best matching edge.
void exec(const filter_clique< vertex_type > &fc)
boost::filtered_graph< boost_cc_compatibility_graph, cc_compatibility_graph_edge_selector< boost_cc_compatibility_graph >, cc_compatibility_graph_vertex_selector< boost_cc_compatibility_graph > > cc_compatibility_graph
compatibility graph
CustomUnorderedMap< C_vertex, vertex_type > uv2v
map between C_vertex and vertex_type
boost::iterator_property_map< std::vector< C_vertex >::iterator, vertex_index_pmap_t > pred_pmap_type
parent property map definition
unsigned counter[N_THREADS]
CustomOrderedSet< vertex > Q_max
set of vertices of the maximum clique found so far
void do_clique_covering(const cc_compatibility_graphRef CG, typename boost::disjoint_sets< rank_pmap_type, pred_pmap_type > &ds, CustomUnorderedSet< C_vertex > &support, const CustomUnorderedSet< C_vertex > &all_vertices, const filter_clique< vertex_type > &fc) override
second fast version of the TTT_based_clique_covering.
const std::string CliqueCovering_AlgorithmToString(const CliqueCovering_Algorithm clique_covering_algorithm)
Return the name corresponding to an clique covering algorithm enum.
typename boost::graph_traits< Graph >::vertex_iterator vertex_iterator
vertex iterator
void suggest_min_resources(size_t) override
suggest that the problem have at least a given number of resources
compatibility_node_info_writer(const CustomUnorderedMap< C_vertex, std::string > &_names)
Constructor.
fast version that just returns the first maximal clique found
size_t num_vertices() override
return the number of vertices of the clique
boost::graph_traits< cc_compatibility_graph >::vertex_descriptor C_vertex
cc_compatibility_graph vertex
void min_resources(size_t) override
specify the minimum number of resources
CustomUnorderedSet< vertex > Q
set of vertices of the current clique
virtual bool is_filtering() const =0
size_t num_vertices() override
return the number of vertices of the clique
void suggest_min_resources(size_t n_resources) override
suggest that the problem have at least a given number of resources
int get_last_W_Q_max()
return the last weight of the maximum clique
boost::graph_traits< cc_compatibility_graph >::edge_descriptor edge_descriptor
const CustomOrderedSet< vertex > get_weighted_maximal_cliques(const Graph &g)
return the weighted maximal clique of a graph g
typename boost::graph_traits< Graph >::vertex_descriptor vertex
vertex object
int W_Q_max
weight of Q_max
Functor used by boost::write_graphviz to write the node info.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...