Camargue
cc_lpcuts.hpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5 
6 #ifndef CMR_CC_LPCUTS_H
7 #define CMR_CC_LPCUTS_H
8 
9 #include "graph.hpp"
10 #include "datagroups.hpp"
11 
12 #include <stdexcept>
13 #include <string>
14 #include <memory>
15 #include <vector>
16 
17 extern "C" {
18 #include <concorde/INCLUDE/tsp.h>
19 }
20 
21 
22 namespace CMR {
23 
25 namespace Sep {
26 
28 class TourGraph {
29 public:
30  TourGraph() noexcept;
31 
32  TourGraph(const std::vector<double> &tour_edges,
33  const std::vector<Graph::Edge> &edges,
34  const std::vector<int> &perm);
35 
36  TourGraph(TourGraph &&T) noexcept;
37  TourGraph &operator=(TourGraph &&T) noexcept;
38 
39  ~TourGraph();
40 
41  TourGraph(const TourGraph &T) = delete;
42  TourGraph &operator=(const TourGraph &T) = delete;
43 
44 
45 
46  CCtsp_lpgraph* pass_ptr() { return &L; }
47  double* tour_array() { return &d_tour[0]; }
48  int node_count() const { return L.ncount; }
49 
50 private:
51  std::vector<double> d_tour;
52  CCtsp_lpgraph L;
53 };
54 
56 class LPcutList {
57 public:
58  LPcutList() noexcept;
59 
61  LPcutList(CCtsp_lpcut_in *head, int count) noexcept;
62 
63  LPcutList(LPcutList &&L) noexcept;
64  LPcutList &operator=(LPcutList &&L) noexcept;
65 
66  void push_front(CCtsp_lpcut_in *new_head);
67 
68  void splice(LPcutList &&L);
69 
70  int size() const { return cutcount; }
71  bool empty() const { return cutcount == 0; }
72 
73  CCtsp_lpcut_in *begin() { return head_cut.get(); }
74  const CCtsp_lpcut_in *begin() const { return head_cut.get(); }
75 
76  void filter_primal(TourGraph &TG);
77 
78  void clear();
79 
80 private:
82  struct hungry_delete {
83  void operator()(CCtsp_lpcut_in *cut) const {
84  for(auto it = cut; it; it = cut){
85  cut = it->next;
86  CCtsp_free_lpcut_in(it);
87  CC_IFFREE(it, CCtsp_lpcut_in);
88  }
89  }
90  };
91  std::unique_ptr<CCtsp_lpcut_in, hungry_delete> head_cut;
92  int cutcount;
93 };
94 
95 
98 class CCsepBase {
99 public:
100  CCsepBase(std::vector<int> &supp_elist,
101  std::vector<double> &supp_ecap,
102  TourGraph &_TG, Sep::LPcutList &_cutq) :
103  elist(supp_elist), ecap(supp_ecap), TG(_TG), cutq(_cutq) {}
104 
106  virtual bool find_cuts() = 0;
107 
108  bool filter_primal = true;
109 
110 protected:
111  std::vector<int> &elist;
112  std::vector<double> &ecap;
113 
114  TourGraph &TG;
115 
116  Sep::LPcutList &cutq;
117 };
118 
120 class LocalCuts : public CCsepBase {
121 public:
122  LocalCuts(std::vector<int> &elist, std::vector<double> &ecap,
123  TourGraph &TG, Sep::LPcutList &cutq, int seed) :
124  CCsepBase(elist, ecap, TG, cutq), random_seed(seed) {}
125 
126  bool find_cuts();
127 
128  static constexpr int MaxChunkSize = 16;
129  int current_max = 8;
130  int random_seed;
131  bool spheres = false;
132 };
133 
135 using CCsepCall = decltype(&CCtsp_segment_cuts);
136 
149 template <CCsepCall sep_fn, bool check_filter_primal, const char *fn_name>
150 class ConcordeSeparator : public CCsepBase {
151 public:
152  ConcordeSeparator(std::vector<int> &elist, std::vector<double> &ecap,
153  TourGraph &TG, Sep::LPcutList &cutq) :
154  CCsepBase(elist, ecap, TG, cutq) {}
155 
156  bool find_cuts()
157  {
158  int cutcount = 0;
159  CCtsp_lpcut_in *head = NULL;
160  std::string err_msg(fn_name); err_msg += " failed";
161 
162 
163  if (sep_fn(&head, &cutcount, TG.node_count(), ecap.size(),
164  &elist[0], &ecap[0]))
165  throw std::runtime_error(err_msg);
166 
167  if (cutcount == 0)
168  return false;
169 
170  cutq = LPcutList(head, cutcount);
171 
172  if (check_filter_primal && filter_primal)
173  cutq.filter_primal(TG);
174 
175  return !cutq.empty();
176  }
177 };
178 
183 constexpr char seg_fname[] = "CCtsp_segment_cuts";
185 constexpr char con_fname[] = "CCtsp_connect_cuts";
186 constexpr char ex_fname[] = "CCtsp_exact_subtours";
187 constexpr char f2m_fname[] = "CCtsp_fastblossom";
188 constexpr char gh2m_fname[] = "CCtsp_ghfastblossom";
189 constexpr char blk_fname[] = "CCtsp_block_combs";
191 
195 
199 
202 
205 
208 
211 
215 inline int BlkCombCall(CCtsp_lpcut_in **c, int *cutcount,
216  int ncount, int ecount, int *elist, double *ecap)
217 {
218  return CCtsp_block_combs(c, cutcount, ncount, ecount, elist, ecap, 1);
219 }
220 
223 
225 
226 }
227 }
228 
229 #endif
Deleter to clear the linked list.
Definition: cc_lpcuts.hpp:82
decltype(&CCtsp_segment_cuts) CCsepCall
Alias declaration for Concorde separator call prototype.
Definition: cc_lpcuts.hpp:135
Primal separation of non-template local cuts via standard heuristics.
Definition: cc_lpcuts.hpp:120
Header for classes/structures/functions to work with graphs.
Management of Concorde lpcut_in linked list.
Definition: cc_lpcuts.hpp:56
int BlkCombCall(CCtsp_lpcut_in **c, int *cutcount, int ncount, int ecount, int *elist, double *ecap)
Wrapper function because CCtsp_block_combs takes a silent parameter.
Definition: cc_lpcuts.hpp:215
Data group structures.
bool find_cuts()
Call the separation routine, returning true iff cuts are found.
Definition: cc_lpcuts.hpp:156
Class template for straightforward Concorde separation routines.
Definition: cc_lpcuts.hpp:150
The namespace for this project.
Definition: abc_nodesel.hpp:20
Abstract base class for calling Concorde separation routines.
Definition: cc_lpcuts.hpp:98
Wrapper to Concorde CCtsp_lpgraph for pricing cuts at tours.
Definition: cc_lpcuts.hpp:28