lemongraph 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +8 -0
  3. data/LICENSE +674 -0
  4. data/README.md +6 -0
  5. data/ext/lemon-1.3.1/AUTHORS +26 -0
  6. data/ext/lemon-1.3.1/CMakeLists.txt +371 -0
  7. data/ext/lemon-1.3.1/INSTALL +167 -0
  8. data/ext/lemon-1.3.1/LICENSE +32 -0
  9. data/ext/lemon-1.3.1/NEWS +337 -0
  10. data/ext/lemon-1.3.1/README +50 -0
  11. data/ext/lemon-1.3.1/cmake/FindCOIN.cmake +110 -0
  12. data/ext/lemon-1.3.1/cmake/FindGLPK.cmake +55 -0
  13. data/ext/lemon-1.3.1/cmake/FindGhostscript.cmake +10 -0
  14. data/ext/lemon-1.3.1/cmake/FindILOG.cmake +102 -0
  15. data/ext/lemon-1.3.1/cmake/FindSOPLEX.cmake +23 -0
  16. data/ext/lemon-1.3.1/cmake/LEMONConfig.cmake.in +13 -0
  17. data/ext/lemon-1.3.1/cmake/nsis/lemon.ico +0 -0
  18. data/ext/lemon-1.3.1/cmake/nsis/uninstall.ico +0 -0
  19. data/ext/lemon-1.3.1/cmake/version.cmake +1 -0
  20. data/ext/lemon-1.3.1/cmake/version.cmake.in +1 -0
  21. data/ext/lemon-1.3.1/contrib/CMakeLists.txt +19 -0
  22. data/ext/lemon-1.3.1/lemon/CMakeLists.txt +91 -0
  23. data/ext/lemon-1.3.1/lemon/adaptors.h +3638 -0
  24. data/ext/lemon-1.3.1/lemon/arg_parser.cc +474 -0
  25. data/ext/lemon-1.3.1/lemon/arg_parser.h +440 -0
  26. data/ext/lemon-1.3.1/lemon/assert.h +214 -0
  27. data/ext/lemon-1.3.1/lemon/base.cc +37 -0
  28. data/ext/lemon-1.3.1/lemon/bellman_ford.h +1116 -0
  29. data/ext/lemon-1.3.1/lemon/bfs.h +1754 -0
  30. data/ext/lemon-1.3.1/lemon/bin_heap.h +347 -0
  31. data/ext/lemon-1.3.1/lemon/binomial_heap.h +445 -0
  32. data/ext/lemon-1.3.1/lemon/bits/alteration_notifier.h +472 -0
  33. data/ext/lemon-1.3.1/lemon/bits/array_map.h +351 -0
  34. data/ext/lemon-1.3.1/lemon/bits/bezier.h +174 -0
  35. data/ext/lemon-1.3.1/lemon/bits/default_map.h +182 -0
  36. data/ext/lemon-1.3.1/lemon/bits/edge_set_extender.h +627 -0
  37. data/ext/lemon-1.3.1/lemon/bits/enable_if.h +131 -0
  38. data/ext/lemon-1.3.1/lemon/bits/graph_adaptor_extender.h +401 -0
  39. data/ext/lemon-1.3.1/lemon/bits/graph_extender.h +1332 -0
  40. data/ext/lemon-1.3.1/lemon/bits/lock.h +65 -0
  41. data/ext/lemon-1.3.1/lemon/bits/map_extender.h +332 -0
  42. data/ext/lemon-1.3.1/lemon/bits/path_dump.h +177 -0
  43. data/ext/lemon-1.3.1/lemon/bits/solver_bits.h +194 -0
  44. data/ext/lemon-1.3.1/lemon/bits/traits.h +388 -0
  45. data/ext/lemon-1.3.1/lemon/bits/variant.h +494 -0
  46. data/ext/lemon-1.3.1/lemon/bits/vector_map.h +244 -0
  47. data/ext/lemon-1.3.1/lemon/bits/windows.cc +166 -0
  48. data/ext/lemon-1.3.1/lemon/bits/windows.h +44 -0
  49. data/ext/lemon-1.3.1/lemon/bucket_heap.h +594 -0
  50. data/ext/lemon-1.3.1/lemon/capacity_scaling.h +1014 -0
  51. data/ext/lemon-1.3.1/lemon/cbc.cc +460 -0
  52. data/ext/lemon-1.3.1/lemon/cbc.h +129 -0
  53. data/ext/lemon-1.3.1/lemon/christofides_tsp.h +254 -0
  54. data/ext/lemon-1.3.1/lemon/circulation.h +807 -0
  55. data/ext/lemon-1.3.1/lemon/clp.cc +464 -0
  56. data/ext/lemon-1.3.1/lemon/clp.h +164 -0
  57. data/ext/lemon-1.3.1/lemon/color.cc +44 -0
  58. data/ext/lemon-1.3.1/lemon/color.h +204 -0
  59. data/ext/lemon-1.3.1/lemon/concept_check.h +77 -0
  60. data/ext/lemon-1.3.1/lemon/concepts/bpgraph.h +1029 -0
  61. data/ext/lemon-1.3.1/lemon/concepts/digraph.h +491 -0
  62. data/ext/lemon-1.3.1/lemon/concepts/graph.h +788 -0
  63. data/ext/lemon-1.3.1/lemon/concepts/graph_components.h +2134 -0
  64. data/ext/lemon-1.3.1/lemon/concepts/heap.h +324 -0
  65. data/ext/lemon-1.3.1/lemon/concepts/maps.h +223 -0
  66. data/ext/lemon-1.3.1/lemon/concepts/path.h +312 -0
  67. data/ext/lemon-1.3.1/lemon/config.h.in +22 -0
  68. data/ext/lemon-1.3.1/lemon/connectivity.h +1688 -0
  69. data/ext/lemon-1.3.1/lemon/core.h +2506 -0
  70. data/ext/lemon-1.3.1/lemon/cost_scaling.h +1607 -0
  71. data/ext/lemon-1.3.1/lemon/counter.h +249 -0
  72. data/ext/lemon-1.3.1/lemon/cplex.cc +994 -0
  73. data/ext/lemon-1.3.1/lemon/cplex.h +292 -0
  74. data/ext/lemon-1.3.1/lemon/cycle_canceling.h +1230 -0
  75. data/ext/lemon-1.3.1/lemon/dfs.h +1637 -0
  76. data/ext/lemon-1.3.1/lemon/dheap.h +352 -0
  77. data/ext/lemon-1.3.1/lemon/dijkstra.h +1303 -0
  78. data/ext/lemon-1.3.1/lemon/dim2.h +726 -0
  79. data/ext/lemon-1.3.1/lemon/dimacs.h +448 -0
  80. data/ext/lemon-1.3.1/lemon/edge_set.h +1420 -0
  81. data/ext/lemon-1.3.1/lemon/edmonds_karp.h +556 -0
  82. data/ext/lemon-1.3.1/lemon/elevator.h +982 -0
  83. data/ext/lemon-1.3.1/lemon/error.h +276 -0
  84. data/ext/lemon-1.3.1/lemon/euler.h +287 -0
  85. data/ext/lemon-1.3.1/lemon/fib_heap.h +475 -0
  86. data/ext/lemon-1.3.1/lemon/fractional_matching.h +2139 -0
  87. data/ext/lemon-1.3.1/lemon/full_graph.h +1082 -0
  88. data/ext/lemon-1.3.1/lemon/glpk.cc +1012 -0
  89. data/ext/lemon-1.3.1/lemon/glpk.h +263 -0
  90. data/ext/lemon-1.3.1/lemon/gomory_hu.h +568 -0
  91. data/ext/lemon-1.3.1/lemon/graph_to_eps.h +1186 -0
  92. data/ext/lemon-1.3.1/lemon/greedy_tsp.h +251 -0
  93. data/ext/lemon-1.3.1/lemon/grid_graph.h +699 -0
  94. data/ext/lemon-1.3.1/lemon/grosso_locatelli_pullan_mc.h +840 -0
  95. data/ext/lemon-1.3.1/lemon/hao_orlin.h +1015 -0
  96. data/ext/lemon-1.3.1/lemon/hartmann_orlin_mmc.h +654 -0
  97. data/ext/lemon-1.3.1/lemon/howard_mmc.h +651 -0
  98. data/ext/lemon-1.3.1/lemon/hypercube_graph.h +459 -0
  99. data/ext/lemon-1.3.1/lemon/insertion_tsp.h +533 -0
  100. data/ext/lemon-1.3.1/lemon/karp_mmc.h +590 -0
  101. data/ext/lemon-1.3.1/lemon/kruskal.h +324 -0
  102. data/ext/lemon-1.3.1/lemon/lemon.pc.in +10 -0
  103. data/ext/lemon-1.3.1/lemon/lgf_reader.h +3854 -0
  104. data/ext/lemon-1.3.1/lemon/lgf_writer.h +2687 -0
  105. data/ext/lemon-1.3.1/lemon/list_graph.h +2510 -0
  106. data/ext/lemon-1.3.1/lemon/lp.h +95 -0
  107. data/ext/lemon-1.3.1/lemon/lp_base.cc +30 -0
  108. data/ext/lemon-1.3.1/lemon/lp_base.h +2147 -0
  109. data/ext/lemon-1.3.1/lemon/lp_skeleton.cc +143 -0
  110. data/ext/lemon-1.3.1/lemon/lp_skeleton.h +234 -0
  111. data/ext/lemon-1.3.1/lemon/maps.h +4057 -0
  112. data/ext/lemon-1.3.1/lemon/matching.h +3505 -0
  113. data/ext/lemon-1.3.1/lemon/math.h +77 -0
  114. data/ext/lemon-1.3.1/lemon/max_cardinality_search.h +794 -0
  115. data/ext/lemon-1.3.1/lemon/min_cost_arborescence.h +808 -0
  116. data/ext/lemon-1.3.1/lemon/nagamochi_ibaraki.h +702 -0
  117. data/ext/lemon-1.3.1/lemon/nauty_reader.h +113 -0
  118. data/ext/lemon-1.3.1/lemon/nearest_neighbor_tsp.h +238 -0
  119. data/ext/lemon-1.3.1/lemon/network_simplex.h +1659 -0
  120. data/ext/lemon-1.3.1/lemon/opt2_tsp.h +367 -0
  121. data/ext/lemon-1.3.1/lemon/pairing_heap.h +474 -0
  122. data/ext/lemon-1.3.1/lemon/path.h +1164 -0
  123. data/ext/lemon-1.3.1/lemon/planarity.h +2754 -0
  124. data/ext/lemon-1.3.1/lemon/preflow.h +985 -0
  125. data/ext/lemon-1.3.1/lemon/quad_heap.h +343 -0
  126. data/ext/lemon-1.3.1/lemon/radix_heap.h +438 -0
  127. data/ext/lemon-1.3.1/lemon/radix_sort.h +487 -0
  128. data/ext/lemon-1.3.1/lemon/random.cc +29 -0
  129. data/ext/lemon-1.3.1/lemon/random.h +1005 -0
  130. data/ext/lemon-1.3.1/lemon/smart_graph.h +1344 -0
  131. data/ext/lemon-1.3.1/lemon/soplex.cc +465 -0
  132. data/ext/lemon-1.3.1/lemon/soplex.h +158 -0
  133. data/ext/lemon-1.3.1/lemon/static_graph.h +476 -0
  134. data/ext/lemon-1.3.1/lemon/suurballe.h +776 -0
  135. data/ext/lemon-1.3.1/lemon/time_measure.h +610 -0
  136. data/ext/lemon-1.3.1/lemon/tolerance.h +242 -0
  137. data/ext/lemon-1.3.1/lemon/unionfind.h +1824 -0
  138. data/ext/lemon-1.3.1/scripts/unify-sources.sh +390 -0
  139. data/ext/lemon-1.3.1/scripts/valgrind-wrapper.sh +22 -0
  140. data/ext/lemongraph/arc_map.cc +1007 -0
  141. data/ext/lemongraph/digraph.cc +282 -0
  142. data/ext/lemongraph/digraph_arc.cc +153 -0
  143. data/ext/lemongraph/digraph_node.cc +277 -0
  144. data/ext/lemongraph/edge_map.cc +770 -0
  145. data/ext/lemongraph/extconf.rb +53 -0
  146. data/ext/lemongraph/graph.cc +351 -0
  147. data/ext/lemongraph/graph_arc.cc +95 -0
  148. data/ext/lemongraph/graph_edge.cc +153 -0
  149. data/ext/lemongraph/graph_item.cc +76 -0
  150. data/ext/lemongraph/graph_node.cc +321 -0
  151. data/ext/lemongraph/lemongraph.cc +260 -0
  152. data/ext/lemongraph/lemongraph.hh +295 -0
  153. data/ext/lemongraph/lemongraph.map +6 -0
  154. data/ext/lemongraph/lemongraph_export.hh +31 -0
  155. data/ext/lemongraph/node_map.cc +1011 -0
  156. data/lemongraph.gemspec +176 -0
  157. data/lib/lemongraph/graphviz.rb +240 -0
  158. data/lib/lemongraph/version.rb +4 -0
  159. data/lib/lemongraph.rb +21 -0
  160. data/samples/lemondeps.rb +38 -0
  161. metadata +202 -0
@@ -0,0 +1,840 @@
1
+ /* -*- mode: C++; indent-tabs-mode: nil; -*-
2
+ *
3
+ * This file is a part of LEMON, a generic C++ optimization library.
4
+ *
5
+ * Copyright (C) 2003-2013
6
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
+ *
9
+ * Permission to use, modify and distribute this software is granted
10
+ * provided that this copyright notice appears in all copies. For
11
+ * precise terms see the accompanying LICENSE file.
12
+ *
13
+ * This software is provided "AS IS" with no warranty of any kind,
14
+ * express or implied, and with no claim as to its suitability for any
15
+ * purpose.
16
+ *
17
+ */
18
+
19
+ #ifndef LEMON_GROSSO_LOCATELLI_PULLAN_MC_H
20
+ #define LEMON_GROSSO_LOCATELLI_PULLAN_MC_H
21
+
22
+ /// \ingroup approx_algs
23
+ ///
24
+ /// \file
25
+ /// \brief The iterated local search algorithm of Grosso, Locatelli, and Pullan
26
+ /// for the maximum clique problem
27
+
28
+ #include <vector>
29
+ #include <limits>
30
+ #include <lemon/core.h>
31
+ #include <lemon/random.h>
32
+
33
+ namespace lemon {
34
+
35
+ /// \addtogroup approx_algs
36
+ /// @{
37
+
38
+ /// \brief Implementation of the iterated local search algorithm of Grosso,
39
+ /// Locatelli, and Pullan for the maximum clique problem
40
+ ///
41
+ /// \ref GrossoLocatelliPullanMc implements the iterated local search
42
+ /// algorithm of Grosso, Locatelli, and Pullan for solving the \e maximum
43
+ /// \e clique \e problem \cite grosso08maxclique.
44
+ /// It is to find the largest complete subgraph (\e clique) in an
45
+ /// undirected graph, i.e., the largest set of nodes where each
46
+ /// pair of nodes is connected.
47
+ ///
48
+ /// This class provides a simple but highly efficient and robust heuristic
49
+ /// method that quickly finds a quite large clique, but not necessarily the
50
+ /// largest one.
51
+ /// The algorithm performs a certain number of iterations to find several
52
+ /// cliques and selects the largest one among them. Various limits can be
53
+ /// specified to control the running time and the effectiveness of the
54
+ /// search process.
55
+ ///
56
+ /// \tparam GR The undirected graph type the algorithm runs on.
57
+ ///
58
+ /// \note %GrossoLocatelliPullanMc provides three different node selection
59
+ /// rules, from which the most powerful one is used by default.
60
+ /// For more information, see \ref SelectionRule.
61
+ template <typename GR>
62
+ class GrossoLocatelliPullanMc
63
+ {
64
+ public:
65
+
66
+ /// \brief Constants for specifying the node selection rule.
67
+ ///
68
+ /// Enum type containing constants for specifying the node selection rule
69
+ /// for the \ref run() function.
70
+ ///
71
+ /// During the algorithm, nodes are selected for addition to the current
72
+ /// clique according to the applied rule.
73
+ /// In general, the PENALTY_BASED rule turned out to be the most powerful
74
+ /// and the most robust, thus it is the default option.
75
+ /// However, another selection rule can be specified using the \ref run()
76
+ /// function with the proper parameter.
77
+ enum SelectionRule {
78
+
79
+ /// A node is selected randomly without any evaluation at each step.
80
+ RANDOM,
81
+
82
+ /// A node of maximum degree is selected randomly at each step.
83
+ DEGREE_BASED,
84
+
85
+ /// A node of minimum penalty is selected randomly at each step.
86
+ /// The node penalties are updated adaptively after each stage of the
87
+ /// search process.
88
+ PENALTY_BASED
89
+ };
90
+
91
+ /// \brief Constants for the causes of search termination.
92
+ ///
93
+ /// Enum type containing constants for the different causes of search
94
+ /// termination. The \ref run() function returns one of these values.
95
+ enum TerminationCause {
96
+
97
+ /// The iteration count limit is reached.
98
+ ITERATION_LIMIT,
99
+
100
+ /// The step count limit is reached.
101
+ STEP_LIMIT,
102
+
103
+ /// The clique size limit is reached.
104
+ SIZE_LIMIT
105
+ };
106
+
107
+ private:
108
+
109
+ TEMPLATE_GRAPH_TYPEDEFS(GR);
110
+
111
+ typedef std::vector<int> IntVector;
112
+ typedef std::vector<char> BoolVector;
113
+ typedef std::vector<BoolVector> BoolMatrix;
114
+ // Note: vector<char> is used instead of vector<bool> for efficiency reasons
115
+
116
+ // The underlying graph
117
+ const GR &_graph;
118
+ IntNodeMap _id;
119
+
120
+ // Internal matrix representation of the graph
121
+ BoolMatrix _gr;
122
+ int _n;
123
+
124
+ // Search options
125
+ bool _delta_based_restart;
126
+ int _restart_delta_limit;
127
+
128
+ // Search limits
129
+ int _iteration_limit;
130
+ int _step_limit;
131
+ int _size_limit;
132
+
133
+ // The current clique
134
+ BoolVector _clique;
135
+ int _size;
136
+
137
+ // The best clique found so far
138
+ BoolVector _best_clique;
139
+ int _best_size;
140
+
141
+ // The "distances" of the nodes from the current clique.
142
+ // _delta[u] is the number of nodes in the clique that are
143
+ // not connected with u.
144
+ IntVector _delta;
145
+
146
+ // The current tabu set
147
+ BoolVector _tabu;
148
+
149
+ // Random number generator
150
+ Random _rnd;
151
+
152
+ private:
153
+
154
+ // Implementation of the RANDOM node selection rule.
155
+ class RandomSelectionRule
156
+ {
157
+ private:
158
+
159
+ // References to the algorithm instance
160
+ const BoolVector &_clique;
161
+ const IntVector &_delta;
162
+ const BoolVector &_tabu;
163
+ Random &_rnd;
164
+
165
+ // Pivot rule data
166
+ int _n;
167
+
168
+ public:
169
+
170
+ // Constructor
171
+ RandomSelectionRule(GrossoLocatelliPullanMc &mc) :
172
+ _clique(mc._clique), _delta(mc._delta), _tabu(mc._tabu),
173
+ _rnd(mc._rnd), _n(mc._n)
174
+ {}
175
+
176
+ // Return a node index for a feasible add move or -1 if no one exists
177
+ int nextFeasibleAddNode() const {
178
+ int start_node = _rnd[_n];
179
+ for (int i = start_node; i != _n; i++) {
180
+ if (_delta[i] == 0 && !_tabu[i]) return i;
181
+ }
182
+ for (int i = 0; i != start_node; i++) {
183
+ if (_delta[i] == 0 && !_tabu[i]) return i;
184
+ }
185
+ return -1;
186
+ }
187
+
188
+ // Return a node index for a feasible swap move or -1 if no one exists
189
+ int nextFeasibleSwapNode() const {
190
+ int start_node = _rnd[_n];
191
+ for (int i = start_node; i != _n; i++) {
192
+ if (!_clique[i] && _delta[i] == 1 && !_tabu[i]) return i;
193
+ }
194
+ for (int i = 0; i != start_node; i++) {
195
+ if (!_clique[i] && _delta[i] == 1 && !_tabu[i]) return i;
196
+ }
197
+ return -1;
198
+ }
199
+
200
+ // Return a node index for an add move or -1 if no one exists
201
+ int nextAddNode() const {
202
+ int start_node = _rnd[_n];
203
+ for (int i = start_node; i != _n; i++) {
204
+ if (_delta[i] == 0) return i;
205
+ }
206
+ for (int i = 0; i != start_node; i++) {
207
+ if (_delta[i] == 0) return i;
208
+ }
209
+ return -1;
210
+ }
211
+
212
+ // Update internal data structures between stages (if necessary)
213
+ void update() {}
214
+
215
+ }; //class RandomSelectionRule
216
+
217
+
218
+ // Implementation of the DEGREE_BASED node selection rule.
219
+ class DegreeBasedSelectionRule
220
+ {
221
+ private:
222
+
223
+ // References to the algorithm instance
224
+ const BoolVector &_clique;
225
+ const IntVector &_delta;
226
+ const BoolVector &_tabu;
227
+ Random &_rnd;
228
+
229
+ // Pivot rule data
230
+ int _n;
231
+ IntVector _deg;
232
+
233
+ public:
234
+
235
+ // Constructor
236
+ DegreeBasedSelectionRule(GrossoLocatelliPullanMc &mc) :
237
+ _clique(mc._clique), _delta(mc._delta), _tabu(mc._tabu),
238
+ _rnd(mc._rnd), _n(mc._n), _deg(_n)
239
+ {
240
+ for (int i = 0; i != _n; i++) {
241
+ int d = 0;
242
+ BoolVector &row = mc._gr[i];
243
+ for (int j = 0; j != _n; j++) {
244
+ if (row[j]) d++;
245
+ }
246
+ _deg[i] = d;
247
+ }
248
+ }
249
+
250
+ // Return a node index for a feasible add move or -1 if no one exists
251
+ int nextFeasibleAddNode() const {
252
+ int start_node = _rnd[_n];
253
+ int node = -1, max_deg = -1;
254
+ for (int i = start_node; i != _n; i++) {
255
+ if (_delta[i] == 0 && !_tabu[i] && _deg[i] > max_deg) {
256
+ node = i;
257
+ max_deg = _deg[i];
258
+ }
259
+ }
260
+ for (int i = 0; i != start_node; i++) {
261
+ if (_delta[i] == 0 && !_tabu[i] && _deg[i] > max_deg) {
262
+ node = i;
263
+ max_deg = _deg[i];
264
+ }
265
+ }
266
+ return node;
267
+ }
268
+
269
+ // Return a node index for a feasible swap move or -1 if no one exists
270
+ int nextFeasibleSwapNode() const {
271
+ int start_node = _rnd[_n];
272
+ int node = -1, max_deg = -1;
273
+ for (int i = start_node; i != _n; i++) {
274
+ if (!_clique[i] && _delta[i] == 1 && !_tabu[i] &&
275
+ _deg[i] > max_deg) {
276
+ node = i;
277
+ max_deg = _deg[i];
278
+ }
279
+ }
280
+ for (int i = 0; i != start_node; i++) {
281
+ if (!_clique[i] && _delta[i] == 1 && !_tabu[i] &&
282
+ _deg[i] > max_deg) {
283
+ node = i;
284
+ max_deg = _deg[i];
285
+ }
286
+ }
287
+ return node;
288
+ }
289
+
290
+ // Return a node index for an add move or -1 if no one exists
291
+ int nextAddNode() const {
292
+ int start_node = _rnd[_n];
293
+ int node = -1, max_deg = -1;
294
+ for (int i = start_node; i != _n; i++) {
295
+ if (_delta[i] == 0 && _deg[i] > max_deg) {
296
+ node = i;
297
+ max_deg = _deg[i];
298
+ }
299
+ }
300
+ for (int i = 0; i != start_node; i++) {
301
+ if (_delta[i] == 0 && _deg[i] > max_deg) {
302
+ node = i;
303
+ max_deg = _deg[i];
304
+ }
305
+ }
306
+ return node;
307
+ }
308
+
309
+ // Update internal data structures between stages (if necessary)
310
+ void update() {}
311
+
312
+ }; //class DegreeBasedSelectionRule
313
+
314
+
315
+ // Implementation of the PENALTY_BASED node selection rule.
316
+ class PenaltyBasedSelectionRule
317
+ {
318
+ private:
319
+
320
+ // References to the algorithm instance
321
+ const BoolVector &_clique;
322
+ const IntVector &_delta;
323
+ const BoolVector &_tabu;
324
+ Random &_rnd;
325
+
326
+ // Pivot rule data
327
+ int _n;
328
+ IntVector _penalty;
329
+
330
+ public:
331
+
332
+ // Constructor
333
+ PenaltyBasedSelectionRule(GrossoLocatelliPullanMc &mc) :
334
+ _clique(mc._clique), _delta(mc._delta), _tabu(mc._tabu),
335
+ _rnd(mc._rnd), _n(mc._n), _penalty(_n, 0)
336
+ {}
337
+
338
+ // Return a node index for a feasible add move or -1 if no one exists
339
+ int nextFeasibleAddNode() const {
340
+ int start_node = _rnd[_n];
341
+ int node = -1, min_p = std::numeric_limits<int>::max();
342
+ for (int i = start_node; i != _n; i++) {
343
+ if (_delta[i] == 0 && !_tabu[i] && _penalty[i] < min_p) {
344
+ node = i;
345
+ min_p = _penalty[i];
346
+ }
347
+ }
348
+ for (int i = 0; i != start_node; i++) {
349
+ if (_delta[i] == 0 && !_tabu[i] && _penalty[i] < min_p) {
350
+ node = i;
351
+ min_p = _penalty[i];
352
+ }
353
+ }
354
+ return node;
355
+ }
356
+
357
+ // Return a node index for a feasible swap move or -1 if no one exists
358
+ int nextFeasibleSwapNode() const {
359
+ int start_node = _rnd[_n];
360
+ int node = -1, min_p = std::numeric_limits<int>::max();
361
+ for (int i = start_node; i != _n; i++) {
362
+ if (!_clique[i] && _delta[i] == 1 && !_tabu[i] &&
363
+ _penalty[i] < min_p) {
364
+ node = i;
365
+ min_p = _penalty[i];
366
+ }
367
+ }
368
+ for (int i = 0; i != start_node; i++) {
369
+ if (!_clique[i] && _delta[i] == 1 && !_tabu[i] &&
370
+ _penalty[i] < min_p) {
371
+ node = i;
372
+ min_p = _penalty[i];
373
+ }
374
+ }
375
+ return node;
376
+ }
377
+
378
+ // Return a node index for an add move or -1 if no one exists
379
+ int nextAddNode() const {
380
+ int start_node = _rnd[_n];
381
+ int node = -1, min_p = std::numeric_limits<int>::max();
382
+ for (int i = start_node; i != _n; i++) {
383
+ if (_delta[i] == 0 && _penalty[i] < min_p) {
384
+ node = i;
385
+ min_p = _penalty[i];
386
+ }
387
+ }
388
+ for (int i = 0; i != start_node; i++) {
389
+ if (_delta[i] == 0 && _penalty[i] < min_p) {
390
+ node = i;
391
+ min_p = _penalty[i];
392
+ }
393
+ }
394
+ return node;
395
+ }
396
+
397
+ // Update internal data structures between stages (if necessary)
398
+ void update() {}
399
+
400
+ }; //class PenaltyBasedSelectionRule
401
+
402
+ public:
403
+
404
+ /// \brief Constructor.
405
+ ///
406
+ /// Constructor.
407
+ /// The global \ref rnd "random number generator instance" is used
408
+ /// during the algorithm.
409
+ ///
410
+ /// \param graph The undirected graph the algorithm runs on.
411
+ GrossoLocatelliPullanMc(const GR& graph) :
412
+ _graph(graph), _id(_graph), _rnd(rnd)
413
+ {
414
+ initOptions();
415
+ }
416
+
417
+ /// \brief Constructor with random seed.
418
+ ///
419
+ /// Constructor with random seed.
420
+ ///
421
+ /// \param graph The undirected graph the algorithm runs on.
422
+ /// \param seed Seed value for the internal random number generator
423
+ /// that is used during the algorithm.
424
+ GrossoLocatelliPullanMc(const GR& graph, int seed) :
425
+ _graph(graph), _id(_graph), _rnd(seed)
426
+ {
427
+ initOptions();
428
+ }
429
+
430
+ /// \brief Constructor with random number generator.
431
+ ///
432
+ /// Constructor with random number generator.
433
+ ///
434
+ /// \param graph The undirected graph the algorithm runs on.
435
+ /// \param random A random number generator that is used during the
436
+ /// algorithm.
437
+ GrossoLocatelliPullanMc(const GR& graph, const Random& random) :
438
+ _graph(graph), _id(_graph), _rnd(random)
439
+ {
440
+ initOptions();
441
+ }
442
+
443
+ /// \name Execution Control
444
+ /// The \ref run() function can be used to execute the algorithm.\n
445
+ /// The functions \ref iterationLimit(int), \ref stepLimit(int), and
446
+ /// \ref sizeLimit(int) can be used to specify various limits for the
447
+ /// search process.
448
+
449
+ /// @{
450
+
451
+ /// \brief Sets the maximum number of iterations.
452
+ ///
453
+ /// This function sets the maximum number of iterations.
454
+ /// Each iteration of the algorithm finds a maximal clique (but not
455
+ /// necessarily the largest one) by performing several search steps
456
+ /// (node selections).
457
+ ///
458
+ /// This limit controls the running time and the success of the
459
+ /// algorithm. For larger values, the algorithm runs slower, but it more
460
+ /// likely finds larger cliques. For smaller values, the algorithm is
461
+ /// faster but probably gives worse results.
462
+ ///
463
+ /// The default value is \c 1000.
464
+ /// \c -1 means that number of iterations is not limited.
465
+ ///
466
+ /// \warning You should specify a reasonable limit for the number of
467
+ /// iterations and/or the number of search steps.
468
+ ///
469
+ /// \return <tt>(*this)</tt>
470
+ ///
471
+ /// \sa stepLimit(int)
472
+ /// \sa sizeLimit(int)
473
+ GrossoLocatelliPullanMc& iterationLimit(int limit) {
474
+ _iteration_limit = limit;
475
+ return *this;
476
+ }
477
+
478
+ /// \brief Sets the maximum number of search steps.
479
+ ///
480
+ /// This function sets the maximum number of elementary search steps.
481
+ /// Each iteration of the algorithm finds a maximal clique (but not
482
+ /// necessarily the largest one) by performing several search steps
483
+ /// (node selections).
484
+ ///
485
+ /// This limit controls the running time and the success of the
486
+ /// algorithm. For larger values, the algorithm runs slower, but it more
487
+ /// likely finds larger cliques. For smaller values, the algorithm is
488
+ /// faster but probably gives worse results.
489
+ ///
490
+ /// The default value is \c -1, which means that number of steps
491
+ /// is not limited explicitly. However, the number of iterations is
492
+ /// limited and each iteration performs a finite number of search steps.
493
+ ///
494
+ /// \warning You should specify a reasonable limit for the number of
495
+ /// iterations and/or the number of search steps.
496
+ ///
497
+ /// \return <tt>(*this)</tt>
498
+ ///
499
+ /// \sa iterationLimit(int)
500
+ /// \sa sizeLimit(int)
501
+ GrossoLocatelliPullanMc& stepLimit(int limit) {
502
+ _step_limit = limit;
503
+ return *this;
504
+ }
505
+
506
+ /// \brief Sets the desired clique size.
507
+ ///
508
+ /// This function sets the desired clique size that serves as a search
509
+ /// limit. If a clique of this size (or a larger one) is found, then the
510
+ /// algorithm terminates.
511
+ ///
512
+ /// This function is especially useful if you know an exact upper bound
513
+ /// for the size of the cliques in the graph or if any clique above
514
+ /// a certain size limit is sufficient for your application.
515
+ ///
516
+ /// The default value is \c -1, which means that the size limit is set to
517
+ /// the number of nodes in the graph.
518
+ ///
519
+ /// \return <tt>(*this)</tt>
520
+ ///
521
+ /// \sa iterationLimit(int)
522
+ /// \sa stepLimit(int)
523
+ GrossoLocatelliPullanMc& sizeLimit(int limit) {
524
+ _size_limit = limit;
525
+ return *this;
526
+ }
527
+
528
+ /// \brief The maximum number of iterations.
529
+ ///
530
+ /// This function gives back the maximum number of iterations.
531
+ /// \c -1 means that no limit is specified.
532
+ ///
533
+ /// \sa iterationLimit(int)
534
+ int iterationLimit() const {
535
+ return _iteration_limit;
536
+ }
537
+
538
+ /// \brief The maximum number of search steps.
539
+ ///
540
+ /// This function gives back the maximum number of search steps.
541
+ /// \c -1 means that no limit is specified.
542
+ ///
543
+ /// \sa stepLimit(int)
544
+ int stepLimit() const {
545
+ return _step_limit;
546
+ }
547
+
548
+ /// \brief The desired clique size.
549
+ ///
550
+ /// This function gives back the desired clique size that serves as a
551
+ /// search limit. \c -1 means that this limit is set to the number of
552
+ /// nodes in the graph.
553
+ ///
554
+ /// \sa sizeLimit(int)
555
+ int sizeLimit() const {
556
+ return _size_limit;
557
+ }
558
+
559
+ /// \brief Runs the algorithm.
560
+ ///
561
+ /// This function runs the algorithm. If one of the specified limits
562
+ /// is reached, the search process terminates.
563
+ ///
564
+ /// \param rule The node selection rule. For more information, see
565
+ /// \ref SelectionRule.
566
+ ///
567
+ /// \return The termination cause of the search. For more information,
568
+ /// see \ref TerminationCause.
569
+ TerminationCause run(SelectionRule rule = PENALTY_BASED)
570
+ {
571
+ init();
572
+ switch (rule) {
573
+ case RANDOM:
574
+ return start<RandomSelectionRule>();
575
+ case DEGREE_BASED:
576
+ return start<DegreeBasedSelectionRule>();
577
+ default:
578
+ return start<PenaltyBasedSelectionRule>();
579
+ }
580
+ }
581
+
582
+ /// @}
583
+
584
+ /// \name Query Functions
585
+ /// The results of the algorithm can be obtained using these functions.\n
586
+ /// The run() function must be called before using them.
587
+
588
+ /// @{
589
+
590
+ /// \brief The size of the found clique
591
+ ///
592
+ /// This function returns the size of the found clique.
593
+ ///
594
+ /// \pre run() must be called before using this function.
595
+ int cliqueSize() const {
596
+ return _best_size;
597
+ }
598
+
599
+ /// \brief Gives back the found clique in a \c bool node map
600
+ ///
601
+ /// This function gives back the characteristic vector of the found
602
+ /// clique in the given node map.
603
+ /// It must be a \ref concepts::WriteMap "writable" node map with
604
+ /// \c bool (or convertible) value type.
605
+ ///
606
+ /// \pre run() must be called before using this function.
607
+ template <typename CliqueMap>
608
+ void cliqueMap(CliqueMap &map) const {
609
+ for (NodeIt n(_graph); n != INVALID; ++n) {
610
+ map[n] = static_cast<bool>(_best_clique[_id[n]]);
611
+ }
612
+ }
613
+
614
+ /// \brief Iterator to list the nodes of the found clique
615
+ ///
616
+ /// This iterator class lists the nodes of the found clique.
617
+ /// Before using it, you must allocate a GrossoLocatelliPullanMc instance
618
+ /// and call its \ref GrossoLocatelliPullanMc::run() "run()" method.
619
+ ///
620
+ /// The following example prints out the IDs of the nodes in the found
621
+ /// clique.
622
+ /// \code
623
+ /// GrossoLocatelliPullanMc<Graph> mc(g);
624
+ /// mc.run();
625
+ /// for (GrossoLocatelliPullanMc<Graph>::CliqueNodeIt n(mc);
626
+ /// n != INVALID; ++n)
627
+ /// {
628
+ /// std::cout << g.id(n) << std::endl;
629
+ /// }
630
+ /// \endcode
631
+ class CliqueNodeIt
632
+ {
633
+ private:
634
+ NodeIt _it;
635
+ BoolNodeMap _map;
636
+
637
+ public:
638
+
639
+ /// Constructor
640
+
641
+ /// Constructor.
642
+ /// \param mc The algorithm instance.
643
+ CliqueNodeIt(const GrossoLocatelliPullanMc &mc)
644
+ : _map(mc._graph)
645
+ {
646
+ mc.cliqueMap(_map);
647
+ for (_it = NodeIt(mc._graph); _it != INVALID && !_map[_it]; ++_it) ;
648
+ }
649
+
650
+ /// Conversion to \c Node
651
+ operator Node() const { return _it; }
652
+
653
+ bool operator==(Invalid) const { return _it == INVALID; }
654
+ bool operator!=(Invalid) const { return _it != INVALID; }
655
+
656
+ /// Next node
657
+ CliqueNodeIt &operator++() {
658
+ for (++_it; _it != INVALID && !_map[_it]; ++_it) ;
659
+ return *this;
660
+ }
661
+
662
+ /// Postfix incrementation
663
+
664
+ /// Postfix incrementation.
665
+ ///
666
+ /// \warning This incrementation returns a \c Node, not a
667
+ /// \c CliqueNodeIt as one may expect.
668
+ typename GR::Node operator++(int) {
669
+ Node n=*this;
670
+ ++(*this);
671
+ return n;
672
+ }
673
+
674
+ };
675
+
676
+ /// @}
677
+
678
+ private:
679
+
680
+ // Initialize search options and limits
681
+ void initOptions() {
682
+ // Search options
683
+ _delta_based_restart = true;
684
+ _restart_delta_limit = 4;
685
+
686
+ // Search limits
687
+ _iteration_limit = 1000;
688
+ _step_limit = -1; // this is disabled by default
689
+ _size_limit = -1; // this is disabled by default
690
+ }
691
+
692
+ // Adds a node to the current clique
693
+ void addCliqueNode(int u) {
694
+ if (_clique[u]) return;
695
+ _clique[u] = true;
696
+ _size++;
697
+ BoolVector &row = _gr[u];
698
+ for (int i = 0; i != _n; i++) {
699
+ if (!row[i]) _delta[i]++;
700
+ }
701
+ }
702
+
703
+ // Removes a node from the current clique
704
+ void delCliqueNode(int u) {
705
+ if (!_clique[u]) return;
706
+ _clique[u] = false;
707
+ _size--;
708
+ BoolVector &row = _gr[u];
709
+ for (int i = 0; i != _n; i++) {
710
+ if (!row[i]) _delta[i]--;
711
+ }
712
+ }
713
+
714
+ // Initialize data structures
715
+ void init() {
716
+ _n = countNodes(_graph);
717
+ int ui = 0;
718
+ for (NodeIt u(_graph); u != INVALID; ++u) {
719
+ _id[u] = ui++;
720
+ }
721
+ _gr.clear();
722
+ _gr.resize(_n, BoolVector(_n, false));
723
+ ui = 0;
724
+ for (NodeIt u(_graph); u != INVALID; ++u) {
725
+ for (IncEdgeIt e(_graph, u); e != INVALID; ++e) {
726
+ int vi = _id[_graph.runningNode(e)];
727
+ _gr[ui][vi] = true;
728
+ _gr[vi][ui] = true;
729
+ }
730
+ ++ui;
731
+ }
732
+
733
+ _clique.clear();
734
+ _clique.resize(_n, false);
735
+ _size = 0;
736
+ _best_clique.clear();
737
+ _best_clique.resize(_n, false);
738
+ _best_size = 0;
739
+ _delta.clear();
740
+ _delta.resize(_n, 0);
741
+ _tabu.clear();
742
+ _tabu.resize(_n, false);
743
+ }
744
+
745
+ // Executes the algorithm
746
+ template <typename SelectionRuleImpl>
747
+ TerminationCause start() {
748
+ if (_n == 0) return SIZE_LIMIT;
749
+ if (_n == 1) {
750
+ _best_clique[0] = true;
751
+ _best_size = 1;
752
+ return SIZE_LIMIT;
753
+ }
754
+
755
+ // Iterated local search algorithm
756
+ const int max_size = _size_limit >= 0 ? _size_limit : _n;
757
+ const int max_restart = _iteration_limit >= 0 ?
758
+ _iteration_limit : std::numeric_limits<int>::max();
759
+ const int max_select = _step_limit >= 0 ?
760
+ _step_limit : std::numeric_limits<int>::max();
761
+
762
+ SelectionRuleImpl sel_method(*this);
763
+ int select = 0, restart = 0;
764
+ IntVector restart_nodes;
765
+ while (select < max_select && restart < max_restart) {
766
+
767
+ // Perturbation/restart
768
+ restart++;
769
+ if (_delta_based_restart) {
770
+ restart_nodes.clear();
771
+ for (int i = 0; i != _n; i++) {
772
+ if (_delta[i] >= _restart_delta_limit)
773
+ restart_nodes.push_back(i);
774
+ }
775
+ }
776
+ int rs_node = -1;
777
+ if (restart_nodes.size() > 0) {
778
+ rs_node = restart_nodes[_rnd[restart_nodes.size()]];
779
+ } else {
780
+ rs_node = _rnd[_n];
781
+ }
782
+ BoolVector &row = _gr[rs_node];
783
+ for (int i = 0; i != _n; i++) {
784
+ if (_clique[i] && !row[i]) delCliqueNode(i);
785
+ }
786
+ addCliqueNode(rs_node);
787
+
788
+ // Local search
789
+ _tabu.clear();
790
+ _tabu.resize(_n, false);
791
+ bool tabu_empty = true;
792
+ int max_swap = _size;
793
+ while (select < max_select) {
794
+ select++;
795
+ int u;
796
+ if ((u = sel_method.nextFeasibleAddNode()) != -1) {
797
+ // Feasible add move
798
+ addCliqueNode(u);
799
+ if (tabu_empty) max_swap = _size;
800
+ }
801
+ else if ((u = sel_method.nextFeasibleSwapNode()) != -1) {
802
+ // Feasible swap move
803
+ int v = -1;
804
+ BoolVector &row = _gr[u];
805
+ for (int i = 0; i != _n; i++) {
806
+ if (_clique[i] && !row[i]) {
807
+ v = i;
808
+ break;
809
+ }
810
+ }
811
+ addCliqueNode(u);
812
+ delCliqueNode(v);
813
+ _tabu[v] = true;
814
+ tabu_empty = false;
815
+ if (--max_swap <= 0) break;
816
+ }
817
+ else if ((u = sel_method.nextAddNode()) != -1) {
818
+ // Non-feasible add move
819
+ addCliqueNode(u);
820
+ }
821
+ else break;
822
+ }
823
+ if (_size > _best_size) {
824
+ _best_clique = _clique;
825
+ _best_size = _size;
826
+ if (_best_size >= max_size) return SIZE_LIMIT;
827
+ }
828
+ sel_method.update();
829
+ }
830
+
831
+ return (restart >= max_restart ? ITERATION_LIMIT : STEP_LIMIT);
832
+ }
833
+
834
+ }; //class GrossoLocatelliPullanMc
835
+
836
+ ///@}
837
+
838
+ } //namespace lemon
839
+
840
+ #endif //LEMON_GROSSO_LOCATELLI_PULLAN_MC_H