@@ -35,14 +35,6 @@ namespace graph_colouring {
35
35
/* *< The actual colouring */
36
36
};
37
37
38
- /* *
39
- * Used in the parallel colouring algorithm to track certain events
40
- */
41
- struct ColouringStrategyContext {
42
- /* *> Counts the number of finished pedigrees (=populationSize/2) */
43
- std::atomic<size_t > wpCount;
44
- };
45
-
46
38
ColorCount colorCount (const Colouring &s) {
47
39
std::vector<bool > usedColor (s.size ());
48
40
ColorCount color_count = 0 ;
@@ -108,9 +100,9 @@ namespace graph_colouring {
108
100
return nextTry;
109
101
}
110
102
111
- inline bool hasFinished (const std::vector<ColouringStrategyContext > &context) {
112
- for (auto &c : context) {
113
- if (c. wpCount > 0 ) {
103
+ inline bool hasFinished (const std::vector<std::atomic< size_t > > &context) {
104
+ for (auto &wpCount : context) {
105
+ if (wpCount > 0 ) {
114
106
return false ;
115
107
}
116
108
}
@@ -122,20 +114,15 @@ namespace graph_colouring {
122
114
const size_t populationSize,
123
115
const size_t maxItr,
124
116
const size_t threadId,
125
- std::vector<ColouringStrategyContext > &context,
117
+ std::vector<std::atomic< size_t > > &context,
126
118
boost::lockfree::queue<WorkingPackage> &workQueue,
127
119
boost::lockfree::queue<MasterPackage> &masterQueue,
128
120
std::vector<Colouring> &population,
129
121
std::vector<Colouring> &localBestColourings,
130
122
std::vector<std::atomic<bool >> &lock,
131
123
std::atomic<ColorCount> &target_k,
132
124
std::atomic<bool > &terminated) {
133
- typedef std::mt19937::result_type seed_type;
134
- typename std::chrono::system_clock seed_clock;
135
- auto init_seed = static_cast <seed_type>(seed_clock.now ().time_since_epoch ().count ());
136
- init_seed += static_cast <seed_type>(threadId);
137
-
138
- std::mt19937 generator (init_seed);
125
+ std::mt19937 generator (threadId);
139
126
140
127
// Only used to avoid rapid reporting of already known colourings
141
128
ColorCount last_reported_k = target_k + 1 ;
@@ -146,12 +133,10 @@ namespace graph_colouring {
146
133
const ColouringStrategy &strategy = *strategies[wp.strategyId ];
147
134
148
135
if (target_k < wp.target_k && strategy.isFixedKStrategy ()) {
149
- context[wp.strategyId ].wpCount . fetch_sub (1 );
136
+ context[wp.strategyId ].fetch_sub (1 );
150
137
continue ;
151
138
}
152
139
153
- Colouring result;
154
-
155
140
if (wp.itr > 0 ) {
156
141
auto p1 = chooseParent (wp.strategyId , populationSize, lock, generator);
157
142
auto p2 = chooseParent (wp.strategyId , populationSize, lock, generator);
@@ -170,16 +155,22 @@ namespace graph_colouring {
170
155
auto lsOp = strategies[wp.strategyId ]->lsOperators [
171
156
lsOprDist (generator)];
172
157
173
- result = lsOp (crossoverOp (*parents[0 ], *parents[1 ], G), G);
174
- *parents[weakerParent] = result;
158
+ *parents[weakerParent] = lsOp (crossoverOp (*parents[0 ], *parents[1 ], G), G);
159
+
160
+ if (strategy.isSolution (G, target_k, *parents[weakerParent]) && last_reported_k > target_k) {
161
+ last_reported_k = colorCount (*parents[weakerParent]);
162
+ masterQueue.push ({last_reported_k, wp.strategyId });
163
+ size_t threadCount = localBestColourings.size () / strategies.size ();
164
+ localBestColourings[wp.strategyId * threadCount + threadId] = *parents[weakerParent];
165
+ }
175
166
176
167
lock[p1] = false ;
177
168
lock[p2] = false ;
178
169
179
170
if (wp.itr < maxItr) {
180
171
workQueue.push ({wp.itr + 1 , wp.strategyId , wp.target_k , wp.colouring });
181
172
} else {
182
- context[wp.strategyId ].wpCount . fetch_sub (1 );
173
+ context[wp.strategyId ].fetch_sub (1 );
183
174
}
184
175
} else {
185
176
std::uniform_int_distribution<size_t > initOprDist (0 , strategy.initOperators .size () - 1 );
@@ -188,24 +179,26 @@ namespace graph_colouring {
188
179
auto initOpr = strategy.initOperators [initOprDist (generator)];
189
180
auto lsOpr = strategy.lsOperators [lsOprDist (generator)];
190
181
191
- result = lsOpr (initOpr (G, wp.target_k ), G);
192
- population[wp.strategyId * populationSize + wp.colouring ] = result;
182
+ population[wp.strategyId * populationSize + wp.colouring ] = lsOpr (initOpr (G, wp.target_k ), G);
183
+
184
+ if (strategy.isSolution (G, target_k, population[wp.strategyId * populationSize + wp.colouring ])
185
+ && last_reported_k > target_k) {
186
+ last_reported_k = colorCount (population[wp.strategyId * populationSize + wp.colouring ]);
187
+ masterQueue.push ({last_reported_k, wp.strategyId });
188
+ size_t threadCount = localBestColourings.size () / strategies.size ();
189
+ localBestColourings[wp.strategyId * threadCount + threadId] = population[
190
+ wp.strategyId * populationSize + wp.colouring ];
191
+ }
193
192
194
193
lock[wp.strategyId * populationSize + wp.colouring ] = false ;
195
194
196
195
auto matingPopulationSize = populationSize / 2 ;
197
196
if (wp.colouring < matingPopulationSize) {
198
197
workQueue.push ({wp.itr + 1 , wp.strategyId , wp.target_k , wp.colouring });
199
198
} else {
200
- context[wp.strategyId ].wpCount . fetch_sub (1 );
199
+ context[wp.strategyId ].fetch_sub (1 );
201
200
}
202
201
}
203
- if (strategy.isSolution (G, target_k, result) && last_reported_k > target_k) {
204
- last_reported_k = colorCount (result);
205
- masterQueue.push ({last_reported_k, wp.strategyId });
206
- size_t threadCount = localBestColourings.size () / strategies.size ();
207
- localBestColourings[wp.strategyId * threadCount + threadId] = result;
208
- }
209
202
}
210
203
std::this_thread::yield ();
211
204
}
@@ -233,7 +226,7 @@ namespace graph_colouring {
233
226
std::vector<Colouring> localBestColourings (strategies.size () * threadCount);
234
227
// lock[i] = true -> i-th individual is free for mating
235
228
std::vector<std::atomic<bool >> lock (strategies.size () * populationSize);
236
- std::vector<ColouringStrategyContext > context (strategies.size ());
229
+ std::vector<std::atomic< size_t > > context (strategies.size ());
237
230
238
231
// Represents the smallest number of colors used in a recently found colouring
239
232
std::atomic<ColorCount> target_k (k);
@@ -268,7 +261,7 @@ namespace graph_colouring {
268
261
for (size_t colouringId = 0 ; colouringId < populationSize; colouringId++) {
269
262
for (size_t strategyId = 0 ; strategyId < strategies.size (); strategyId++) {
270
263
lock[strategyId * populationSize + colouringId] = true ;
271
- context[strategyId].wpCount . fetch_add (1 );
264
+ context[strategyId].fetch_add (1 );
272
265
workQueue.push ({0 , strategyId, target_k, colouringId});
273
266
}
274
267
}
@@ -285,16 +278,16 @@ namespace graph_colouring {
285
278
target_k = mp.next_k - 1 ;
286
279
for (size_t strategyId = 0 ; strategyId < strategies.size (); strategyId++) {
287
280
if (strategies[strategyId]->isFixedKStrategy ()) {
288
- // Wait until every worker stopped working on the effected population
289
- while (context[strategyId]. wpCount > 0 ) {
281
+ // Wait until every worker stopped working on the affected population
282
+ while (context[strategyId] > 0 ) {
290
283
std::this_thread::yield ();
291
284
}
292
- context[strategyId]. wpCount = 0 ;
285
+ context[strategyId] = 0 ;
293
286
for (size_t colouringId = 0 ; colouringId < populationSize; colouringId++) {
294
287
lock[strategyId * populationSize + colouringId] = true ;
295
288
}
296
289
for (size_t colouringId = 0 ; colouringId < populationSize; colouringId++) {
297
- context[strategyId].wpCount . fetch_add (1 );
290
+ context[strategyId].fetch_add (1 );
298
291
workQueue.push ({0 , strategyId, target_k, colouringId});
299
292
}
300
293
}
0 commit comments