Camargue
hypergraph.hpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5 
6 #ifndef CMR_HYPERGRAPH_H
7 #define CMR_HYPERGRAPH_H
8 
9 #include "cut_structs.hpp"
10 #include "lp_interface.hpp"
11 #include "cliq.hpp"
12 #include "lp_util.hpp"
13 #include "price_util.hpp"
14 #include "err_util.hpp"
15 
16 #include <algorithm>
17 #include <iostream>
18 #include <map>
19 #include <stdexcept>
20 #include <utility>
21 #include <vector>
22 
23 extern "C" {
24 #include <concorde/INCLUDE/tsp.h>
25 }
26 
27 namespace CMR {
28 namespace Sep {
29 
31 class HyperGraph {
32 public:
35  : sense('\0'), source_bank(nullptr), source_toothbank(nullptr) {}
36 
38  HyperGraph(CliqueBank &bank,
39  const CCtsp_lpcut_in &cc_lpcut,
40  const std::vector<int> &tour);
41 
43  HyperGraph(CliqueBank &bank, ToothBank &tbank,
44  const dominoparity &dp_cut, double _rhs,
45  const std::vector<int> &tour);
46 
48  HyperGraph(CliqueBank &bank,
49  const std::vector<int> &blossom_handle,
50  const std::vector<std::vector<int>> &tooth_edges);
51 
52  HyperGraph(HyperGraph &&H) noexcept;
53  HyperGraph &operator=(HyperGraph &&H) noexcept;
54 
56  void transfer_source(CliqueBank &new_source_bank);
57 
59  CCtsp_lpcut_in to_lpcut_in(const std::vector<int> &active_perm,
60  bool with_skeleton) const;
61 
62  ~HyperGraph();
63 
65  enum Type {
66  Domino = 0,
67  Subtour = 1,
68  Comb = 2,
69  Non = 3,
70  Branch = 3,
71  };
72 
73  Type cut_type() const;
74 
75  int tour_age() const { return t_age; }
76  int piv_age() const { return p_age; }
77 
78  bool fresh_cut() const { return t_age <= 0 || p_age <= 0; }
79 
81  double get_coeff(int end0, int end1) const;
82 
84  template <typename EndPt_type>
85  void get_coeffs(const std::vector<EndPt_type> &edges,
86  std::vector<int> &rmatind,
87  std::vector<double> &rmatval) const;
88 
89  char get_sense() const { return sense; }
90  double get_rhs() const { return rhs; }
91 
92  const std::vector<Clique::Ptr> &get_cliques() const { return cliques; }
93  const std::vector<Tooth::Ptr> &get_teeth() const { return teeth; }
94 
95  friend class ExternalCuts;
96 
97 private:
98  char sense;
99  double rhs;
100 
101  std::vector<Clique::Ptr> cliques;
102  std::vector<Tooth::Ptr> teeth;
103 
106 
107  int t_age;
108  int p_age;
109 };
110 
111 inline std::ostream &operator<<(std::ostream &os, HyperGraph::Type t)
112 {
113  using T = HyperGraph::Type;
114  if (t == T::Domino)
115  os << "Domino";
116  else if (t == T::Subtour)
117  os << "Subtour";
118  else if (t == T::Comb)
119  os << "Blossom/Comb/Wild Thing";
120  else if (t == T::Non)
121  os << "Non HyperGraph Gomory cut or branch constraint.";
122  return os;
123 }
124 
127 public:
129  ExternalCuts(const std::vector<int> &tour, const std::vector<int> &perm);
130 
131  ~ExternalCuts();
132 
134  void add_cut(const CCtsp_lpcut_in &cc_lpcut,
135  const std::vector<int> &current_tour);
136 
138  void add_cut(const dominoparity &dp_cut, const double rhs,
139  const std::vector<int> &current_tour);
140 
142  void add_cut(const std::vector<int> &blossom_handle,
143  const std::vector<std::vector<int>> &tooth_edges);
144 
146  void add_cut(HyperGraph &H);
147 
149  void add_cut();
150 
151  void reset_ages();
152  void tour_age_cuts(std::vector<double> duals);
153  void piv_age_cuts(std::vector<double> duals);
154 
156  void del_cuts(std::vector<int> &delset);
157 
159  const HyperGraph &get_cut(int lp_rownum) const {
160  return cuts[lp_rownum - node_count];
161  }
162 
163  const std::vector<HyperGraph> &get_cuts() const { return cuts; }
164 
165  int cut_count() const { return cuts.size(); }
166 
167  int pool_count() const { return cc_pool ? cc_pool->cutcount : 0; }
168 
169  const CliqueBank &get_cbank() const { return clique_bank; }
170  const ToothBank &get_tbank() const { return tooth_bank; };
171 
173  void get_col(int end0, int end1, std::vector<int> &cmatind,
174  std::vector<double> &cmatval) const;
175 
176  friend class Separator;
177 
178 private:
179  void pool_add(HyperGraph H);
180 
183  const int node_count;
184 
187 
189 
190  std::vector<HyperGraph> cuts;
191 
192  std::vector<HyperGraph> cut_pool;
193 
194  CCtsp_lpcuts *cc_pool;
195 
196  CCtsp_cuttree tightcuts;
197 
198 };
199 
201 
210 template <typename EndPt_type>
211 void HyperGraph::get_coeffs(const std::vector<EndPt_type> &edges,
212  std::vector<int> &rmatind,
213  std::vector<double> &rmatval) const
214 {
215  using std::vector;
216 
217  if (cut_type() == Type::Non)
218  throw std::logic_error("Tried HyperGraph::get_coeffs on Non cut.");
219 
220  rmatind.clear();
221  rmatval.clear();
222 
223  const vector<int> &def_tour = source_bank->ref_tour();
224  int ncount = def_tour.size();
225 
226  std::map<int, int> coeff_map;
227  vector<bool> node_marks(ncount, false);
228 
229  if (cut_type() != Type::Domino) {
230  for (const Clique::Ptr &clq_ref : cliques) {
231  for (const Segment &seg : clq_ref->seg_list())
232  for (int k = seg.start; k <= seg.end; ++k)
233  node_marks[def_tour[k]] = true;
234 
235  for (int i = 0; i < edges.size(); ++i) {
236  if (node_marks[edges[i].end[0]] !=
237  node_marks[edges[i].end[1]]) {
238  if (coeff_map.count(i))
239  coeff_map[i] += 1;
240  else
241  coeff_map[i] = 1;
242  }
243  }
244 
245  node_marks = vector<bool>(ncount, false);
246  }
247 
248  rmatind.reserve(coeff_map.size());
249  rmatval.reserve(coeff_map.size());
250 
251  for (std::pair<const int, int> &kv : coeff_map) {
252  rmatind.push_back(kv.first);
253  rmatval.push_back(kv.second);
254  }
255 
256  return;
257  } //else it is a domino cut
258 
259  const Clique::Ptr &handle_ref = cliques[0];
260  for (const Segment &seg : handle_ref->seg_list())
261  for (int k = seg.start; k <= seg.end; ++k)
262  node_marks[def_tour[k]] = true;
263 
264  for (int i = 0; i < edges.size(); ++i) {
265  bool e0 = node_marks[edges[i].end[0]];
266  bool e1 = node_marks[edges[i].end[1]];
267 
268  if (e0 && e1) {
269  if (coeff_map.count(i))
270  coeff_map[i] += 2;
271  else
272  coeff_map[i] = 2;
273  } else if (e0 != e1) {
274  if (coeff_map.count(i))
275  coeff_map[i] += 1;
276  else
277  coeff_map[i] = 1;
278  }
279  }
280 
281  node_marks = vector<bool>(ncount, false);
282 
283  const vector<int> &tooth_perm = source_toothbank->ref_perm();
284 
285  for (const Tooth::Ptr &t_ref : teeth) {
286  const Clique &root_clq = t_ref->set_pair()[0];
287  const Clique &bod_clq = t_ref->set_pair()[1];
288 
289  for (const Segment &seg : bod_clq.seg_list())
290  for (int k = seg.start; k <= seg.end; ++k)
291  node_marks[def_tour[k]] = true;
292 
293  for (int i = 0; i < edges.size(); ++i) {
294  int e0 = edges[i].end[0];
295  int e1 = edges[i].end[1];
296 
297  bool bod_e0 = node_marks[e0];
298  bool bod_e1 = node_marks[e1];
299 
300  if (bod_e0 && bod_e1) {
301  if (coeff_map.count(i))
302  coeff_map[i] += 2;
303  else
304  coeff_map[i] = 2;
305  } else if (bod_e0 != bod_e1) {
306  if (bod_e0) {
307  if (root_clq.contains(tooth_perm[e1])) {
308  if (coeff_map.count(i))
309  coeff_map[i] += 1;
310  else coeff_map[i] = 1;
311  }
312  } else { //bod_e1
313  if (root_clq.contains(tooth_perm[e0])) {
314  if (coeff_map.count(i))
315  coeff_map[i] += 1;
316  else coeff_map[i] = 1;
317  }
318  }
319  }
320  }
321 
322  std::fill(node_marks.begin(), node_marks.end(), false);
323  }
324 
325  int coeff_size = 0;
326 
327  for (std::pair<const int, int> &kv : coeff_map)
328  if (kv.second % 2 == 0)
329  ++coeff_size;
330 
331  rmatind.reserve(coeff_size);
332  rmatval.reserve(coeff_size);
333 
334  for (std::pair<const int, int> &kv : coeff_map) {
335  int ind = kv.first;
336  double coeff = kv.second;
337  coeff /= 2;
338  coeff = floor(coeff);
339  if (fabs(coeff) >= Epsilon::Zero) {
340  rmatind.push_back(ind);
341  rmatval.push_back(coeff);
342  }
343  }
344 }
345 
346 }
347 }
348 
349 #endif
~HyperGraph()
Destruct and decrement/delete Clique/Tooth refs.
Definition: hypergraph.cpp:236
A constraint to enforce branching.
Definition: hypergraph.hpp:70
const HyperGraph & get_cut(int lp_rownum) const
Return a cut corresponding to a row number index from the lp.
Definition: hypergraph.hpp:159
Miscellaneous functions, structs/enums, and constants for LPs.
Non HyperGraph cut: Gomory cut or branching constraint.
Definition: hypergraph.hpp:69
CCtsp_cuttree tightcuts
Cut tree for separation routines.
Definition: hypergraph.hpp:196
constexpr double Zero
Numbers less than this treated as zero.
Definition: util.hpp:62
Type
Enumeration for the types of HyperGraph inequalities.
Definition: hypergraph.hpp:65
CliqueBank pool_cliques
Bank of cliques for cuts in cut_pool.
Definition: hypergraph.hpp:188
Structure for storing simple DP inequalities.
Definition: cut_structs.hpp:84
Storage of a repository of Teeth, for use in building a HyperGraph.
Definition: cliq.hpp:225
ToothBank tooth_bank
Bank for adding and dispensing teeth.
Definition: hypergraph.hpp:186
void get_coeffs(const std::vector< EndPt_type > &edges, std::vector< int > &rmatind, std::vector< double > &rmatval) const
Get sparse coefficient row for a list of endpoints.
Definition: hypergraph.hpp:211
std::vector< HyperGraph > cut_pool
Pool of cuts pruned from CoreLP.
Definition: hypergraph.hpp:192
The external storage of a collection of HyperGraph cuts in a Relaxation.
Definition: hypergraph.hpp:126
std::shared_ptr< Clique > Ptr
shared_ptr alias declaration.
Definition: cliq.hpp:54
Reference counted storage of Cliques and Tooth objects.
const std::vector< int > & ref_perm() const
Const ref to saved perm for dereferencing.
Definition: cliq.hpp:264
Interface to the LP solver.
const std::vector< Segment > & seg_list() const
A constant reference to the list of segments in the Clique.
Definition: cliq.hpp:60
HyperGraph & operator=(HyperGraph &&H) noexcept
The move-assigned-from HyperGraph H is left null but valid as if default constructed.
Definition: hypergraph.cpp:132
CCtsp_lpcut_in to_lpcut_in(const std::vector< int > &active_perm, bool with_skeleton) const
Turn this cut into a CCtsp_lpcut_in.
Definition: hypergraph.cpp:181
ERROR HANDLING CLASSES AND ROUTINES.
A domino parity inequality.
Definition: hypergraph.hpp:66
A comb-like constraint.
Definition: hypergraph.hpp:68
Storage of a repository of Cliques, for use in building a HyperGraph.
Definition: cliq.hpp:167
bool contains(const int index) const
Returns true iff the Clique contains index.
Definition: cliq.hpp:69
Class for storing segment lists representing edges of a hypergraph.
Definition: cliq.hpp:34
Management of basic separation routines.
Definition: separator.hpp:25
std::shared_ptr< Tooth > Ptr
Pointer alias declaration.
Definition: cliq.hpp:104
double rhs
The righthand-side of the cut.
Definition: hypergraph.hpp:99
void transfer_source(CliqueBank &new_source_bank)
Change the source_bank to new_source_bank.
Definition: hypergraph.cpp:161
External representation of a cut added to the lp relaxation.
Definition: hypergraph.hpp:31
The namespace for this project.
Definition: abc_nodesel.hpp:20
std::vector< Clique::Ptr > cliques
The cliques comprising the cut.
Definition: hypergraph.hpp:101
std::vector< HyperGraph > cuts
List of the cuts in the CoreLP.
Definition: hypergraph.hpp:190
std::vector< Tooth::Ptr > teeth
The teeth comprising the cut.
Definition: hypergraph.hpp:102
const int node_count
Number of nodes in the Instance being tracked.
Definition: hypergraph.hpp:183
char sense
The inequality sense of the cut.
Definition: hypergraph.hpp:98
double get_coeff(int end0, int end1) const
Get the coefficient of an edge specified by endpoints.
Definition: hypergraph.cpp:260
CCtsp_lpcuts * cc_pool
Concorde rep of cut pool.
Definition: hypergraph.hpp:194
HyperGraph()
Default construct an empty Type::Non HyperGraph cut.
Definition: hypergraph.hpp:34
CliqueBank clique_bank
Bank for adding and dispensing cliques.
Definition: hypergraph.hpp:185
Simple utility struct for storing an interval of nodes.
Definition: util.hpp:198
An SEC.
Definition: hypergraph.hpp:67
CliqueBank * source_bank
The CliqueBank for dereferencing the cliques.
Definition: hypergraph.hpp:104
ToothBank * source_toothbank
The ToothBank for the teeth.
Definition: hypergraph.hpp:105
Constants and functions related to edge pricing.