PandA-2024.02
clique_covering.hpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2004-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
57 #ifndef CLIQUE_COVERING_HPP
58 #define CLIQUE_COVERING_HPP
59 
61 #include "custom_map.hpp" // for map
62 #include "custom_set.hpp" // for set
63 #include "dsatur2_coloring.hpp"
64 #include "exceptions.hpp"
65 #include "ortools/graph/assignment.h"
66 #include "refcount.hpp"
67 #include "string_manipulation.hpp"
68 
69 #include <algorithm> // for binary_search, sort
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> // for tie
77 #include <boost/version.hpp>
78 #include <cstddef> // for size_t
79 #include <iterator> // for inserter, reverse_...
80 #include <limits> // for numeric_limits
81 #include <ostream> // for operator<<, ostream
82 #include <string> // for string, operator+
83 #include <utility> // for pair, swap
84 #include <vector> // for vector, allocator
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"
89 #else
90 #pragma GCC diagnostic warning "-Wsign-compare"
91 #pragma GCC diagnostic warning "-Wsign-conversion"
92 #endif
93 
94 #if defined(__clang__)
95 #pragma clang diagnostic push
96 #pragma clang diagnostic ignored "-Wsign-compare"
97 #pragma clang diagnostic ignored "-Wsign-conversion"
98 #endif
99 
100 template <typename vertex_type>
101 struct check_clique;
102 template <typename vertex_type>
104 
106 template <typename IIter1, typename Container, typename OIter>
107 OIter unordered_set_difference(IIter1 first1, IIter1 last1, Container second, OIter result)
108 {
109  while(first1 != last1)
110  {
111  if(second.find(*first1) == second.end())
112  {
113  *result = *first1;
114  ++result;
115  }
116  ++first1;
117  }
118  return result;
119 }
120 
122 template <typename IIter1, typename Container, typename OIter>
123 OIter unordered_set_intersection(IIter1 first1, IIter1 last1, Container second, OIter result)
124 {
125  while(first1 != last1)
126  {
127  if(second.find(*first1) != second.end())
128  {
129  *result = *first1;
130  ++result;
131  }
132  ++first1;
133  }
134  return result;
135 }
136 
139 {
140  COLORING = 0,
149 };
150 
156 const std::string CliqueCovering_AlgorithmToString(const CliqueCovering_Algorithm clique_covering_algorithm);
157 
158 template <typename VertexType>
160 {
161  public:
165  clique_covering() = default;
166 
170  virtual ~clique_covering() = default;
171 
178  static typename refcount<clique_covering<VertexType>> create_solver(CliqueCovering_Algorithm solver,
179  unsigned int nvert);
180 
187  virtual C_vertex add_vertex(const VertexType& element, const std::string& name) = 0;
188 
196  virtual void add_edge(const VertexType& src, const VertexType& dest, int _weight) = 0;
197 
201  virtual size_t num_vertices() = 0;
202 
208  virtual void exec(const filter_clique<VertexType>& fc, check_clique<VertexType>& cq) = 0;
209 
215  virtual CustomOrderedSet<VertexType> get_clique(unsigned int i) = 0;
216 
221  virtual void writeDot(const std::string& filename) const = 0;
222 
228  virtual void add_subpartitions(size_t id, VertexType v) = 0;
229 
234  virtual void suggest_min_resources(size_t n_resources) = 0;
235 
240  virtual void suggest_max_resources(size_t n_resources) = 0;
241 
246  virtual void max_resources(size_t n_resources) = 0;
247 
252  virtual void min_resources(size_t n_resources) = 0;
253 };
254 
259 {
260  private:
263 
264  public:
269  {
270  }
271 
275  void operator()(std::ostream& out, const boost::graph_traits<cc_compatibility_graph>::edge_descriptor& e) const
276  {
277  out << "[label=\"" << g[e].weight << "\"]";
278  }
279 };
280 
285 {
286  private:
289 
290  public:
293  {
294  }
295 
297  void operator()(std::ostream& out, const C_vertex& v) const
298  {
299  out << "[label=\"" << names.find(v)->second << "\"]";
300  }
301 };
302 
306 template <typename Graph>
308 {
310  using vertex_iterator = typename boost::graph_traits<Graph>::vertex_iterator;
312  using vertex = typename boost::graph_traits<Graph>::vertex_descriptor;
314  using adjacency_iterator = typename boost::graph_traits<Graph>::adjacency_iterator;
316  using edge_iterator = typename boost::graph_traits<Graph>::out_edge_iterator;
317 
323  int W_Q;
325  int W_Q_max;
326 
328 
331  const CustomUnorderedSet<vertex>& cand, const Graph& g)
332  {
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;
336  const typename CustomUnorderedSet<vertex>::const_iterator it_end = subg.end();
337  for(auto it = subg.begin(); it != it_end; ++it)
338  {
339  int weight_intersection = 0;
340  edge_iterator ei, ei_end;
341  boost::tie(ei, ei_end) = boost::out_edges(*it, g);
342  for(; ei != ei_end; ++ei)
343  {
344  if(cand.find(boost::target(*ei, g)) != cand.end())
345  {
346  weight_intersection += g[*ei].weight;
347  }
348  }
349  if(weight_intersection > max_weighted_intersection)
350  {
351  max_weighted_intersection = weight_intersection;
352  result = *it;
353  }
354  }
355  THROW_ASSERT(max_weighted_intersection >= 0, "something wrong happened");
356  return result;
357  }
358 
361  {
362  vertex result = boost::graph_traits<Graph>::null_vertex();
363  int max_weight = -1;
364  THROW_ASSERT(!ext.empty(), "at least one element should belong to ext");
365  const typename CustomUnorderedSet<vertex>::const_iterator it_end = ext.end();
366  for(typename CustomUnorderedSet<vertex>::const_iterator it = ext.begin(); it != it_end; ++it)
367  {
368  int cur_weight = 0;
369  edge_iterator ei, ei_end;
370  boost::tie(ei, ei_end) = boost::out_edges(*it, g);
371  for(; ei != ei_end; ++ei)
372  {
373  cur_weight += g[*ei].weight;
374  }
375  if(cur_weight > max_weight)
376  {
377  result = *it;
378  max_weight = cur_weight;
379  }
380  }
381  THROW_ASSERT(max_weight >= 0, "something wrong happened");
382  return result;
383  }
384 
387  {
388  int result = 0;
389  edge_iterator ei, ei_end;
390  boost::tie(ei, ei_end) = boost::out_edges(q_vertex, g);
391  for(; ei != ei_end; ++ei)
392  {
393  if(Q_set.find(boost::target(*ei, g)) != Q_set.end())
394  {
395  result += g[*ei].weight;
396  }
397  }
398  return result;
399  }
400 
402  void expand(CustomUnorderedSet<vertex>& subg, CustomUnorderedSet<vertex>& cand, const Graph& g, int upper_bound)
403  {
404  if(subg.empty() && Q.size() >= Q_max.size())
405  {
406  if(Q.size() > Q_max.size() || W_Q > W_Q_max)
407  {
408  Q_max.clear();
409  Q_max.insert(Q.begin(), Q.end());
410  W_Q_max = W_Q;
411  // std::cerr << "clique W=" << W_Q_max << " size=" << Q_max.size() << std::endl;
412  }
413  return;
414  }
415  else if(cand.empty())
416  {
417  return;
418  }
419 
421  vertex u = get_max_weighted_adiacent_intersection(subg, cand, g);
422  // vertex u =get_max_adiacent_intersection(subg, cand, g);
424  adjacency_iterator vi, vi_end;
425  boost::tie(vi, vi_end) = boost::adjacent_vertices(u, g);
428  gamma_u.insert(vi, vi_end);
431  unordered_set_difference(cand.begin(), cand.end(), gamma_u, std::inserter(EXT_u, EXT_u.end()));
432  while(!EXT_u.empty())
433  {
434  vertex q = get_max_weight_vertex(EXT_u, g);
435  // vertex q = get_max_degree_vertex(EXT_u, g);
436  // std::cerr << names[q] << "," << std::endl;
437  Q.insert(q);
438  int W_Q_pre = W_Q;
440  int delta = compute_delta_weight(q, Q, g);
441  W_Q += delta;
442  boost::tie(vi, vi_end) = boost::adjacent_vertices(q, g);
444  gamma_q.insert(vi, vi_end);
446  unordered_set_intersection(subg.begin(), subg.end(), gamma_q, std::inserter(subg_q, subg_q.end()));
448  unordered_set_intersection(cand.begin(), cand.end(), gamma_q, std::inserter(cand_q, cand_q.end()));
449  expand(subg_q, cand_q, g, upper_bound);
450  if(upper_bound <= W_Q_max)
451  {
452  return;
453  }
454  cand.erase(q);
455  // std::cerr << "back," << std::endl;
456  Q.erase(q);
457  W_Q = W_Q_pre;
458  EXT_u.erase(q);
459  }
460  }
461 
462  public:
465  {
466  Q.clear();
467  Q_max.clear();
468  W_Q = 0;
469  W_Q_max = std::numeric_limits<int>::min();
472  vertex_iterator vi, vi_end;
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);
477  return Q_max;
478  }
479 
482  {
483  return W_Q_max;
484  }
486  : W_Q(0), W_Q_max(std::numeric_limits<int>::min()), names(_names)
487  {
488  }
489 };
490 
494 template <typename Graph>
496 {
498  using vertex_iterator = typename boost::graph_traits<Graph>::vertex_iterator;
500  using vertex = typename boost::graph_traits<Graph>::vertex_descriptor;
502  using adjacency_iterator = typename boost::graph_traits<Graph>::adjacency_iterator;
504  using edge_iterator = typename boost::graph_traits<Graph>::out_edge_iterator;
505 
511  int W_Q;
513  int W_Q_max;
514 
516 
519  const CustomUnorderedSet<vertex>& cand, const Graph& g)
520  {
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;
524  const typename CustomUnorderedSet<vertex>::const_iterator it_end = subg.end();
525  for(auto it = subg.begin(); it != it_end; ++it)
526  {
527  int weight_intersection = 0;
528  edge_iterator ei, ei_end;
529  boost::tie(ei, ei_end) = boost::out_edges(*it, g);
530  for(; ei != ei_end; ++ei)
531  {
532  if(cand.find(boost::target(*ei, g)) != cand.end())
533  {
534  weight_intersection += g[*ei].weight;
535  }
536  }
537  if(weight_intersection > max_weighted_intersection)
538  {
539  max_weighted_intersection = weight_intersection;
540  result = *it;
541  }
542  }
543  THROW_ASSERT(max_weighted_intersection >= 0, "something wrong happened");
544  return result;
545  }
546 
549  {
550  vertex result = boost::graph_traits<Graph>::null_vertex();
551  int max_weight = -1;
552  THROW_ASSERT(!ext.empty(), "at least one element should belong to ext");
553  const typename CustomUnorderedSet<vertex>::const_iterator it_end = ext.end();
554  for(typename CustomUnorderedSet<vertex>::const_iterator it = ext.begin(); it != it_end; ++it)
555  {
556  int cur_weight = 0;
557  edge_iterator ei, ei_end;
558  boost::tie(ei, ei_end) = boost::out_edges(*it, g);
559  for(; ei != ei_end; ++ei)
560  {
561  cur_weight += g[*ei].weight;
562  }
563  if(cur_weight > max_weight)
564  {
565  result = *it;
566  max_weight = cur_weight;
567  }
568  }
569  THROW_ASSERT(max_weight >= 0, "something wrong happened");
570  return result;
571  }
572 
575  {
576  int result = 0;
577  edge_iterator ei, ei_end;
578  boost::tie(ei, ei_end) = boost::out_edges(q_vertex, g);
579  for(; ei != ei_end; ++ei)
580  {
581  if(Q_set.find(boost::target(*ei, g)) != Q_set.end())
582  {
583  result += g[*ei].weight;
584  }
585  }
586  return result;
587  }
588 
591  {
592  if(subg.empty() && Q.size() >= Q_max.size())
593  {
594  if(Q.size() > Q_max.size() || W_Q > W_Q_max)
595  {
596  Q_max.clear();
597  Q_max.insert(Q.begin(), Q.end());
598  W_Q_max = W_Q;
599  // std::cerr << "clique W=" << W_Q_max << " size=" << Q_max.size() << std::endl;
600  }
601  return;
602  }
603  else if(cand.empty())
604  {
605  return;
606  }
607 
609  vertex u = get_max_weighted_adiacent_intersection(subg, cand, g);
610  // vertex u =get_max_adiacent_intersection(subg, cand, g);
612  adjacency_iterator vi, vi_end;
613  boost::tie(vi, vi_end) = boost::adjacent_vertices(u, g);
616  gamma_u.insert(vi, vi_end);
619  unordered_set_difference(cand.begin(), cand.end(), gamma_u, std::inserter(EXT_u, EXT_u.end()));
620  while(!EXT_u.empty())
621  {
622  vertex q = get_max_weight_vertex(EXT_u, g);
623  // vertex q = get_max_degree_vertex(EXT_u, g);
624  // std::cerr << names[q] << "," << std::endl;
625  Q.insert(q);
626  int W_Q_pre = W_Q;
628  int delta = compute_delta_weight(q, Q, g);
629  W_Q += delta;
630  // std::cerr << "W_Q=" << W_Q << std::endl;
631  boost::tie(vi, vi_end) = boost::adjacent_vertices(q, g);
633  gamma_q.insert(vi, vi_end);
635  unordered_set_intersection(subg.begin(), subg.end(), gamma_q, std::inserter(subg_q, subg_q.end()));
637  unordered_set_intersection(cand.begin(), cand.end(), gamma_q, std::inserter(cand_q, cand_q.end()));
638  expand(subg_q, cand_q, g);
639  // std::cerr << "W_Q_max=" << W_Q_max << std::endl;
640  if(W_Q_max >= 0)
641  {
642  return;
643  }
644  cand.erase(q);
645  // std::cerr << "back," << std::endl;
646  Q.erase(q);
647  W_Q = W_Q_pre;
648  EXT_u.erase(q);
649  }
650  }
651 
652  public:
655  {
656  Q.clear();
657  Q_max.clear();
658  W_Q = 0;
659  W_Q_max = std::numeric_limits<int>::min();
662  vertex_iterator vi, vi_end;
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);
667  return Q_max;
668  }
669 
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)
673  {
674  }
675 };
676 
677 template <typename vertex_type>
679 {
683  std::vector<CustomOrderedSet<C_vertex>> cliques;
687  static const int COMPATIBILITY_ALL_EDGES = ~0;
689  bool all_edges;
690  unsigned vindex;
691 
692  protected:
697 
698  public:
700  explicit coloring_based_clique_covering(bool _all_edges, unsigned int nvert)
701  : clique_covering_graph_bulk(nvert), max_level(0), all_edges(_all_edges), vindex(0)
702  {
703  }
704 
706  ~coloring_based_clique_covering() override = default;
707 
709  C_vertex add_vertex(const vertex_type& element, const std::string& name) override
710  {
712  THROW_ASSERT(v2uv.find(element) == v2uv.end(), "vertex already added");
714  v2uv[element] = result = boost::vertex(vindex, clique_covering_graph_bulk);
715  ++vindex;
716  uv2v[result] = element;
717  names[result] = name;
718  return result;
719  }
720 
722  void add_edge(const vertex_type& src, const vertex_type& dest, int _weight) override
723  {
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;
731  boost::add_edge(SRC, DEST, edge_compatibility_selector(1 << _weight, _weight), clique_covering_graph_bulk);
732  }
733 
735  size_t num_vertices() override
736  {
737  return cliques.size();
738  }
739 
740  CustomOrderedSet<vertex_type> get_clique(unsigned int i) override
741  {
743  CustomOrderedSet<C_vertex>& cur_clique = cliques[i];
744  auto it_end = cur_clique.end();
745  for(auto it = cur_clique.begin(); it != it_end; ++it)
746  {
747  THROW_ASSERT(uv2v.find(*it) != uv2v.end(), "vertex not added");
748  result.insert(uv2v.find(*it)->second);
749  }
750  return result;
751  }
752 
753  virtual void do_clique_covering(const cc_compatibility_graphRef filteredCG,
754  boost::disjoint_sets<rank_pmap_type, pred_pmap_type>& ds,
757  {
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&>
763  color;
764 
765  std::vector<cg_vertices_size_type> color_vec;
767 
768  using vertex_descriptor_cg = boost::graph_traits<conflict_graph>::vertex_descriptor;
770  std::vector<C_vertex> reverse_map;
771 
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)
775  {
776  ++num_vert;
777  }
778  auto* cg = new conflict_graph(num_vert);
779 
780  unsigned int vertex_index = 0;
781  BGL_FORALL_VERTICES(v, *filteredCG, cc_compatibility_graph)
782  {
783  vmap[v] = boost::vertex(vertex_index, *cg);
784  reverse_map.push_back(v);
785  ++vertex_index;
786  }
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));
791 
792  BGL_FORALL_VERTICES(u, *filteredCG, cc_compatibility_graph)
793  {
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());
797  BGL_FORALL_VERTICES(v, *filteredCG, cc_compatibility_graph)
798  {
799  if(u > v)
800  {
801  continue;
802  }
803  // Might want to check for self-loops
804  if(!std::binary_search(neighbors.begin(), neighbors.end(), v))
805  {
806  boost::add_edge(vmap[u], vmap[v], *cg);
807  }
808  }
809  }
810 
812  cg_vertices_size_type num_colors = dsatur2_coloring(*cg, color);
813  std::vector<unsigned int> colors(num_colors);
814 
815  for(unsigned int i = 0; i < num_colors; ++i)
816  {
818  }
819  for(unsigned int i = 0; i < vertex_index; ++i)
820  {
821  cg_vertices_size_type c = color_vec[i];
822  if(colors[c] == std::numeric_limits<unsigned int>::max())
823  {
824  colors[c] = i;
825  }
826  else
827  {
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);
831  }
832  }
833  }
834 
837  boost::disjoint_sets<rank_pmap_type, pred_pmap_type>& ds,
838  std::map<C_vertex, CustomOrderedSet<C_vertex>>& current_partitions)
839  {
840  auto it_end = support.end();
841  for(auto it = support.begin(); it != it_end;)
842  {
843  auto current = it++;
844  C_vertex rep = ds.find_set(*current);
845  C_vertex cur = *current;
846  if(rep != cur)
847  {
848  if(current_partitions.find(rep) == current_partitions.end())
849  {
850  CustomOrderedSet<C_vertex> singularity;
851  singularity.insert(cur);
852  current_partitions[rep] = singularity;
853  }
854  else
855  {
856  current_partitions.find(rep)->second.insert(cur);
857  }
858  }
859  else
860  {
861  if(current_partitions.find(rep) == current_partitions.end())
862  {
864  current_partitions[rep] = null_set;
865  }
866  }
867  }
868  }
869 
870 #define THRESHOLD_2_SIMPLIFY 200
872  {
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;
882  CustomUnorderedSet<C_vertex> all_vertices;
883 
884  boost::initialize_incremental_components(clique_covering_graph_bulk, ds);
885 
886  u_vertex_iterator ui, uiend;
887  for(boost::tie(ui, uiend) = boost::vertices(clique_covering_graph_bulk); ui != uiend; ++ui)
888  {
889  support.insert(*ui);
890  all_vertices.insert(*ui);
891  }
892  auto completeCG = cc_compatibility_graphRef(
893  new cc_compatibility_graph(clique_covering_graph_bulk,
895  COMPATIBILITY_ALL_EDGES, &clique_covering_graph_bulk),
897 
898  std::map<C_vertex, CustomOrderedSet<C_vertex>> current_partitions;
899 
900  if(all_edges || support.size() > THRESHOLD_2_SIMPLIFY)
901  {
902  do_clique_covering(completeCG, ds, support, all_vertices, fc);
903  }
904  else
905  {
907  int cur_level = max_level;
908  int selector = 1 << cur_level;
910  clique_covering_graph_bulk,
911  cc_compatibility_graph_edge_selector<boost_cc_compatibility_graph>(selector, &clique_covering_graph_bulk),
913  while(cur_level > 0)
914  {
915  do_clique_covering(filteredCG, ds, support, all_vertices, fc);
917  build_partitions(support, ds, current_partitions);
919  bool restart;
920  do
921  {
922  restart = false;
923  auto cp_it_end = current_partitions.end();
924  for(auto cp_it = current_partitions.begin(); cp_it != cp_it_end; ++cp_it)
925  {
926  C_vertex rep = cp_it->first;
927  CustomOrderedSet<C_vertex>& current_cliques = cp_it->second;
928  auto c_it_end = current_cliques.end();
929  for(auto c_it = current_cliques.begin(); c_it != c_it_end;)
930  {
931  auto current = c_it++;
932  C_vertex cur = *current;
933  C_outEdgeIterator ei, ei_end;
935  for(boost::tie(ei, ei_end) = boost::out_edges(rep, *completeCG); ei != ei_end; ++ei)
936  {
937  C_vertex rep_target = boost::target(*ei, *completeCG);
938  if(rep_target != cur)
939  {
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))
944  {
945  (*completeCG)[*ei].selector = 0;
946  // std::cerr << names[cur] << "|"<< names[rep] << " -0- " << names[rep_target] <<
947  // std::endl;
948  c_it = current_cliques.begin();
949  restart = true;
950  // std::cerr << "restart\n";
951  }
952  }
953  }
954  for(boost::tie(ei, ei_end) = boost::out_edges(cur, *completeCG); ei != ei_end; ++ei)
955  {
956  C_vertex cur_target = boost::target(*ei, *completeCG);
957  if(cur_target != rep)
958  {
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))
963  {
964  (*completeCG)[*ei].selector = 0;
965  // std::cerr << names[rep] << "|"<< names[cur] << " -1- " << names[cur_target] <<
966  // std::endl;
967  }
968  }
969  }
970  }
971  }
972  } while(restart);
973  current_partitions.clear();
974 
977  auto it_end = support.end();
978  for(auto it = support.begin(); it != it_end;)
979  {
980  auto current = it++;
981  C_vertex rep = ds.find_set(*current);
982  C_vertex cur = *current;
983  if(rep != cur || boost::out_degree(rep, *completeCG) == 0)
984  {
985  // std::cerr << "remove vertex " << names[cur] << std::endl;
986  support.erase(current);
987  }
988  }
990  --cur_level;
991  selector = selector | 1 << cur_level;
992  // std::cerr << "new selector " << cur_level << std::endl;
994  clique_covering_graph_bulk,
996  &clique_covering_graph_bulk),
998  }
1000  boost::tie(ui, uiend) = boost::vertices(clique_covering_graph_bulk);
1001  support.clear();
1002  support.insert(ui, uiend);
1003  }
1004 
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)
1009  {
1010  cliques.push_back(cp_it->second);
1011  cliques.back().insert(cp_it->first);
1012  }
1013  }
1014 
1015  void writeDot(const std::string& filename) const override
1016  {
1017  std::ofstream f(filename.c_str());
1018  boost::write_graphviz(f, clique_covering_graph_bulk, compatibility_node_info_writer(names),
1019  compatibility_edge_writer(clique_covering_graph_bulk));
1020  }
1021 
1022  void add_subpartitions(size_t, vertex_type) override
1023  {
1024  }
1025 
1026  void suggest_min_resources(size_t) override
1027  {
1028  }
1029 
1030  void suggest_max_resources(size_t) override
1031  {
1032  }
1033 
1034  void min_resources(size_t) override
1035  {
1036  }
1037 
1038  void max_resources(size_t) override
1039  {
1040  }
1041 };
1042 
1045 template <typename vertex_type>
1047 {
1048  public:
1050  explicit TTT_based_clique_covering_fast(bool _all_edges, unsigned int nvert)
1051  : coloring_based_clique_covering<vertex_type>(_all_edges, nvert)
1052  {
1053  }
1054 
1056  typename boost::disjoint_sets<rank_pmap_type, pred_pmap_type>& ds,
1057  CustomUnorderedSet<C_vertex>& support, const CustomUnorderedSet<C_vertex>& all_vertices,
1058  const filter_clique<vertex_type>& fc) override
1059  {
1061  // std::cerr << "Looking for a maximum weighted clique in a set of " << support.size() << std::endl;
1062  CustomUnorderedSet<C_vertex> support_copy(support);
1063  while(!support.empty())
1064  {
1066  // std::cerr << "Found one of size " << curr_clique.size() << std::endl;
1067 
1069  bool removed_vertex = false;
1070  C_vertex vertex_to_be_removed;
1071  do
1072  {
1073  if(curr_clique.size() > 1)
1074  {
1075  CustomOrderedSet<C_vertex> curr_expandend_clique;
1076  const CustomUnorderedSet<C_vertex>::const_iterator av_it_end = all_vertices.end();
1077  for(auto av_it = all_vertices.begin(); av_it != av_it_end; ++av_it)
1078  {
1079  C_vertex rep = ds.find_set(*av_it);
1080  if(curr_clique.find(rep) != curr_clique.end())
1081  {
1082  curr_expandend_clique.insert(*av_it);
1083  }
1084  }
1085 
1086  removed_vertex = fc.select_candidate_to_remove(curr_expandend_clique, vertex_to_be_removed,
1088  if(removed_vertex)
1089  {
1090  // std::cerr << "Vertex removed " << curr_clique.size() << std::endl;
1091  curr_clique.erase(ds.find_set(vertex_to_be_removed));
1092  }
1093  }
1094  else
1095  {
1096  removed_vertex = false;
1097  }
1098  } while(removed_vertex);
1099 
1100  // std::cerr << "Found one of size " << curr_clique.size() << std::endl;
1101  C_vertex first = *curr_clique.begin();
1102  const CustomOrderedSet<C_vertex>::const_iterator cc_it_end = curr_clique.end();
1103  const CustomOrderedSet<C_vertex>::const_iterator first_cc_it = curr_clique.begin();
1104  CustomOrderedSet<C_vertex>::const_iterator cc_it = first_cc_it;
1105  do
1106  {
1107  C_vertex curr_vertex = *cc_it;
1108  auto current = support.find(curr_vertex);
1109  THROW_ASSERT(current != support.end(), "unexpected condition");
1110  if(cc_it != first_cc_it)
1111  {
1112  ds.union_set(first, curr_vertex);
1113  }
1114  support.erase(current);
1115  ++cc_it;
1116  } while(cc_it != cc_it_end);
1117 
1119  auto s_it_end = support.end();
1120  for(auto s_it = support.begin(); s_it != s_it_end;)
1121  {
1122  auto current = s_it++;
1123  if(boost::out_degree(*current, *CG) == 0)
1124  {
1125  support.erase(current);
1126  }
1127  }
1128  }
1129  support.insert(support_copy.begin(), support_copy.end());
1130  }
1131 };
1132 
1133 template <typename vertex_type>
1135 {
1136  public:
1138  explicit TTT_based_clique_covering(bool _all_edges, unsigned int nvert)
1139  : coloring_based_clique_covering<vertex_type>(_all_edges, nvert)
1140  {
1141  }
1142 
1144  typename boost::disjoint_sets<rank_pmap_type, pred_pmap_type>& ds,
1145  CustomUnorderedSet<C_vertex>& support, const CustomUnorderedSet<C_vertex>& all_vertices,
1146  const filter_clique<vertex_type>& fc) override
1147  {
1149  CustomUnorderedSet<C_vertex> support_copy(support);
1150  int upper_bound = std::numeric_limits<int>::max();
1151  while(!support.empty())
1152  {
1153  // std::cerr << "Looking for a maximum weighted clique on a graph with " << support.size() << " vertices" <<
1154  // std::endl;
1155  CustomOrderedSet<C_vertex> curr_clique = MWC.get_weighted_maximal_cliques(*CG, upper_bound);
1157  upper_bound = MWC.get_last_W_Q_max();
1158 
1160  bool removed_vertex = false;
1161  C_vertex vertex_to_be_removed;
1162  do
1163  {
1164  if(curr_clique.size() > 1)
1165  {
1166  CustomOrderedSet<C_vertex> curr_expandend_clique;
1167  const CustomUnorderedSet<C_vertex>::const_iterator av_it_end = all_vertices.end();
1168  for(auto av_it = all_vertices.begin(); av_it != av_it_end; ++av_it)
1169  {
1170  C_vertex rep = ds.find_set(*av_it);
1171  if(curr_clique.find(rep) != curr_clique.end())
1172  {
1173  curr_expandend_clique.insert(*av_it);
1174  }
1175  }
1176  removed_vertex = fc.select_candidate_to_remove(curr_expandend_clique, vertex_to_be_removed,
1178  if(removed_vertex)
1179  {
1180  // std::cerr << "Vertex removed " << curr_clique.size() << std::endl;
1181  curr_clique.erase(ds.find_set(vertex_to_be_removed));
1182  }
1183  }
1184  else
1185  {
1186  removed_vertex = false;
1187  }
1188  } while(removed_vertex);
1189 
1190  // std::cerr << "Found one of size " << curr_clique.size() << std::endl;
1191  C_vertex first = *curr_clique.begin();
1192  const CustomOrderedSet<C_vertex>::const_iterator cc_it_end = curr_clique.end();
1193  const CustomOrderedSet<C_vertex>::const_iterator first_cc_it = curr_clique.begin();
1194  CustomOrderedSet<C_vertex>::const_iterator cc_it = first_cc_it;
1195  do
1196  {
1197  C_vertex curr_vertex = *cc_it;
1198  auto current = support.find(curr_vertex);
1199  THROW_ASSERT(current != support.end(), "unexpected condition");
1200  if(cc_it != first_cc_it)
1201  {
1202  ds.union_set(first, curr_vertex);
1203  }
1204  support.erase(current);
1205  ++cc_it;
1206  } while(cc_it != cc_it_end);
1207 
1209  auto s_it_end = support.end();
1210  for(auto s_it = support.begin(); s_it != s_it_end;)
1211  {
1212  auto current = s_it++;
1213  if(boost::out_degree(*current, *CG) == 0)
1214  {
1215  support.erase(current);
1216  }
1217  }
1218  }
1219  support.insert(support_copy.begin(), support_copy.end());
1220  }
1221 };
1222 
1223 template <typename vertex_type>
1225 {
1226  using edge_descriptor = boost::graph_traits<cc_compatibility_graph>::edge_descriptor;
1227 
1229  const CustomUnorderedSet<C_vertex>& all_vertices,
1230  typename boost::disjoint_sets<rank_pmap_type, pred_pmap_type>& ds,
1231  const filter_clique<vertex_type>& fc)
1232  {
1233  if(!fc.is_filtering())
1234  {
1235  return false;
1236  }
1237  C_vertex vertex_to_be_removed;
1238  CustomOrderedSet<C_vertex> curr_expandend_clique;
1239  const CustomUnorderedSet<C_vertex>::const_iterator av_it_end = all_vertices.end();
1240  for(auto av_it = all_vertices.begin(); av_it != av_it_end; ++av_it)
1241  {
1242  C_vertex rep = ds.find_set(*av_it);
1243  if(rep == src || rep == tgt)
1244  {
1245  curr_expandend_clique.insert(*av_it);
1246  }
1247  }
1248  return fc.select_candidate_to_remove(curr_expandend_clique, vertex_to_be_removed,
1250  }
1251 
1252 #define MAX_EDGE_CONSIDERED 50
1253  bool select_edge_start(C_vertex source, C_vertex& tgt, const cc_compatibility_graph& subgraph,
1254  const CustomUnorderedSet<C_vertex>& all_vertices,
1255  typename boost::disjoint_sets<rank_pmap_type, pred_pmap_type>& ds,
1256  const filter_clique<vertex_type>& fc)
1257  {
1258  size_t h_max_neighbors = 0;
1259  size_t h_min_del_edges = std::numeric_limits<size_t>::max();
1260  bool first_iter = true;
1261  C_outEdgeIterator sei0, sei0_end;
1262  auto counter = 0u;
1263  for(boost::tie(sei0, sei0_end) = boost::out_edges(source, subgraph); sei0 != sei0_end; ++sei0)
1264  {
1265  C_vertex target = boost::target(*sei0, subgraph);
1266  if(is_non_compliant(source, target, subgraph, all_vertices, ds, fc))
1267  {
1268  continue;
1269  }
1270 
1271  size_t h_neighbors = 0, h_del_edges = 0;
1272  C_outEdgeIterator sei, sei_end, tei, tei_end;
1273  size_t src_out_degree = 0, tgt_out_degree = 0;
1274  CustomUnorderedSet<C_vertex> src_neighbors, tgt_neighbors, common_neighbors;
1275 
1276  for(boost::tie(sei, sei_end) = boost::out_edges(source, subgraph); sei != sei_end; ++sei)
1277  {
1278  ++src_out_degree;
1279  src_neighbors.insert(boost::target(*sei, subgraph));
1280  }
1281  for(boost::tie(tei, tei_end) = boost::out_edges(target, subgraph); tei != tei_end; ++tei)
1282  {
1283  ++tgt_out_degree;
1284  tgt_neighbors.insert(boost::target(*tei, subgraph));
1285  }
1286  unordered_set_intersection(src_neighbors.begin(), src_neighbors.end(), tgt_neighbors,
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))
1292  {
1293  first_iter = false;
1294  h_max_neighbors = h_neighbors;
1295  h_min_del_edges = h_del_edges;
1296  tgt = target;
1297  }
1299  {
1300  break;
1301  }
1302  else
1303  {
1304  ++counter;
1305  }
1306  }
1307  return !first_iter;
1308  }
1309 
1311  bool select_edge(C_vertex& src, C_vertex& tgt, const cc_compatibility_graph& subgraph,
1312  const CustomUnorderedSet<C_vertex>& all_vertices,
1313  typename boost::disjoint_sets<rank_pmap_type, pred_pmap_type>& ds,
1314  const filter_clique<vertex_type>& fc)
1315  {
1316  size_t h_max_neighbors = 0;
1317  size_t h_min_del_edges = std::numeric_limits<size_t>::max();
1318  boost::graph_traits<cc_compatibility_graph>::edge_iterator ei, ei_end;
1319  bool first_iter = true;
1320  auto counter = 0u;
1321  for(boost::tie(ei, ei_end) = boost::edges(subgraph); ei != ei_end; ++ei)
1322  {
1323  C_vertex source, target;
1324  source = boost::source(*ei, subgraph);
1325  target = boost::target(*ei, subgraph);
1326  if(is_non_compliant(source, target, subgraph, all_vertices, ds, fc))
1327  {
1328  continue;
1329  }
1330 
1331  size_t h_neighbors = 0, h_del_edges = 0;
1332  C_outEdgeIterator sei, sei_end, tei, tei_end;
1333  size_t src_out_degree = 0, tgt_out_degree = 0;
1334  CustomUnorderedSet<C_vertex> src_neighbors, tgt_neighbors, common_neighbors;
1335 
1336  for(boost::tie(sei, sei_end) = boost::out_edges(source, subgraph); sei != sei_end; ++sei)
1337  {
1338  ++src_out_degree;
1339  src_neighbors.insert(boost::target(*sei, subgraph));
1340  }
1341  for(boost::tie(tei, tei_end) = boost::out_edges(target, subgraph); tei != tei_end; ++tei)
1342  {
1343  ++tgt_out_degree;
1344  tgt_neighbors.insert(boost::target(*tei, subgraph));
1345  }
1346  unordered_set_intersection(src_neighbors.begin(), src_neighbors.end(), tgt_neighbors,
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))
1352  {
1353  first_iter = false;
1354  h_max_neighbors = h_neighbors;
1355  h_min_del_edges = h_del_edges;
1356  src = source;
1357  tgt = target;
1358  }
1360  {
1361  break;
1362  }
1363  else
1364  {
1365  ++counter;
1366  }
1367  }
1368  return !first_iter;
1369  }
1370 
1371  public:
1373  explicit TS_based_clique_covering(bool _all_edges, unsigned int nvert)
1374  : coloring_based_clique_covering<vertex_type>(_all_edges, nvert)
1375  {
1376  }
1377 
1379  typename boost::disjoint_sets<rank_pmap_type, pred_pmap_type>& ds,
1380  CustomUnorderedSet<C_vertex>& support, const CustomUnorderedSet<C_vertex>& all_vertices,
1381  const filter_clique<vertex_type>& fc) override
1382  {
1383  CustomUnorderedSet<C_vertex> support_copy(support);
1384 
1385  while(support.size() > 1)
1386  {
1387  // std::cerr << "Looking for a maximum weighted clique on a graph with " << support.size() << " vertices"
1388  // << std::endl;
1390  C_vertex src, tgt;
1391  bool res_edge = select_edge(src, tgt, *CG, all_vertices, ds, fc);
1392  if(!res_edge)
1393  {
1394  break;
1395  }
1396 
1397  std::map<edge_descriptor, int> removed_edges;
1399 
1400  do
1401  {
1403  CustomOrderedSet<C_vertex> neighbors_src;
1404  neighbors_src.insert(boost::adjacent_vertices(src, *CG).first, adjacent_vertices(src, *CG).second);
1405  CustomOrderedSet<C_vertex> neighbors_tgt;
1406  neighbors_tgt.insert(boost::adjacent_vertices(tgt, *CG).first, adjacent_vertices(tgt, *CG).second);
1407  C_outEdgeIterator sei, sei_end;
1408  for(boost::tie(sei, sei_end) = boost::out_edges(src, *CG); sei != sei_end; ++sei)
1409  {
1410  C_vertex target = boost::target(*sei, *CG);
1411  if(tgt == target)
1412  {
1413  continue;
1414  }
1415  if(neighbors_tgt.find(target) == neighbors_tgt.end())
1416  {
1417  removed_edges[*sei] = (*CG)[*sei].selector;
1418  (*CG)[*sei].selector = 0;
1419  }
1420  }
1421  for(boost::tie(sei, sei_end) = boost::out_edges(tgt, *CG); sei != sei_end; ++sei)
1422  {
1423  C_vertex target = boost::target(*sei, *CG);
1424  if(src == target)
1425  {
1426  continue;
1427  }
1428  if(neighbors_src.find(target) == neighbors_src.end())
1429  {
1430  removed_edges[*sei] = (*CG)[*sei].selector;
1431  (*CG)[*sei].selector = 0;
1432  }
1433  }
1434  ds.union_set(src, tgt);
1435  C_vertex rep = ds.find_set(src);
1436  THROW_ASSERT(rep == src || rep == tgt, "unexpected condition");
1437  if(rep != src)
1438  {
1439  std::swap(src, tgt);
1440  }
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));
1445 
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)
1451  {
1452  (*CG)[re_it->first].selector = re_it->second;
1453  }
1454 
1455  // std::cerr << "Found one of size " << cluster_size << std::endl;
1456 
1458  auto s_it_end = support.end();
1459  for(auto s_it = support.begin(); s_it != s_it_end;)
1460  {
1461  current = s_it++;
1462  if(boost::out_degree(*current, *CG) == 0)
1463  {
1464  support.erase(current);
1465  }
1466  }
1467  }
1468 
1469  support.insert(support_copy.begin(), support_copy.end());
1470  }
1471 };
1472 
1473 template <typename vertex_type>
1475 {
1476  using edge_descriptor = boost::graph_traits<cc_compatibility_graph>::edge_descriptor;
1477 
1478  size_t compute_cost(const std::vector<CustomOrderedSet<C_vertex>>& curr_cliques,
1479  const filter_clique<vertex_type>& fc)
1480  {
1481  size_t total_cost = 0;
1482  for(const auto& clique_val : curr_cliques)
1483  {
1484  total_cost += fc.clique_cost(clique_val, coloring_based_clique_covering<vertex_type>::uv2v);
1485  }
1486  return total_cost;
1487  }
1488 
1489  public:
1491  explicit RTS_based_clique_covering(bool _all_edges) : TS_based_clique_covering<vertex_type>(_all_edges)
1492  {
1493  }
1494 
1496  {
1497  std::vector<CustomOrderedSet<C_vertex>> best_cliques;
1498  size_t best_cost = std::numeric_limits<size_t>::max();
1499  size_t iterations =
1501  // std::cerr << "N iterations " << iterations << std::endl;
1502  for(unsigned int i = 0; i < iterations; ++i)
1503  {
1506  size_t new_cost = compute_cost(coloring_based_clique_covering<vertex_type>::cliques, fc);
1507  if(new_cost < best_cost)
1508  {
1509  // std::cerr << "New cost " << new_cost << "-" << i << std::endl;
1511  best_cost = new_cost;
1512  }
1513  }
1515  }
1516 };
1517 
1519 template <typename vertex_type>
1521 {
1522  private:
1526  std::vector<CustomUnorderedSet<C_vertex>> cliques;
1535  unsigned int vindex;
1537  size_t num_cols;
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;
1544 
1548  {
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&>
1553  color;
1554 
1555  std::vector<cg_vertices_size_type> color_vec;
1556 
1557  size_t n_vertices = boost::num_vertices(CG);
1558  color_vec.resize(n_vertices);
1559  color =
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));
1562 
1564  dsatur2_coloring(CG, color);
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)
1568  {
1569  cg_vertices_size_type c = color[*ui];
1570  auto p_it = partitions.find(c);
1571  if(p_it == partitions.end())
1572  {
1574  singularity.insert(*ui);
1575  partitions[c] = singularity;
1576  }
1577  else
1578  {
1579  p_it->second.insert(*ui);
1580  max_size = std::max(max_size, static_cast<size_t>(p_it->second.size()));
1581  }
1582  }
1583  return max_size;
1584  }
1585 
1586  public:
1589  : clique_covering_graph_bulk(nvert),
1590  max_weight(std::numeric_limits<int>::min()),
1591  vindex(0),
1592  num_cols(0),
1593  max_num_cols(0)
1594  {
1595  }
1596 
1598  C_vertex add_vertex(const vertex_type& element, const std::string& name) override
1599  {
1600  C_vertex result;
1601  THROW_ASSERT(v2uv.find(element) == v2uv.end(), "vertex already added");
1603  v2uv[element] = result = boost::vertex(vindex, clique_covering_graph_bulk);
1604  ++vindex;
1605  uv2v[result] = element;
1606  names[result] = name;
1607  return result;
1608  }
1609 
1611  void add_edge(const vertex_type& src, const vertex_type& dest, int _weight) override
1612  {
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);
1620  boost::add_edge(SRC, DEST, edge_compatibility_selector(COMPATIBILITY_EDGE, _weight), clique_covering_graph_bulk);
1621  }
1622 
1624  size_t num_vertices() override
1625  {
1626  return cliques.size();
1627  }
1628 
1630  {
1632  CustomUnorderedSet<C_vertex>& cur_clique = cliques[i];
1633  CustomUnorderedSet<C_vertex>::const_iterator it_end = cur_clique.end();
1634  for(CustomUnorderedSet<C_vertex>::const_iterator it = cur_clique.begin(); it != it_end; ++it)
1635  {
1636  THROW_ASSERT(uv2v.find(*it) != uv2v.end(), "vertex not added");
1637  result.insert(uv2v.find(*it)->second);
1638  }
1639  return result;
1640  }
1641 
1643  {
1646  partitions.clear();
1647  num_cols = color_the_cc_compatibility_graph(clique_covering_graph_bulk);
1648  // std::cerr << "initial max_num_cols " << max_num_cols << std::endl;
1649  auto completeCG = cc_compatibility_graphRef(
1650  new cc_compatibility_graph(clique_covering_graph_bulk,
1652  COMPATIBILITY_ALL_EDGES, &clique_covering_graph_bulk),
1654 
1655  // std::cerr << "cliques.size " << cliques.size() << "\n";
1657  for(unsigned int i = 0; i < num_cols; ++i)
1658  {
1660  cliques.push_back(empty);
1661  }
1662  // std::cerr << "num_cols " << num_cols << "\n";
1663  // std::cerr << "partitions.size " << partitions.size() << "\n";
1664  std::vector<CustomOrderedSet<boost::graph_traits<boost_cc_compatibility_graph>::vertex_descriptor>>
1665  partitionsSorted;
1666  for(const auto& p : partitions)
1667  {
1668  partitionsSorted.push_back(p.second);
1669  }
1670  std::sort(
1671  partitionsSorted.begin(), partitionsSorted.end(),
1674  return a.size() > b.size();
1675  });
1676  size_t num_rows = num_cols;
1677  bool restart_bipartite;
1678  do
1679  {
1680  restart_bipartite = false;
1682  // int pindex = 0;
1683  for(const auto& p : partitionsSorted)
1684  {
1685  // std::cerr << "partition" << pindex++ << "\n";
1686  // std::cerr << "partition size=" << p.size() << "\n";
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();
1691  // auto min_to_be_removed = std::numeric_limits<unsigned>::max();
1692  for(unsigned i = 0; i < num_rows && !restart_bipartite; ++i)
1693  {
1694  if(v_it == v_it_end)
1695  {
1696  // std::cerr << "over\n";
1697  for(unsigned int y = 0; y < num_cols; ++y)
1698  {
1699  assignment.AddArcWithCost(static_cast<operations_research::NodeIndex>(i),
1700  static_cast<operations_research::NodeIndex>(y), 1);
1701  // std::cerr << "i" << i << "-> y" << y << " (1)\n";
1702  }
1703  }
1704  else
1705  {
1707  bool compatible_exist = false;
1708  unsigned compatible_column = 0;
1709  for(unsigned int y = 0; y < num_cols; ++y)
1710  {
1711  if(cliques[y].find(*v_it) != cliques[y].end())
1712  {
1714  // std::cerr << "already assigned to a clique\n";
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);
1719  break;
1720  }
1721  }
1722  if(compatible_exist)
1723  {
1724  assignment.AddArcWithCost(static_cast<operations_research::NodeIndex>(i),
1725  static_cast<operations_research::NodeIndex>(compatible_column), 1);
1726  // std::cerr << "i" << i << "-> y" << compatible_column << " (1)\n";
1727  // std::cerr << "compatible_exist\n";
1728  }
1729  else
1730  {
1731  // std::cerr << "compatible does not exist " << max_num_cols << " " << num_cols << "\n";
1732  bool added_an_element = false;
1733  // unsigned to_removed_number = 0;
1734  for(unsigned int y = 0; y < num_cols; ++y)
1735  {
1736  if(column_already_assigned.find(y) == column_already_assigned.end())
1737  {
1738  CustomOrderedSet<C_vertex> curr_expandend_clique;
1739  const auto& current_clique = cliques.at(y);
1740  // std::cerr << "current_clique.size=" << current_clique.size() << "y=" << y << "\n";
1741  // std::cerr << "y=" << y << "\n";
1742  bool to_be_removed = false;
1743  for(const auto cv : current_clique)
1744  {
1745  // std::cerr << "*v_it=" << *v_it << " cv=" << cv << "\n";
1746  auto edge_check = boost::edge(*v_it, cv, *completeCG);
1747  if(!edge_check.second)
1748  {
1749  to_be_removed = true;
1750  break;
1751  }
1752  }
1753  if(!to_be_removed && current_clique.size())
1754  {
1755  curr_expandend_clique.insert(current_clique.begin(), current_clique.end());
1756  curr_expandend_clique.insert(*v_it);
1757  // std::cerr << "curr_expandend_clique.size=" << curr_expandend_clique.size() << "\n";
1758  C_vertex vertex_to_be_removed;
1759  to_be_removed = fc.select_candidate_to_remove(curr_expandend_clique, vertex_to_be_removed,
1760  uv2v, *completeCG);
1761  }
1762  if(to_be_removed)
1763  {
1764  // std::cerr << "to be removed\n";
1765  //++to_removed_number;
1766  }
1767  if(!to_be_removed)
1768  {
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;
1773  // std::cerr << "i" << i << "-> y" << y << " (" << clique_cost << ")\n";
1774  }
1775  }
1776  }
1777  // min_to_be_removed = std::min(min_to_be_removed, to_removed_number);
1778  // std::cerr << "to_removed_number=" << to_removed_number << " p.size() " << p.size()
1779  // << " num_columns " << num_cols << "\n";
1780  if(!added_an_element)
1781  {
1782  restart_bipartite = true;
1783  //++skip_infeasibles;
1784  // std::cerr << "restart the problem (" + STR(num_cols) + ")\n";
1785  }
1786  }
1787  ++v_it;
1788  }
1789  }
1790  if(!restart_bipartite && assignment.Solve() == operations_research::SimpleLinearSumAssignment::OPTIMAL)
1791  {
1792  v_it = p.begin();
1793  for(unsigned int i = 0; i < num_rows; ++i)
1794  {
1795  if(v_it != v_it_end)
1796  {
1797  auto s = assignment.RightMate(i);
1798  // std::cerr << "assign " << names[*v_it] << " to clique" << s << "\n";
1799  cliques[s].insert(*v_it);
1800  ++v_it;
1801  }
1802  }
1803  }
1804  else
1805  {
1806  // std::cerr << "restart assignment problem " << num_cols << "\n";
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)
1811  {
1812  ++num_cols;
1813  ++num_rows;
1815  cliques.push_back(empty);
1816  if(max_num_cols != 0 && num_cols == max_num_cols)
1817  {
1818  break;
1819  }
1820  }
1821  for(auto& cl : cliques)
1822  {
1823  cl.clear();
1824  }
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;
1829  break;
1830  }
1831  }
1832  } while(restart_bipartite);
1833 
1835  for(auto itC = cliques.begin(); itC != cliques.end();)
1836  {
1837  if(itC->empty())
1838  {
1839  itC = cliques.erase(itC);
1840  }
1841  else
1842  {
1843  ++itC;
1844  }
1845  }
1846  }
1847 
1848  void writeDot(const std::string& filename) const override
1849  {
1850  std::ofstream f(filename.c_str());
1851  boost::write_graphviz(f, clique_covering_graph_bulk, compatibility_node_info_writer(names),
1852  compatibility_edge_writer(clique_covering_graph_bulk));
1853  }
1854 
1855  void add_subpartitions(size_t id, vertex_type v) override
1856  {
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);
1861  }
1862 
1863  void suggest_min_resources(size_t n_resources) override
1864  {
1865  num_cols = std::max(num_cols, n_resources);
1866  }
1867 
1868  void min_resources(size_t n_resources) override
1869  {
1870  num_cols = std::max(num_cols, n_resources);
1871  }
1872 
1873  void suggest_max_resources(size_t) override
1874  {
1875  }
1876 
1877  void max_resources(size_t n_resources) override
1878  {
1879  max_num_cols = std::max(max_num_cols, n_resources);
1880  }
1881 };
1882 
1883 //******************************************************************************************************************
1884 
1885 template <typename VertexType>
1887  unsigned int nvert)
1888 {
1889  switch(solver)
1890  {
1894  return refcount<clique_covering<VertexType>>(new coloring_based_clique_covering<VertexType>(false, nvert));
1898  return refcount<clique_covering<VertexType>>(new TTT_based_clique_covering<VertexType>(false, nvert));
1902  return refcount<clique_covering<VertexType>>(new TTT_based_clique_covering_fast<VertexType>(false, nvert));
1906  return refcount<clique_covering<VertexType>>(new TS_based_clique_covering<VertexType>(false, nvert));
1909  default:
1910  THROW_UNREACHABLE("This clique covering algorithm has not been implemented");
1911  }
1913 }
1914 
1915 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
1916 #pragma GCC diagnostic pop
1917 #endif
1918 
1919 #if defined(__clang__)
1920 #pragma clang diagnostic pop
1921 #endif
1922 
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.
string target
Definition: lenet_tvm.py:16
std::string filename
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.
Definition: graph.hpp:1321
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
#define min(x, y)
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
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.
#define max
Definition: backprop.h:17
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
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
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
unsigned edges[4545]
Definition: graph.h:25
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 ...
unsigned map[NUM_VERTICES]
Definition: bfs.c:12
absl::flat_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMap
Definition: custom_map.hpp:148
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.
Definition: graph.hpp:1303
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.
int result[SIZE]
Definition: adpcm.c:800
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...
Definition: refcount.hpp:94
void build_partitions(CustomUnorderedSet< C_vertex > &support, boost::disjoint_sets< rank_pmap_type, pred_pmap_type > &ds, std::map< C_vertex, CustomOrderedSet< C_vertex >> &current_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]
Definition: data.c:3
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
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 ...
Definition: exceptions.hpp:289

Generated on Mon Feb 12 2024 13:02:50 for PandA-2024.02 by doxygen 1.8.13