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.
- checksums.yaml +7 -0
- data/.yardopts +8 -0
- data/LICENSE +674 -0
- data/README.md +6 -0
- data/ext/lemon-1.3.1/AUTHORS +26 -0
- data/ext/lemon-1.3.1/CMakeLists.txt +371 -0
- data/ext/lemon-1.3.1/INSTALL +167 -0
- data/ext/lemon-1.3.1/LICENSE +32 -0
- data/ext/lemon-1.3.1/NEWS +337 -0
- data/ext/lemon-1.3.1/README +50 -0
- data/ext/lemon-1.3.1/cmake/FindCOIN.cmake +110 -0
- data/ext/lemon-1.3.1/cmake/FindGLPK.cmake +55 -0
- data/ext/lemon-1.3.1/cmake/FindGhostscript.cmake +10 -0
- data/ext/lemon-1.3.1/cmake/FindILOG.cmake +102 -0
- data/ext/lemon-1.3.1/cmake/FindSOPLEX.cmake +23 -0
- data/ext/lemon-1.3.1/cmake/LEMONConfig.cmake.in +13 -0
- data/ext/lemon-1.3.1/cmake/nsis/lemon.ico +0 -0
- data/ext/lemon-1.3.1/cmake/nsis/uninstall.ico +0 -0
- data/ext/lemon-1.3.1/cmake/version.cmake +1 -0
- data/ext/lemon-1.3.1/cmake/version.cmake.in +1 -0
- data/ext/lemon-1.3.1/contrib/CMakeLists.txt +19 -0
- data/ext/lemon-1.3.1/lemon/CMakeLists.txt +91 -0
- data/ext/lemon-1.3.1/lemon/adaptors.h +3638 -0
- data/ext/lemon-1.3.1/lemon/arg_parser.cc +474 -0
- data/ext/lemon-1.3.1/lemon/arg_parser.h +440 -0
- data/ext/lemon-1.3.1/lemon/assert.h +214 -0
- data/ext/lemon-1.3.1/lemon/base.cc +37 -0
- data/ext/lemon-1.3.1/lemon/bellman_ford.h +1116 -0
- data/ext/lemon-1.3.1/lemon/bfs.h +1754 -0
- data/ext/lemon-1.3.1/lemon/bin_heap.h +347 -0
- data/ext/lemon-1.3.1/lemon/binomial_heap.h +445 -0
- data/ext/lemon-1.3.1/lemon/bits/alteration_notifier.h +472 -0
- data/ext/lemon-1.3.1/lemon/bits/array_map.h +351 -0
- data/ext/lemon-1.3.1/lemon/bits/bezier.h +174 -0
- data/ext/lemon-1.3.1/lemon/bits/default_map.h +182 -0
- data/ext/lemon-1.3.1/lemon/bits/edge_set_extender.h +627 -0
- data/ext/lemon-1.3.1/lemon/bits/enable_if.h +131 -0
- data/ext/lemon-1.3.1/lemon/bits/graph_adaptor_extender.h +401 -0
- data/ext/lemon-1.3.1/lemon/bits/graph_extender.h +1332 -0
- data/ext/lemon-1.3.1/lemon/bits/lock.h +65 -0
- data/ext/lemon-1.3.1/lemon/bits/map_extender.h +332 -0
- data/ext/lemon-1.3.1/lemon/bits/path_dump.h +177 -0
- data/ext/lemon-1.3.1/lemon/bits/solver_bits.h +194 -0
- data/ext/lemon-1.3.1/lemon/bits/traits.h +388 -0
- data/ext/lemon-1.3.1/lemon/bits/variant.h +494 -0
- data/ext/lemon-1.3.1/lemon/bits/vector_map.h +244 -0
- data/ext/lemon-1.3.1/lemon/bits/windows.cc +166 -0
- data/ext/lemon-1.3.1/lemon/bits/windows.h +44 -0
- data/ext/lemon-1.3.1/lemon/bucket_heap.h +594 -0
- data/ext/lemon-1.3.1/lemon/capacity_scaling.h +1014 -0
- data/ext/lemon-1.3.1/lemon/cbc.cc +460 -0
- data/ext/lemon-1.3.1/lemon/cbc.h +129 -0
- data/ext/lemon-1.3.1/lemon/christofides_tsp.h +254 -0
- data/ext/lemon-1.3.1/lemon/circulation.h +807 -0
- data/ext/lemon-1.3.1/lemon/clp.cc +464 -0
- data/ext/lemon-1.3.1/lemon/clp.h +164 -0
- data/ext/lemon-1.3.1/lemon/color.cc +44 -0
- data/ext/lemon-1.3.1/lemon/color.h +204 -0
- data/ext/lemon-1.3.1/lemon/concept_check.h +77 -0
- data/ext/lemon-1.3.1/lemon/concepts/bpgraph.h +1029 -0
- data/ext/lemon-1.3.1/lemon/concepts/digraph.h +491 -0
- data/ext/lemon-1.3.1/lemon/concepts/graph.h +788 -0
- data/ext/lemon-1.3.1/lemon/concepts/graph_components.h +2134 -0
- data/ext/lemon-1.3.1/lemon/concepts/heap.h +324 -0
- data/ext/lemon-1.3.1/lemon/concepts/maps.h +223 -0
- data/ext/lemon-1.3.1/lemon/concepts/path.h +312 -0
- data/ext/lemon-1.3.1/lemon/config.h.in +22 -0
- data/ext/lemon-1.3.1/lemon/connectivity.h +1688 -0
- data/ext/lemon-1.3.1/lemon/core.h +2506 -0
- data/ext/lemon-1.3.1/lemon/cost_scaling.h +1607 -0
- data/ext/lemon-1.3.1/lemon/counter.h +249 -0
- data/ext/lemon-1.3.1/lemon/cplex.cc +994 -0
- data/ext/lemon-1.3.1/lemon/cplex.h +292 -0
- data/ext/lemon-1.3.1/lemon/cycle_canceling.h +1230 -0
- data/ext/lemon-1.3.1/lemon/dfs.h +1637 -0
- data/ext/lemon-1.3.1/lemon/dheap.h +352 -0
- data/ext/lemon-1.3.1/lemon/dijkstra.h +1303 -0
- data/ext/lemon-1.3.1/lemon/dim2.h +726 -0
- data/ext/lemon-1.3.1/lemon/dimacs.h +448 -0
- data/ext/lemon-1.3.1/lemon/edge_set.h +1420 -0
- data/ext/lemon-1.3.1/lemon/edmonds_karp.h +556 -0
- data/ext/lemon-1.3.1/lemon/elevator.h +982 -0
- data/ext/lemon-1.3.1/lemon/error.h +276 -0
- data/ext/lemon-1.3.1/lemon/euler.h +287 -0
- data/ext/lemon-1.3.1/lemon/fib_heap.h +475 -0
- data/ext/lemon-1.3.1/lemon/fractional_matching.h +2139 -0
- data/ext/lemon-1.3.1/lemon/full_graph.h +1082 -0
- data/ext/lemon-1.3.1/lemon/glpk.cc +1012 -0
- data/ext/lemon-1.3.1/lemon/glpk.h +263 -0
- data/ext/lemon-1.3.1/lemon/gomory_hu.h +568 -0
- data/ext/lemon-1.3.1/lemon/graph_to_eps.h +1186 -0
- data/ext/lemon-1.3.1/lemon/greedy_tsp.h +251 -0
- data/ext/lemon-1.3.1/lemon/grid_graph.h +699 -0
- data/ext/lemon-1.3.1/lemon/grosso_locatelli_pullan_mc.h +840 -0
- data/ext/lemon-1.3.1/lemon/hao_orlin.h +1015 -0
- data/ext/lemon-1.3.1/lemon/hartmann_orlin_mmc.h +654 -0
- data/ext/lemon-1.3.1/lemon/howard_mmc.h +651 -0
- data/ext/lemon-1.3.1/lemon/hypercube_graph.h +459 -0
- data/ext/lemon-1.3.1/lemon/insertion_tsp.h +533 -0
- data/ext/lemon-1.3.1/lemon/karp_mmc.h +590 -0
- data/ext/lemon-1.3.1/lemon/kruskal.h +324 -0
- data/ext/lemon-1.3.1/lemon/lemon.pc.in +10 -0
- data/ext/lemon-1.3.1/lemon/lgf_reader.h +3854 -0
- data/ext/lemon-1.3.1/lemon/lgf_writer.h +2687 -0
- data/ext/lemon-1.3.1/lemon/list_graph.h +2510 -0
- data/ext/lemon-1.3.1/lemon/lp.h +95 -0
- data/ext/lemon-1.3.1/lemon/lp_base.cc +30 -0
- data/ext/lemon-1.3.1/lemon/lp_base.h +2147 -0
- data/ext/lemon-1.3.1/lemon/lp_skeleton.cc +143 -0
- data/ext/lemon-1.3.1/lemon/lp_skeleton.h +234 -0
- data/ext/lemon-1.3.1/lemon/maps.h +4057 -0
- data/ext/lemon-1.3.1/lemon/matching.h +3505 -0
- data/ext/lemon-1.3.1/lemon/math.h +77 -0
- data/ext/lemon-1.3.1/lemon/max_cardinality_search.h +794 -0
- data/ext/lemon-1.3.1/lemon/min_cost_arborescence.h +808 -0
- data/ext/lemon-1.3.1/lemon/nagamochi_ibaraki.h +702 -0
- data/ext/lemon-1.3.1/lemon/nauty_reader.h +113 -0
- data/ext/lemon-1.3.1/lemon/nearest_neighbor_tsp.h +238 -0
- data/ext/lemon-1.3.1/lemon/network_simplex.h +1659 -0
- data/ext/lemon-1.3.1/lemon/opt2_tsp.h +367 -0
- data/ext/lemon-1.3.1/lemon/pairing_heap.h +474 -0
- data/ext/lemon-1.3.1/lemon/path.h +1164 -0
- data/ext/lemon-1.3.1/lemon/planarity.h +2754 -0
- data/ext/lemon-1.3.1/lemon/preflow.h +985 -0
- data/ext/lemon-1.3.1/lemon/quad_heap.h +343 -0
- data/ext/lemon-1.3.1/lemon/radix_heap.h +438 -0
- data/ext/lemon-1.3.1/lemon/radix_sort.h +487 -0
- data/ext/lemon-1.3.1/lemon/random.cc +29 -0
- data/ext/lemon-1.3.1/lemon/random.h +1005 -0
- data/ext/lemon-1.3.1/lemon/smart_graph.h +1344 -0
- data/ext/lemon-1.3.1/lemon/soplex.cc +465 -0
- data/ext/lemon-1.3.1/lemon/soplex.h +158 -0
- data/ext/lemon-1.3.1/lemon/static_graph.h +476 -0
- data/ext/lemon-1.3.1/lemon/suurballe.h +776 -0
- data/ext/lemon-1.3.1/lemon/time_measure.h +610 -0
- data/ext/lemon-1.3.1/lemon/tolerance.h +242 -0
- data/ext/lemon-1.3.1/lemon/unionfind.h +1824 -0
- data/ext/lemon-1.3.1/scripts/unify-sources.sh +390 -0
- data/ext/lemon-1.3.1/scripts/valgrind-wrapper.sh +22 -0
- data/ext/lemongraph/arc_map.cc +1007 -0
- data/ext/lemongraph/digraph.cc +282 -0
- data/ext/lemongraph/digraph_arc.cc +153 -0
- data/ext/lemongraph/digraph_node.cc +277 -0
- data/ext/lemongraph/edge_map.cc +770 -0
- data/ext/lemongraph/extconf.rb +53 -0
- data/ext/lemongraph/graph.cc +351 -0
- data/ext/lemongraph/graph_arc.cc +95 -0
- data/ext/lemongraph/graph_edge.cc +153 -0
- data/ext/lemongraph/graph_item.cc +76 -0
- data/ext/lemongraph/graph_node.cc +321 -0
- data/ext/lemongraph/lemongraph.cc +260 -0
- data/ext/lemongraph/lemongraph.hh +295 -0
- data/ext/lemongraph/lemongraph.map +6 -0
- data/ext/lemongraph/lemongraph_export.hh +31 -0
- data/ext/lemongraph/node_map.cc +1011 -0
- data/lemongraph.gemspec +176 -0
- data/lib/lemongraph/graphviz.rb +240 -0
- data/lib/lemongraph/version.rb +4 -0
- data/lib/lemongraph.rb +21 -0
- data/samples/lemondeps.rb +38 -0
- 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
|