dep_selector 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,557 @@
1
+ //
2
+ // Author:: Christopher Walters (<cw@opscode.com>)
3
+ // Author:: Mark Anderson (<mark@opscode.com>)
4
+ // Copyright:: Copyright (c) 2010-2011 Opscode, Inc.
5
+ // License:: Apache License, Version 2.0
6
+ //
7
+ // Licensed under the Apache License, Version 2.0 (the "License");
8
+ // you may not use this file except in compliance with the License.
9
+ // You may obtain a copy of the License at
10
+ //
11
+ // http://www.apache.org/licenses/LICENSE-2.0
12
+ //
13
+ // Unless required by applicable law or agreed to in writing, software
14
+ // distributed under the License is distributed on an "AS IS" BASIS,
15
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ // See the License for the specific language governing permissions and
17
+ // limitations under the License.
18
+ //
19
+
20
+ #include <gecode/driver.hh>
21
+ #include <gecode/int.hh>
22
+ #include <gecode/minimodel.hh>
23
+ #include <gecode/gist.hh>
24
+ #include <gecode/search.hh>
25
+
26
+ #include "dep_selector_to_gecode.h"
27
+
28
+ #include <limits>
29
+ #include <iostream>
30
+ #include <vector>
31
+
32
+ //#define DEBUG
33
+ //#define USE_DUMB_BRANCHING
34
+ #define VECTOR_CONSTRAIN
35
+
36
+ using namespace Gecode;
37
+ const int VersionProblem::UNRESOLVED_VARIABLE = INT_MIN;
38
+ const int VersionProblem::MIN_TRUST_LEVEL = 0;
39
+ const int VersionProblem::MAX_TRUST_LEVEL = 10;
40
+ const int VersionProblem::MAX_PREFERRED_WEIGHT = 10;
41
+
42
+ VersionProblem::VersionProblem(int packageCount)
43
+ : size(packageCount), finalized(false), cur_package(0), package_versions(*this, packageCount),
44
+ disabled_package_variables(*this, packageCount, 0, 1), total_disabled(*this, 0, packageCount*MAX_TRUST_LEVEL),
45
+ total_required_disabled(*this, 0, packageCount), total_induced_disabled(*this, 0, packageCount),
46
+ total_suspicious_disabled(*this, 0, packageCount),
47
+ is_required(new int[packageCount]),
48
+ is_suspicious(new int[packageCount]),
49
+ at_latest(*this, packageCount, 0, 1),
50
+ // These domains could be narrowed a bit; check later
51
+ total_preferred_at_latest(*this, -packageCount*MAX_PREFERRED_WEIGHT, packageCount*MAX_PREFERRED_WEIGHT),
52
+ total_not_preferred_at_latest(*this, -packageCount, packageCount),
53
+ preferred_at_latest_weights(new int[packageCount])
54
+ {
55
+ for (int i = 0; i < packageCount; i++)
56
+ {
57
+ preferred_at_latest_weights[i] = 0;
58
+ is_required[i] = 0;
59
+ is_suspicious[i] = 0;
60
+ }
61
+ }
62
+
63
+ VersionProblem::VersionProblem(bool share, VersionProblem & s)
64
+ : Space(share, s), size(s.size),
65
+ finalized(s.finalized), cur_package(s.cur_package),
66
+ disabled_package_variables(s.disabled_package_variables), total_disabled(s.total_disabled),
67
+ total_required_disabled(s.total_required_disabled), total_induced_disabled(s.total_induced_disabled),
68
+ total_suspicious_disabled(s.total_suspicious_disabled),
69
+ is_required(NULL), is_suspicious(NULL),
70
+ at_latest(s.at_latest),
71
+ total_preferred_at_latest(s.total_preferred_at_latest),
72
+ total_not_preferred_at_latest(s.total_preferred_at_latest),
73
+ preferred_at_latest_weights(NULL)
74
+ {
75
+ package_versions.update(*this, share, s.package_versions);
76
+ disabled_package_variables.update(*this, share, s.disabled_package_variables);
77
+ total_disabled.update(*this, share, s.total_disabled);
78
+ total_required_disabled.update(*this, share, s.total_required_disabled);
79
+ total_induced_disabled.update(*this, share, s.total_induced_disabled);
80
+ total_suspicious_disabled.update(*this, share, s.total_suspicious_disabled);
81
+ at_latest.update(*this, share, s.at_latest);
82
+ total_preferred_at_latest.update(*this, share, s.total_preferred_at_latest);
83
+ total_not_preferred_at_latest.update(*this, share, s.total_not_preferred_at_latest);
84
+ }
85
+
86
+ // Support for gecode
87
+ Space* VersionProblem::copy(bool share)
88
+ {
89
+ return new VersionProblem(share,*this);
90
+ }
91
+
92
+ VersionProblem::~VersionProblem()
93
+ {
94
+ delete[] preferred_at_latest_weights;
95
+ delete[] is_required;
96
+ delete[] is_suspicious;
97
+ }
98
+
99
+ int VersionProblem::Size()
100
+ {
101
+ return size;
102
+ }
103
+
104
+ int VersionProblem::PackageCount()
105
+ {
106
+ return cur_package;
107
+ }
108
+
109
+ int
110
+ VersionProblem::AddPackage(int minVersion, int maxVersion, int currentVersion)
111
+ {
112
+ if (cur_package == size) {
113
+ return -1;
114
+ }
115
+
116
+ #ifdef DEBUG
117
+ std::cout << "Adding package id " << cur_package << '/' << size << ": min = " << minVersion << ", max = " << maxVersion << ", current version " << currentVersion << std::endl;
118
+ std::cout.flush();
119
+ #endif // DEBUG
120
+ int index = cur_package;
121
+ cur_package++;
122
+ // IntVar version(*this, minVersion, maxVersion);
123
+ package_versions[index] = IntVar(*this, minVersion, maxVersion);
124
+
125
+ // register the binding of package to version that corresponds to the package's latest
126
+ rel(*this, package_versions[index], IRT_EQ, maxVersion, at_latest[index]);
127
+
128
+ return index;
129
+ }
130
+
131
+ bool
132
+ VersionProblem::AddVersionConstraint(int packageId, int version,
133
+ int dependentPackageId, int minDependentVersion, int maxDependentVersion)
134
+ {
135
+ BoolVar version_match(*this, 0, 1);
136
+ BoolVar depend_match(*this, 0, 1);
137
+ BoolVar predicated_depend_match(*this, 0, 1);
138
+
139
+ #ifdef DEBUG
140
+ std::cout << "Add VC for " << packageId << " @ " << version << " depPkg " << dependentPackageId;
141
+ std::cout << " [ " << minDependentVersion << ", " << maxDependentVersion << " ]" << std::endl;
142
+ std::cout.flush();
143
+ #endif // DEBUG
144
+
145
+
146
+ //version_flags << version_match;
147
+ // Constrain pred to reify package @ version
148
+ rel(*this, package_versions[packageId], IRT_EQ, version, version_match);
149
+ // Add the predicated version constraints imposed on dependent package
150
+
151
+ // package_versions[dependendPackageId] in domain [minDependentVersion,maxDependentVersion] <=> depend_match
152
+ dom(*this, package_versions[dependentPackageId], minDependentVersion, maxDependentVersion, depend_match);
153
+
154
+ // disabled_package_variables[dependentPackageId] OR depend_match <=> predicated_depend_match
155
+ // rel(*this, disabled_package_variables[dependentPackageId], BOT_OR, depend_match, version_match);
156
+
157
+ rel(*this, disabled_package_variables[dependentPackageId], BOT_OR, depend_match, predicated_depend_match);
158
+ rel(*this, version_match, BOT_IMP, predicated_depend_match, 1);
159
+ }
160
+
161
+ void
162
+ VersionProblem::MarkPackageSuspicious(int packageId)
163
+ {
164
+ is_suspicious[packageId] = 1;
165
+ }
166
+
167
+ void
168
+ VersionProblem::MarkPackageRequired(int packageId)
169
+ {
170
+ is_required[packageId] = 1;
171
+ }
172
+
173
+ void
174
+ VersionProblem::MarkPackagePreferredToBeAtLatest(int packageId, int weight)
175
+ {
176
+ preferred_at_latest_weights[packageId] = std::max(MAX_PREFERRED_WEIGHT, std::min(0, weight));
177
+ }
178
+
179
+ void VersionProblem::Finalize()
180
+ {
181
+ #ifdef DEBUG
182
+ std::cout << "Finalization Started" << std::endl;
183
+ std::cout.flush();
184
+ #endif // DEBUG
185
+ finalized = true;
186
+
187
+ // Setup constraint for cost
188
+ // We wish to minimize the total number of disabled packages, by priority ranks
189
+ IntArgs disabled_required_weights(size, is_required);
190
+ linear(*this, disabled_required_weights, disabled_package_variables, IRT_EQ, total_required_disabled);
191
+ #ifdef DEBUG
192
+ std::cout << "disabled_required_weights: " << disabled_required_weights << std::endl;
193
+ std::cout << "total_required_disabled: " << total_required_disabled << std::endl;
194
+ #endif // DEBUG
195
+
196
+ IntArgs disabled_induced_weights(size);
197
+ for (int i = 0; i < size; i++) {
198
+ disabled_induced_weights[i] = !(is_required[i] || is_suspicious[i]);
199
+ }
200
+ linear(*this, disabled_induced_weights, disabled_package_variables, IRT_EQ, total_induced_disabled);
201
+ #ifdef DEBUG
202
+ std::cout << "disabled_induced_weights: " << disabled_induced_weights << std::endl;
203
+ std::cout << "total_induced_disabled: " << total_induced_disabled << std::endl;
204
+ #endif // DEBUG
205
+
206
+ IntArgs disabled_suspicious_weights(size, is_suspicious);
207
+ linear(*this, disabled_suspicious_weights, disabled_package_variables, IRT_EQ, total_suspicious_disabled);
208
+ #ifdef DEBUG
209
+ std::cout << "disabled_suspicious_weights: " << disabled_suspicious_weights << std::endl;
210
+ std::cout << "total_suspicious_disabled: " << total_suspicious_disabled << std::endl;
211
+ #endif // DEBUG
212
+
213
+ linear(*this, disabled_package_variables, IRT_EQ, total_disabled);
214
+ #ifdef DEBUG
215
+ std::cout << "total_disabled: " << total_disabled << std::endl;
216
+ #endif DEBUG
217
+
218
+ // Setup computation for total_preferred_at_latest
219
+ // We wish to maximize the total number of packages at their latest versions in the preferred tier of packages
220
+ // We negate the weights in the cost function to make it fit into the context of a minimization problem.
221
+ for (int i = 0; i < size; i++) {
222
+ preferred_at_latest_weights[i] = -preferred_at_latest_weights[i];
223
+ }
224
+ IntArgs preferred_at_latest_weights_args(size, preferred_at_latest_weights);
225
+ linear(*this, preferred_at_latest_weights_args, at_latest, IRT_EQ, total_preferred_at_latest);
226
+ #ifdef DEBUG
227
+ std::cout << "preferred_at_latest_weights_args: " << preferred_at_latest_weights_args << std::endl;
228
+ std::cout << "total_preferred_at_latest: " << total_preferred_at_latest << std::endl;
229
+ #endif DEBUG
230
+
231
+ // Setup computation for remaining variables
232
+ // We wish to maximize the total number of packages at their latest version in the non-preferred tier of packages
233
+ // We negate the weights in the cost function to make it fit into the context of a minimization problem.
234
+ IntArgs not_preferred_at_latest_weights_args = IntArgs::create(size, 0, 0);
235
+ for (int i = 0; i < size; i++) {
236
+ if (preferred_at_latest_weights[i] == 0) {
237
+ not_preferred_at_latest_weights_args[i] = -1;
238
+ }
239
+ }
240
+ linear(*this, not_preferred_at_latest_weights_args, at_latest, IRT_EQ, total_not_preferred_at_latest);
241
+ #ifdef DEBUG
242
+ std::cout << "not_preferred_at_latest_weights_args: " << not_preferred_at_latest_weights_args << std::endl;
243
+ std::cout << "total_not_preferred_at_latest: " << total_not_preferred_at_latest << std::endl;
244
+ #endif DEBUG
245
+
246
+ // Cleanup
247
+ // Assign a dummy variable to elements greater than actually used.
248
+ for (int i = cur_package; i < size; i++) {
249
+ package_versions[i] = IntVar(*this, -1, -1);
250
+ disabled_package_variables[i] = BoolVar(*this, 1, 1);
251
+ }
252
+
253
+ #ifdef USE_DUMB_BRANCHING
254
+ # ifdef DEBUG
255
+ std::cout << "Adding branching (POOR)" << std::endl;
256
+ std::cout.flush();
257
+ # endif // DEBUG
258
+ // This branching starts as far as possible from the solution, in order to exercise the optimization functions.
259
+ branch(*this, disabled_package_variables, INT_VAR_SIZE_MIN, INT_VAL_MAX);
260
+ branch(*this, package_versions, INT_VAR_SIZE_MIN, INT_VAL_MIN);
261
+ branch(*this, total_required_disabled, INT_VAL_MAX);
262
+ branch(*this, total_induced_disabled, INT_VAL_MAX);
263
+ branch(*this, total_suspicious_disabled, INT_VAL_MAX);
264
+ branch(*this, total_disabled, INT_VAL_MAX);
265
+ branch(*this, at_latest, INT_VAR_SIZE_MIN, INT_VAL_MIN);
266
+ branch(*this, total_preferred_at_latest, INT_VAL_MIN);
267
+ branch(*this, total_not_preferred_at_latest, INT_VAL_MIN);
268
+ #else // USE_DUMB_BRANCHING
269
+ # ifdef DEBUG
270
+ std::cout << "Adding branching (BEST)" << std::endl;
271
+ std::cout.flush();
272
+ # endif // DEBUG
273
+ // This branching is meant to start with most probable solution
274
+ branch(*this, disabled_package_variables, INT_VAR_SIZE_MIN, INT_VAL_MIN);
275
+ branch(*this, package_versions, INT_VAR_SIZE_MIN, INT_VAL_MAX);
276
+ branch(*this, total_required_disabled, INT_VAL_MIN);
277
+ branch(*this, total_induced_disabled, INT_VAL_MIN);
278
+ branch(*this, total_suspicious_disabled, INT_VAL_MIN);
279
+ branch(*this, total_disabled, INT_VAL_MIN);
280
+ branch(*this, at_latest, INT_VAR_SIZE_MIN, INT_VAL_MAX);
281
+ branch(*this, total_preferred_at_latest, INT_VAL_MAX);
282
+ branch(*this, total_not_preferred_at_latest, INT_VAL_MAX);
283
+ #endif // USE_DUMB_BRANCHING
284
+
285
+ #ifdef DEBUG
286
+ std::cout << "Finalization Done" << std::endl;
287
+ std::cout.flush();
288
+ #endif // DEBUG
289
+ }
290
+
291
+ ////////////////////////////////////////////////////////////////////////
292
+ // A general note about constrain functions
293
+ ////////////////////////////////////////////////////////////////////////
294
+ //
295
+ // Constrain functions take a space ('best_known_solution') that is has an assignment of variables
296
+ // and operate in the context of a fresh space, not yet fully assigned. Their purpose is to add
297
+ // constraints such that the assignments in the fresh space will either yield a better solution, or
298
+ // none at all if the best_known_solution is the best possible.
299
+ //
300
+
301
+ #ifdef TOTAL_DISABLED_COST
302
+ //
303
+ // Very simple constraint function that only minimizes total disabled packages. This is left here
304
+ // for debugging purposes. Turn this on to test that the basic system can be solved.
305
+ //
306
+ void VersionProblem::constrain(const Space & _best_known_solution)
307
+ {
308
+ const VersionProblem& best_known_solution = static_cast<const VersionProblem &>(_best_known_solution);
309
+
310
+ // add first-level objective function minimization (failing packages, weighted)
311
+ // new constraint: total_disabled < best_known_total_disabled_value)
312
+ int best_known_total_disabled_value = best_known_solution.total_disabled.val();
313
+ rel(*this, total_disabled, IRT_LE, best_known_total_disabled_value);
314
+ PrintVarAligned("Constrain: total_disabled: ", total_disabled);
315
+ }
316
+ #endif // TOTAL_DISABLED_COST
317
+
318
+ // _best_known_soln is the most recent satisfying assignment of
319
+ // variables that Gecode has found. This method examines the solution
320
+ // and adds additional constraints that are applied after restarting
321
+ // the search, which means that the next time a solution that's found
322
+ // must be strictly better than the current best known solution.
323
+ //
324
+ // Our model requires us to have a series of objective functions where
325
+ // each successive objective function is evaluated if and only if all
326
+ // higher precedent objective functions are tied.
327
+ //
328
+ // [TODO: DESCRIBE WHAT THE ACTUAL SERIES OF OBJECTIVE FUNCTIONS IS]
329
+ //
330
+ // Lower precedent objective functions are modeled as the consequent
331
+ // of an implication whose antecedent is the conjunction of all the
332
+ // higher precedent objective functions being assigned to their best
333
+ // known value; thus, the optimal value of an objection function
334
+ // "activates" the next highest objective function. This has the
335
+ // effect of isolating the logic of each objective function such that
336
+ // it is only applied to the set of equally preferable solutions under
337
+ // the higher precedent objective functions. The objective function
338
+ // then applies its constraints, the solution space is restarted and
339
+ // walks the space until it finds another, more constrained solution.
340
+
341
+ #ifdef VECTOR_CONSTRAIN
342
+ //
343
+ // The vector constrain function assembles multiple cost functions into a vector cost, and then
344
+ // constrains the vector cost to be less than the vector cost of the current best_known_solution.
345
+ // The less than operation here is a pairwise comparison in order of decreasing precedence; only if
346
+ // higher precedence elements are tied will the lower precedence elements be consulted. The elements
347
+ // are in increasing order of precedence.
348
+ //
349
+ // In this case the lowest precedence cost is total_not_preferred_at_latest, followed by total_preferred_at_latest
350
+ // and finally total_disabled.
351
+ //
352
+ void VersionProblem::constrain(const Space & _best_known_solution)
353
+ {
354
+ const VersionProblem& best_known_solution = static_cast<const VersionProblem &>(_best_known_solution);
355
+
356
+ IntVarArgs current(5);
357
+ IntVarArgs best(5);
358
+ BuildCostVector(current);
359
+ best_known_solution.BuildCostVector(best);
360
+ ConstrainVectorLessThanBest(current, best);
361
+ }
362
+ #endif // VECTOR_CONSTRAIN
363
+
364
+ void VersionProblem::BuildCostVector(IntVarArgs & costVector) const {
365
+ costVector[0] = total_not_preferred_at_latest;
366
+ costVector[1] = total_preferred_at_latest;
367
+ costVector[2] = total_suspicious_disabled;
368
+ costVector[3] = total_induced_disabled;
369
+ costVector[4] = total_required_disabled;
370
+ }
371
+
372
+
373
+
374
+ IntVar & VersionProblem::GetPackageVersionVar(int packageId)
375
+ {
376
+ if (packageId < cur_package) {
377
+ return package_versions[packageId];
378
+ } else {
379
+ #ifdef DEBUG
380
+ std::cout << "Bad package Id " << packageId << " >= " << cur_package << std::endl;
381
+ std::cout.flush();
382
+ #endif //DEBUG
383
+ // return 0;
384
+ }
385
+ }
386
+
387
+ int VersionProblem::GetPackageVersion(int packageId)
388
+ {
389
+ IntVar & var = GetPackageVersionVar(packageId);
390
+ if (1 == var.size()) return var.val();
391
+ return UNRESOLVED_VARIABLE;
392
+ }
393
+ bool VersionProblem::GetPackageDisabledState(int packageId)
394
+ {
395
+ return disabled_package_variables[packageId].val() == 1;
396
+ }
397
+
398
+ int VersionProblem::GetMax(int packageId)
399
+ {
400
+ return GetPackageVersionVar(packageId).max();
401
+ }
402
+ int VersionProblem::GetMin(int packageId)
403
+ {
404
+ return GetPackageVersionVar(packageId).min();
405
+ }
406
+
407
+ int VersionProblem::GetDisabledVariableCount()
408
+ {
409
+ if (total_disabled.min() == total_disabled.max()) {
410
+ return total_disabled.min();
411
+ } else {
412
+ return UNRESOLVED_VARIABLE;
413
+ }
414
+ }
415
+
416
+
417
+ // Utility
418
+ void VersionProblem::Print(std::ostream & out)
419
+ {
420
+ out << "Version problem dump: " << cur_package << "/" << size << " packages used/allocated" << std::endl;
421
+ out << "Disabled Variables: " << disabled_package_variables << std::endl;
422
+ out << "Total Disabled variables (required): " << total_required_disabled << std::endl;
423
+ out << "Total Disabled variables: (induced): " << total_induced_disabled << std::endl;
424
+ out << "Total Disabled variables: (suspicious): " << total_suspicious_disabled << std::endl;
425
+ out << "Total Disabled variables: " << total_disabled << std::endl;
426
+ out << "at_latest: " << at_latest << std::endl;
427
+ out << "total_preferred_at_latest: " << total_preferred_at_latest << std::endl;
428
+ out << "total_not_preferred_at_latest: " << total_not_preferred_at_latest << std::endl;
429
+ for (int i = 0; i < cur_package; i++) {
430
+ out << "\t";
431
+ PrintPackageVar(out, i);
432
+ out << std::endl;
433
+ }
434
+ out.flush();
435
+ }
436
+
437
+ // TODO: Validate package ids !
438
+
439
+ void VersionProblem::PrintPackageVar(std::ostream & out, int packageId)
440
+ {
441
+ IntVar & var = GetPackageVersionVar(packageId);
442
+ out << "PackageId: " << packageId << " Sltn: " << var << " disabled: " << disabled_package_variables[packageId] << " at latest: " << at_latest[packageId];
443
+ }
444
+
445
+ bool VersionProblem::CheckPackageId(int id)
446
+ {
447
+ return (id < size);
448
+ }
449
+
450
+ // We want to sort vectors
451
+ // This constrains current to be less than best by a process analogous to subtraction
452
+ // we compute current - best, pairwise with borrows from less significant elements. We require it to be less than zero by requiring the most
453
+ // significant element to generate a borrow.
454
+ //
455
+ void VersionProblem::ConstrainVectorLessThanBest(IntVarArgs & current, IntVarArgs & best) {
456
+ BoolVarArray borrow(*this, current.size()+1, 0, 1);
457
+
458
+ // No borrows can happen at the least significant element.
459
+ rel(*this, borrow[0], IRT_EQ, 0);
460
+
461
+ for (int i = 0; i < current.size(); i++) {
462
+ // If best+borrow is greater than current (equivalently current-(best+borrow) is < 0) then a more significant element
463
+ // must have decreased, so we propagate a borrow to the next most significant element.
464
+ int best_val = best[i].val();
465
+ IntVar delta = expr(*this, current[i] - best_val - borrow[i]);
466
+ // (delta < 0) <=> borrow[i+1]
467
+ rel(*this, delta, IRT_LE, 0, borrow[i+1]);
468
+ #ifdef DEBUG
469
+ std::cout << "ConstrainVector: borrow[" << i+1 << "] " << borrow[i+1] << ",\tdelta " << delta << std::endl;
470
+ std::cout << "ConstrainVector: current[" << i << "] " << current[i] << ",\tbest_val " << best_val << std::endl;
471
+ #endif //DEBUG
472
+ }
473
+
474
+ // must borrow off past the most significant element.
475
+ rel(*this, borrow[current.size()], IRT_EQ, 1);
476
+ }
477
+
478
+ VersionProblem * VersionProblem::Solve(VersionProblem * problem)
479
+ {
480
+ problem->Finalize();
481
+ problem->status();
482
+ #ifdef DEBUG
483
+ std::cout << "Before solve" << std::endl;
484
+ problem->Print(std::cout);
485
+ #endif //DEBUG
486
+ int i = 0;
487
+
488
+ Gecode::Support::Timer timer;
489
+ VersionProblem *best_solution = NULL;
490
+ timer.start();
491
+
492
+ for (int k = 0; k < 1; k++)
493
+ {
494
+
495
+ Restart<VersionProblem> solver(problem);
496
+ best_solution = NULL;
497
+
498
+ while (VersionProblem *solution = solver.next())
499
+ {
500
+ if (best_solution != NULL)
501
+ {
502
+ delete best_solution;
503
+ }
504
+ best_solution = solution;
505
+ ++i;
506
+ #ifdef DEBUG
507
+ std::cout << "Trial Solution #" << i << "===============================" << std::endl;
508
+ const Search::Statistics & stats = solver.statistics();
509
+ std::cout << "Solver stats: Prop:" << stats.propagate << " Fail:" << stats.fail << " Node:" << stats.node;
510
+ std::cout << " Depth:" << stats.depth << " memory:" << stats.memory << std::endl;
511
+ solution->Print(std::cout);
512
+ #endif //DEBUG
513
+ }
514
+
515
+ }
516
+
517
+ double elapsed_time = timer.stop();
518
+ #ifdef DEBUG_LITE
519
+ std::cout << "Solution completed: " << (best_solution ? "Found solution" : "No solution found") << std::endl;
520
+ std::cout << "Solution consumed: " << elapsed_time << " ms " << i << " steps" << std::endl;
521
+ std::cout << "======================================================================" << std::endl;
522
+ std::cout.flush();
523
+ #endif // DEBUG_LITE
524
+
525
+ return best_solution;
526
+ }
527
+
528
+ //
529
+ // Debug output
530
+ //
531
+ template <class T> void PrintVarAligned(const char * message, T & var)
532
+ {
533
+ #ifdef DEBUG
534
+ std::cout.width(40);
535
+ std::cout << std::left << message << var << std::endl;
536
+ std::cout.width(0);
537
+ #endif
538
+ }
539
+ template <class S, class T> void PrintVarAligned(const char * message, S & var1, T & var2)
540
+ {
541
+ #ifdef DEBUG
542
+ std::cout.width(40);
543
+ std::cout << std::left << message << var1 << " " << var2 << std::endl;
544
+ std::cout.width(0);
545
+ #endif
546
+ }
547
+
548
+ //template void PrintVarAligned<int>(const char * message, int & var);
549
+
550
+
551
+
552
+ //
553
+ // Version Problem
554
+ //
555
+ //
556
+ //
557
+ //