MinLCA algorithms
optimisation-sa-colours.hh
Go to the documentation of this file.
1 #ifndef __MINLCA_MINLCA_OPTIMISATION_SA_COLOURS_HH
2 #define __MINLCA_MINLCA_OPTIMISATION_SA_COLOURS_HH
3 
4 #include <minlca/base.hh>
5 #include <minlca/optimisation.hh>
7 
10 
11 namespace minlca
12 {
13 
18 template<typename Graph = lemon::SmartGraph>
19 class MinLCAColoursSA : public MinLCAOpt<Graph>
20 {
21  TEMPLATE_GRAPH_TYPEDEFS(Graph);
22 protected:
24 
25  class NodeSA;
26 
27  friend class NodeSA;
28 
30  *_sa;
32  lemon::Random *_r;
34  lemon::RangeIdMap<Graph, Node> _vertex_id_map;
35 
39  virtual void init()
40  {
41  Base::init();
42  }
43 
44 public:
55  const Graph &g,
56  int maxK = 0,
57  int seed = 0
58  )
59  : Base(g, maxK),
60  _sa(nullptr),
61  _result(nullptr),
62  _r(nullptr),
63  _delete_random(true),
64  _vertex_id_map(g)
65  {
66  _r = new lemon::Random(seed);
67  }
68 
74  {
75  if (_sa != nullptr) {
76  delete _sa;
77  }
78 
79  if (_result != nullptr) {
80  delete _result;
81  }
82  }
83 
87  void setRandom(
88  lemon::Random *r,
89  bool deleteRandom =
90  false
91  )
92  {
93  if (_delete_random) {
94  delete _r;
95  }
96 
97  _r = r;
98  _delete_random = deleteRandom;
99  }
100 
105  virtual void init(int steps, int stIter, int k, double lambda)
106  {
107  Base::init();
108 
109  if (_sa != nullptr) {
110  delete _sa;
111  }
112 
113  _sa = new utils::SimulatedAnnealing<NodeSA>(steps, stIter, k, lambda, *_r);
114 
115  if (_result != nullptr) {
116  delete _result;
117  _result = nullptr;
118  }
119  }
120 
121  virtual void initialSolution(const typename Base::Colouring &c)
122  {
123  if (_result != nullptr) {
124  delete _result;
125  }
126 
127  _result = new NodeSA(this, c);
128  }
129 
130  virtual MinLCAStatus run()
131  {
132  _result->init();
133  _result->run();
134 
135  _sa->init(_result);
136  _result = _sa->run();
137 
138  for (NodeIt v(this->_g); v != lemon::INVALID; ++v) {
139  this->setColour(v, _result->colouring()[v]);
140  }
141 
142  if (_result->status() == SOLUTION_FOUND) {
143  this->setSolutionFound();
144  }
145  else {
146  this->setSolutionNotFound();
147  }
148 
149  return this->status();
150  }
151 
152 protected:
157  class NodeSA : public MinLCA<Graph>
158  {
159  protected:
160  TEMPLATE_GRAPH_TYPEDEFS(Graph);
161  typedef MinLCA<Graph> BaseLCA;
163 
164  BaseSA *_sa;
165  using BaseLCA::_c;
166  using BaseLCA::_lca;
167  using BaseLCA::_g;
168  using BaseLCA::_k;
169  using BaseLCA::_max_k;
170  std::vector<int> _counter;
171 
172 
173  public:
176  BaseSA *sa,
177  const typename BaseLCA::Colouring &c,
179  )
180  : BaseLCA(sa->_g, sa->_max_k), _sa(sa), _counter(_max_k)
181  {
182  for (NodeIt v(this->_g); v != lemon::INVALID; ++v) {
183  this->setColour(v, c[v]);
184  }
185 
186  this->_s = s;
187  }
188 
189  virtual inline void init()
190  {
191  for (NodeIt v(this->_g); v != lemon::INVALID; ++v) {
192  this->checkValid(v);
193  }
194  }
195 
196  inline void init(const std::vector<int> &oldCounter)
197  {
198  _counter = oldCounter;
199  }
200 
201  virtual MinLCAStatus run()
202  {
203  if (this->status() != SOLUTION_FOUND) {
204  return SOLUTION_NOT_FOUND;
205  }
206 
207  for (NodeIt v(this->_g); v != lemon::INVALID; ++v) {
208  checkValid(v);
209  }
210 
211  return this->status();
212  }
213 
214  protected:
219  inline bool checkValid(
220  const Node &v
221  )
222  {
223  if (this->status() == SOLUTION_NOT_FOUND) {
224  return false;
225  }
226 
227  for (IncEdgeIt e(_g, v); e != lemon::INVALID; ++e) {
228  Node u = _g.oppositeNode(v, e);
229 
230  if (this->_c[u] == this->_c[v]) {
231  this->setSolutionNotFound();
232  return false;
233  }
234  }
235 
236  this->setSolutionFound();
237  return true;
238  }
239 
243  inline void swapColours(
244  int c1,
245  int c2
246  )
247  {
248  for (NodeIt v(_g); v != lemon::INVALID; ++v) {
249  if (this->_c[v] == c1) {
250  this->setColour(v, c2);
251  }
252  else if (this->_c[v] == c2) {
253  this->setColour(v, c1);
254  }
255  }
256  }
257 
258  virtual inline void setColour(const Node &v, int vColour)
259  {
260  int old = _c[v];
261  BaseLCA::setColour(v, vColour);
262 
263  if (vColour != -1) {
264  ++_counter[vColour];
265  }
266 
267  if (old != -1) {
268  --_counter[old];
269  }
270  }
271 
276  inline void compress(
277  int c
278  )
279  {
280  if (_counter[c] == 0) {
281  if (_k >= c) {
282  --_k;
283  }
284 
285  for (NodeIt v(_g); v != lemon::INVALID; ++v) {
286  if (_c[v] > c) {
287  this->setColour(v, _c[v] - 1);
288  }
289  }
290  }
291  }
292 
293  public:
294 
299  {
300  NodeSA *next = nullptr;
301 
302  while (next == nullptr) {
303  next = new NodeSA(_sa, _c, this->status());
304  next->init(_counter);
305  int diceSides = 10;
306 
307  if (this->totalColours() < _max_k) {
308  diceSides = 12;
309  }
310 
311  int option = _sa->_r->integer(diceSides);
312 
313  if (option >= 10) {
314  Node v = _sa->_vertex_id_map(_sa->_r->integer(_sa->_vertex_id_map.size()));
315  int old = _c[v];
316  next->setColour(v, this->totalColours());
317  next->compress(old);
318  }
319  else if (option <= 4) {
320  int k = this->totalColours();
321  int c1 = _sa->_r->integer(k - 1);
322  int c2 = c1 + 1 + _sa->_r->integer(k - c1 - 1);
323  next->swapColours(c1, c2);
324  }
325  else {
326  Node v = _sa->_vertex_id_map(_sa->_r->integer(_sa->_vertex_id_map.size()));
327  int c = _sa->_r->integer(this->totalColours() - 1);
328  int old = _c[v];
329 
330  if (old <= c) {
331  ++c;
332  }
333 
334  next->setColour(v, c);
335  next->compress(old);
336  next->checkValid(v);
337  }
338 
339  if (next->status() != SOLUTION_FOUND) {
340  delete next;
341  next = nullptr;
342  }
343  }
344 
345  return next;
346  }
347 
351  inline double energy() const
352  {
353  if (this->status() == SOLUTION_FOUND) {
354  return -static_cast<double>(this->lcaValue());
355  }
356 
357  LEMON_ASSERT(false, "Using bad solution");
358  return -std::numeric_limits<double>::infinity();
359  }
360  };
361 
362 };
363 }
364 
365 #endif
MinLCAStatus _s
The status of the solution.
Definition: base.hh:41
long long lcaValue() const
Value (cost) of the current solution.
Definition: base.hh:175
NodeSA(BaseSA *sa, const typename BaseLCA::Colouring &c, MinLCAStatus s=UNDEFINED)
Constructor.
virtual void init()
Reset the data structures of the algorithm.
Definition: base.hh:112
bool _delete_random
Delete the random number generator in destructor.
virtual void setColour(const Node &v, int vColour)
Set the colour of a vertex.
Definition: base.hh:60
Class defining the node for the simulated annealing search changing the colours.
virtual MinLCAStatus run()
Run the algorithm.
virtual void init()
Reset the data structures of the algorithm.
Generic simulated annealing algorithm.
lemon::RangeIdMap< Graph, Node > _vertex_id_map
Map of vertex identifiers.
MinLCAColoursSA< Graph > BaseSA
Parent class.
std::vector< int > _counter
Number of vertices using a colour.
MinLCAStatus
Possible status for MinLCA solution.
Definition: base.hh:20
MinLCAColoursSA(const Graph &g, int maxK=0, int seed=0)
Constructor.
const Graph & _g
A const reference to the graph we want to arrange.
Definition: base.hh:36
int _k
Largest index of the colours used.
Definition: base.hh:37
Colouring _c
The vertex colouring.
Definition: base.hh:40
Class defining a local search approach changing the colours.
Solution has been found after running.
Definition: base.hh:22
virtual void init(int steps, int stIter, int k, double lambda)
Reset the data structures of the algorithm.
BaseSA * _sa
Pointer to the parent class containing the problem data.
void setRandom(lemon::Random *r, bool deleteRandom=false)
Change the random number generator.
Default namespace Default namespace for MinLCA algorithms.
Definition: base.hh:15
Defines the base class for MinLCA algorithms.
Algorithm has not run yet, or some other status.
Definition: base.hh:21
int _max_k
Maximum number of colours allowed.
Definition: base.hh:38
Base class for MinLCA algorithms.
Definition: base.hh:29
Base class for defining optimisation MinLCA algorithms.
Definition: optimisation.hh:24
double energy() const
Energy of the node.
virtual void setColour(const Node &v, int vColour)
Set the colour of a vertex.
int totalColours() const
Total number of colours used.
Definition: base.hh:183
Solution has not been found after running.
Definition: base.hh:23
const Colouring & colouring() const
Current colouring.
Definition: base.hh:147
NodeSA * randomNeighbour() const
Get a random neighbour.
Defines the base class for MinLCA optimisation algorithms.
void setSolutionNotFound()
Auxiliary function to set solution status to not found.
Definition: base.hh:45
NodeSA * _result
Pointer to the node obtained with simulated annealing.
IntNodeMap Colouring
Type for graph colourings.
Definition: base.hh:33
lemon::Random * _r
Pointer to the random number generator used.
virtual MinLCAStatus run()
Run the algorithm.
Description of generic simulated annealing algorithm.
virtual void init()
Initialise data structures. Do not use.
bool checkValid(const Node &v)
Check if a vertex and its adjacent vertices have different colours.
void swapColours(int c1, int c2)
Swap the vertices of two colours.
MinLCAStatus status() const
Status of the solution.
Definition: base.hh:126
int maxK()
Maximum number of allowed colours.
Definition: base.hh:205
MinLCAOpt< Graph > Base
Base class.
long long _lca
Cost of the current solution.
Definition: base.hh:39
void setSolutionFound()
Auxiliary function to set solution status to found.
Definition: base.hh:52
utils::SimulatedAnnealing< NodeSA > * _sa
Pointer to the simulated annealing algorithm.
void compress(int c)
Compress solution.