Generated on Thu Jan 16 2025 00:00:00 for Gecode by doxygen 1.14.0
script.hpp
Go to the documentation of this file.
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Christian Schulte <schulte@gecode.org>
5 *
6 * Copyright:
7 * Christian Schulte, 2004
8 *
9 * This file is part of Gecode, the generic constraint
10 * development environment:
11 * http://www.gecode.org
12 *
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining
15 * a copy of this software and associated documentation files (the
16 * "Software"), to deal in the Software without restriction, including
17 * without limitation the rights to use, copy, modify, merge, publish,
18 * distribute, sublicense, and/or sell copies of the Software, and to
19 * permit persons to whom the Software is furnished to do so, subject to
20 * the following conditions:
21 *
22 * The above copyright notice and this permission notice shall be
23 * included in all copies or substantial portions of the Software.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 *
33 */
34
35#include <iostream>
36#include <iomanip>
37#include <fstream>
38#include <cstring>
39
40#ifndef GECODE_THREADS_WINDOWS
41#include <csignal>
42#endif
43
44namespace Gecode { namespace Driver {
45
50 class CombinedStop : public Search::Stop {
51 private:
56 static bool sigint;
58 CombinedStop(unsigned int node, unsigned int fail, unsigned int time)
59 : ns((node > 0) ? new Search::NodeStop(node) : NULL),
60 fs((fail > 0) ? new Search::FailStop(fail) : NULL),
61 ts((time > 0) ? new Search::TimeStop(time) : NULL) {
62 sigint = false;
63 }
64 public:
66 enum {
67 SR_NODE = 1 << 0,
68 SR_FAIL = 1 << 1,
69 SR_TIME = 1 << 2,
70 SR_INT = 1 << 3
71 };
73 virtual bool stop(const Search::Statistics& s, const Search::Options& o) {
74 return
75 sigint ||
76 ((ns != NULL) && ns->stop(s,o)) ||
77 ((fs != NULL) && fs->stop(s,o)) ||
78 ((ts != NULL) && ts->stop(s,o));
79 }
80
81 int reason(const Search::Statistics& s, const Search::Options& o) {
82 return
83 (((ns != NULL) && ns->stop(s,o)) ? SR_NODE : 0) |
84 (((fs != NULL) && fs->stop(s,o)) ? SR_FAIL : 0) |
85 (((ts != NULL) && ts->stop(s,o)) ? SR_TIME : 0) |
86 (sigint ? SR_INT : 0);
87 }
88
89 static Search::Stop*
90 create(unsigned int node, unsigned int fail, unsigned int time,
91 bool intr) {
92 if ( (!intr) && (node == 0) && (fail == 0) && (time == 0))
93 return NULL;
94 else
95 return new CombinedStop(node,fail,time);
96 }
97#ifdef GECODE_THREADS_WINDOWS
99 static BOOL interrupt(DWORD t) throw() {
100 if (t == CTRL_C_EVENT) {
101 sigint = true;
102 installCtrlHandler(false,true);
103 return true;
104 }
105 return false;
106 }
107#else
109 static void
111 sigint = true;
112 installCtrlHandler(false,true);
113 }
114#endif
116 static void installCtrlHandler(bool install, bool force=false) {
117 if (force || !sigint) {
118#ifdef GECODE_THREADS_WINDOWS
119 SetConsoleCtrlHandler( (PHANDLER_ROUTINE) interrupt, install);
120#else
121 std::signal(SIGINT, install ? interrupt : SIG_DFL);
122#endif
123 }
124 }
125
127 delete ns; delete fs; delete ts;
128 }
129 };
130
136 stop(Support::Timer& t, std::ostream& os);
137
142 am(double t[], unsigned int n);
143
148 dev(double t[], unsigned int n);
149
151 template<class Options>
152 inline Search::Cutoff*
154 switch (o.restart()) {
155 case RM_NONE:
156 return NULL;
157 case RM_CONSTANT:
159 case RM_LINEAR:
161 case RM_LUBY:
163 case RM_GEOMETRIC:
165 default: GECODE_NEVER;
166 }
167 return NULL;
168 }
169
170
171#ifdef GECODE_HAS_GIST
172
176 template<class Engine>
178 public:
179 static void explore(Space* root, const Gist::Options& opt) {
180 (void) Gist::dfs(root, opt);
181 }
182 };
183
185 template<typename S>
186 class GistEngine<DFS<S> > {
187 public:
188 static void explore(S* root, const Gist::Options& opt) {
189 (void) Gist::dfs(root, opt);
190 }
191 };
192
194 template<typename S>
195 class GistEngine<LDS<S> > {
196 public:
197 static void explore(S* root, const Gist::Options& opt) {
198 (void) Gist::dfs(root, opt);
199 }
200 };
201
203 template<typename S>
204 class GistEngine<BAB<S> > {
205 public:
206 static void explore(S* root, const Gist::Options& opt) {
207 (void) Gist::bab(root, opt);
208 }
209 };
210
211#endif
212
213#ifdef GECODE_HAS_CPPROFILER
214
216 template<class BaseSpace>
218 public:
220 ScriptGetInfo(void);
222 virtual std::string getInfo(const Space& home) const;
223 };
224
225#endif
226
227 template<class BaseSpace>
230 : BaseSpace(opt) {}
231
232 template<class BaseSpace>
236
237 template<class BaseSpace>
238 void
239 ScriptBase<BaseSpace>::print(std::ostream&) const {}
240
241 template<class BaseSpace>
242 void
243 ScriptBase<BaseSpace>::compare(const Space&, std::ostream&) const {}
244
245 template<class BaseSpace>
246 std::ostream&
247 ScriptBase<BaseSpace>::select_ostream(const char* sn, std::ofstream& ofs) {
248 if (strcmp(sn, "stdout") == 0) {
249 return std::cout;
250 } else if (strcmp(sn, "stdlog") == 0) {
251 return std::clog;
252 } else if (strcmp(sn, "stderr") == 0) {
253 return std::cerr;
254 } else {
255 ofs.open(sn);
256 return ofs;
257 }
258 }
259
260#ifdef GECODE_HAS_CPPROFILER
261
262 template<class BaseSpace>
264
265 template<class BaseSpace>
266 std::string
268 std::stringstream ss;
269 if (const ScriptBase<BaseSpace>* sb
270 = dynamic_cast<const ScriptBase<BaseSpace>*>(&home))
271 sb->print(ss);
272 return ss.str();
273 }
274
275#endif
276
277
281 template<class T, template<class> class E>
282 class EngineToMeta : public E<T> {
283 public:
284 EngineToMeta(T* s, const Search::Options& o) : E<T>(s,o) {}
285 };
286
287 template<class BaseSpace>
288 template<class Script, template<class> class Engine, class Options>
289 void
291 if ((o.restart() != RM_NONE) && (o.assets() > 0)) {
292 std::cerr << "Cannot use restarts and portfolio..." << std::endl;
293 exit(EXIT_FAILURE);
294 }
295 if (o.restart() != RM_NONE) {
296 runMeta<Script,Engine,Options,RBS>(o,s);
297 } else if (o.assets() > 0) {
298 runMeta<Script,Engine,Options,PBS>(o,s);
299 } else {
300 runMeta<Script,Engine,Options,EngineToMeta>(o,s);
301 }
302 }
303
304 template<class BaseSpace>
305 template<class Script, template<class> class Engine, class Options,
306 template<class, template<class> class> class Meta>
307 void
308 ScriptBase<BaseSpace>::runMeta(const Options& o, Script* s) {
309 using namespace std;
310
311 ofstream sol_file, log_file;
312
313 ostream& s_out = select_ostream(o.out_file(), sol_file);
314 ostream& l_out = select_ostream(o.log_file(), log_file);
315
317
318 try {
319 switch (o.mode()) {
320 case SM_GIST:
321#ifdef GECODE_HAS_GIST
322 {
323 Gist::Print<Script> pi(o.name());
324 Gist::VarComparator<Script> vc(o.name());
325 Gist::Options opt;
326 opt.inspect.click(&pi);
327 opt.inspect.compare(&vc);
328 opt.clone = false;
329 opt.c_d = o.c_d();
330 opt.a_d = o.a_d();
331 for (unsigned int i=0; o.inspect.click(i) != NULL; i++)
332 opt.inspect.click(o.inspect.click(i));
333 for (unsigned int i=0; o.inspect.solution(i) != NULL; i++)
334 opt.inspect.solution(o.inspect.solution(i));
335 for (unsigned int i=0; o.inspect.move(i) != NULL; i++)
336 opt.inspect.move(o.inspect.move(i));
337 for (unsigned int i=0; o.inspect.compare(i) != NULL; i++)
338 opt.inspect.compare(o.inspect.compare(i));
339 if (s == NULL)
340 s = new Script(o);
341 (void) GistEngine<Engine<Script> >::explore(s, opt);
342 }
343 break;
344 // If Gist is not available, goto solution
345#else
346 goto solution;
347#endif
348 case SM_CPPROFILER:
349#ifdef GECODE_HAS_CPPROFILER
350 {
351 CPProfilerSearchTracer::GetInfo* getInfo = nullptr;
352 if (o.profiler_info())
353 getInfo = new ScriptGetInfo<BaseSpace>;
355 (o.profiler_id(), o.name(), o.profiler_port(), getInfo);
356 }
357 /* FALL THROUGH */
358#endif
359 case SM_SOLUTION:
360#ifndef GECODE_HAS_GIST
361 solution:
362#endif
363 {
364 l_out << o.name() << endl;
365 Support::Timer t;
366 int i = static_cast<int>(o.solutions());
367 t.start();
368 if (s == NULL)
369 s = new Script(o);
370 unsigned int n_p = PropagatorGroup::all.size(*s);
371 unsigned int n_b = BrancherGroup::all.size(*s);
372 so.threads = o.threads();
373 so.c_d = o.c_d();
374 so.a_d = o.a_d();
375 so.d_l = o.d_l();
376 so.assets = o.assets();
377 so.slice = o.slice();
378 so.stop = CombinedStop::create(o.node(),o.fail(), o.time(),
379 o.interrupt());
380 so.cutoff = createCutoff(o);
381 so.clone = false;
382 so.nogoods_limit = o.nogoods() ? o.nogoods_limit() : 0U;
383 if (o.interrupt())
384 CombinedStop::installCtrlHandler(true);
385 {
386 Meta<Script,Engine> e(s,so);
387 if (o.print_last()) {
388 Script* px = NULL;
389 do {
390 Script* ex = e.next();
391 if (ex == NULL) {
392 if (px != NULL) {
393 px->print(s_out);
394 delete px;
395 }
396 break;
397 } else {
398 delete px;
399 px = ex;
400 }
401 } while (--i != 0);
402 } else {
403 do {
404 Script* ex = e.next();
405 if (ex == NULL)
406 break;
407 ex->print(s_out);
408 delete ex;
409 } while (--i != 0);
410 }
411 if (o.interrupt())
412 CombinedStop::installCtrlHandler(false);
413 Search::Statistics stat = e.statistics();
414 s_out << endl;
415 if (e.stopped()) {
416 l_out << "Search engine stopped..." << endl
417 << "\treason: ";
418 int r = static_cast<CombinedStop*>(so.stop)->reason(stat,so);
419 if (r & CombinedStop::SR_INT)
420 l_out << "user interrupt " << endl;
421 else {
422 if (r & CombinedStop::SR_NODE)
423 l_out << "node ";
424 if (r & CombinedStop::SR_FAIL)
425 l_out << "fail ";
426 if (r & CombinedStop::SR_TIME)
427 l_out << "time ";
428 l_out << "limit reached" << endl << endl;
429 }
430 }
431 l_out << "Initial" << endl
432 << "\tpropagators: " << n_p << endl
433 << "\tbranchers: " << n_b << endl
434 << endl
435 << "Summary" << endl
436 << "\truntime: ";
437 stop(t, l_out);
438 l_out << endl
439 << "\tsolutions: "
440 << ::abs(static_cast<int>(o.solutions()) - i) << endl
441 << "\tpropagations: " << stat.propagate << endl
442 << "\tnodes: " << stat.node << endl
443 << "\tfailures: " << stat.fail << endl
444 << "\trestarts: " << stat.restart << endl
445 << "\tno-goods: " << stat.nogood << endl
446 << "\tpeak depth: " << stat.depth << endl
447#ifdef GECODE_PEAKHEAP
448 << "\tpeak memory: "
449 << static_cast<int>((heap.peak()+1023) / 1024) << " KB"
450 << endl
451#endif
452 << endl;
453 }
454 delete so.stop;
455 delete so.tracer;
456 }
457 break;
458 case SM_STAT:
459 {
460 l_out << o.name() << endl;
461 Support::Timer t;
462 int i = static_cast<int>(o.solutions());
463 t.start();
464 if (s == NULL)
465 s = new Script(o);
466 unsigned int n_p = PropagatorGroup::all.size(*s);
467 unsigned int n_b = BrancherGroup::all.size(*s);
468
469 so.clone = false;
470 so.threads = o.threads();
471 so.assets = o.assets();
472 so.slice = o.slice();
473 so.c_d = o.c_d();
474 so.a_d = o.a_d();
475 so.d_l = o.d_l();
476 so.stop = CombinedStop::create(o.node(),o.fail(), o.time(),
477 o.interrupt());
478 so.cutoff = createCutoff(o);
479 so.nogoods_limit = o.nogoods() ? o.nogoods_limit() : 0U;
480 if (o.interrupt())
481 CombinedStop::installCtrlHandler(true);
482 {
483 Meta<Script,Engine> e(s,so);
484 do {
485 Script* ex = e.next();
486 if (ex == NULL)
487 break;
488 delete ex;
489 } while (--i != 0);
490 if (o.interrupt())
491 CombinedStop::installCtrlHandler(false);
492 Search::Statistics stat = e.statistics();
493 l_out << endl
494 << "\tpropagators: " << n_p << endl
495 << "\tbranchers: " << n_b << endl
496 << "\truntime: ";
497 stop(t, l_out);
498 l_out << endl
499 << "\tsolutions: "
500 << ::abs(static_cast<int>(o.solutions()) - i) << endl
501 << "\tpropagations: " << stat.propagate << endl
502 << "\tnodes: " << stat.node << endl
503 << "\tfailures: " << stat.fail << endl
504 << "\trestarts: " << stat.restart << endl
505 << "\tno-goods: " << stat.nogood << endl
506 << "\tpeak depth: " << stat.depth << endl
507#ifdef GECODE_PEAKHEAP
508 << "\tpeak memory: "
509 << static_cast<int>((heap.peak()+1023) / 1024) << " KB"
510 << endl
511#endif
512 << endl;
513 }
514 delete so.stop;
515 }
516 break;
517 case SM_TIME:
518 {
519 l_out << o.name() << endl;
520 Support::Timer t;
521 double* ts = new double[o.samples()];
522 bool stopped = false;
523 for (unsigned int ns = o.samples(); !stopped && ns--; ) {
524 t.start();
525 for (unsigned int k = o.iterations(); !stopped && k--; ) {
526 unsigned int i = o.solutions();
527 Script* s1 = new Script(o);
528 Search::Options sok;
529 sok.clone = false;
530 sok.threads = o.threads();
531 sok.assets = o.assets();
532 sok.slice = o.slice();
533 sok.c_d = o.c_d();
534 sok.a_d = o.a_d();
535 sok.d_l = o.d_l();
536 sok.stop = CombinedStop::create(o.node(),o.fail(), o.time(),
537 false);
538 sok.cutoff = createCutoff(o);
539 sok.nogoods_limit = o.nogoods() ? o.nogoods_limit() : 0U;
540 {
541 Meta<Script,Engine> e(s1,sok);
542 do {
543 Script* ex = e.next();
544 if (ex == NULL)
545 break;
546 delete ex;
547 } while (--i != 0);
548 if (e.stopped())
549 stopped = true;
550 }
551 delete sok.stop;
552 }
553 ts[ns] = t.stop() / o.iterations();
554 }
555 if (stopped) {
556 l_out << "\tSTOPPED" << endl;
557 } else {
558 double m = am(ts,o.samples());
559 double d = dev(ts,o.samples()) * 100.0;
560 l_out << "\truntime: "
561 << setw(20) << right
562 << showpoint << fixed
563 << setprecision(6) << m << "ms"
564 << setprecision(2) << " (" << d << "% deviation)"
565 << endl;
566 }
567 delete [] ts;
568 }
569 break;
570 }
571 } catch (Exception& e) {
572 cerr << "Exception: " << e.what() << "." << endl
573 << "Stopping..." << endl;
574 if (sol_file.is_open())
575 sol_file.close();
576 if (log_file.is_open())
577 log_file.close();
578 exit(EXIT_FAILURE);
579 }
580 if (sol_file.is_open())
581 sol_file.close();
582 if (log_file.is_open())
583 log_file.close();
584 }
585
586}}
587
588// STATISTICS: driver-any
Depth-first branch-and-bound search engine.
Definition search.hh:1070
Class to send solution information to CPProfiler.
Definition search.hh:423
Class to record search trace info for CPProfiler.
Definition search.hh:420
Depth-first search engine.
Definition search.hh:1036
~CombinedStop(void)
Destructor.
Definition script.hpp:126
static void installCtrlHandler(bool install, bool force=false)
Install handler for catching Ctrl-C.
Definition script.hpp:116
virtual bool stop(const Search::Statistics &s, const Search::Options &o)
Test whether search must be stopped.
Definition script.hpp:73
static Search::Stop * create(unsigned int node, unsigned int fail, unsigned int time, bool intr)
Create appropriate stop-object.
Definition script.hpp:90
static void interrupt(int)
Handler for catching Ctrl-C.
Definition script.hpp:110
@ SR_INT
Interrupted by user.
Definition script.hpp:70
@ SR_NODE
Node limit reached.
Definition script.hpp:67
@ SR_FAIL
Fail limit reached.
Definition script.hpp:68
@ SR_TIME
Time limit reached.
Definition script.hpp:69
int reason(const Search::Statistics &s, const Search::Options &o)
Report reason why search has been stopped.
Definition script.hpp:81
EngineToMeta(T *s, const Search::Options &o)
Definition script.hpp:284
static void explore(S *root, const Gist::Options &opt)
Definition script.hpp:206
static void explore(S *root, const Gist::Options &opt)
Definition script.hpp:188
static void explore(S *root, const Gist::Options &opt)
Definition script.hpp:197
Traits class for search engines.
Definition script.hpp:177
static void explore(Space *root, const Gist::Options &opt)
Definition script.hpp:179
Parametric base-class for scripts.
Definition driver.hh:729
static void run(const Options &opt, Script *s=NULL)
Definition script.hpp:290
virtual void compare(const Space &home, std::ostream &os) const
Compare with s.
Definition script.hpp:243
virtual void print(std::ostream &os) const
Print a solution to os.
Definition script.hpp:239
static std::ostream & select_ostream(const char *sn, std::ofstream &ofs)
Choose output stream according to sn.
Definition script.hpp:247
ScriptBase(const Options &opt)
Constructor.
Definition script.hpp:229
ScriptGetInfo(void)
Initialize.
Definition script.hpp:263
virtual std::string getInfo(const Space &home) const
Return info for a space (which must be a script)
Definition script.hpp:267
Options for Gist
Definition gist.hh:234
An inspector for printing simple text output.
Definition gist.hh:188
A simple comparator.
Definition gist.hh:211
Limited discrepancy search engine.
Definition search.hh:1108
Options for scripts
Definition driver.hh:366
void restart(RestartMode r)
Set default restart mode.
Definition options.hpp:373
void assets(unsigned int n)
Set default number of assets in a portfolio.
Definition options.hpp:355
void restart_scale(unsigned int scale)
Set default restart scale factor.
Definition options.hpp:391
void restart_base(double base)
Set default restart base.
Definition options.hpp:382
Base class for cutoff generators for restart-based meta engine.
Definition search.hh:472
static Cutoff * linear(unsigned long int scale=Config::slice)
Create generator for linear sequence scaled by scale.
Definition cutoff.cpp:152
static Cutoff * geometric(unsigned long int scale=Config::slice, double base=Config::base)
Definition cutoff.cpp:160
static Cutoff * constant(unsigned long int scale=Config::slice)
Create generator for constant sequence with constant s.
Definition cutoff.cpp:148
static Cutoff * luby(unsigned long int scale=Config::slice)
Create generator for luby sequence with scale-factor scale.
Definition cutoff.cpp:156
Stop-object based on number of failures
Definition search.hh:852
Stop-object based on number of nodes
Definition search.hh:829
Search engine options
Definition search.hh:746
unsigned int c_d
Create a clone after every c_d commits (commit distance)
Definition search.hh:753
bool clone
Whether engines create a clone when being initialized.
Definition search.hh:749
unsigned int d_l
Discrepancy limit (for LDS)
Definition search.hh:757
Cutoff * cutoff
Cutoff for restart-based search.
Definition search.hh:767
unsigned int a_d
Create a clone during recomputation if distance is greater than a_d (adaptive distance)
Definition search.hh:755
Stop * stop
Stop object for stopping search.
Definition search.hh:765
SearchTracer * tracer
Tracer object for tracing search.
Definition search.hh:769
unsigned int assets
Number of assets (engines) in a portfolio.
Definition search.hh:759
unsigned int slice
Size of a slice in a portfolio (in number of failures)
Definition search.hh:761
unsigned int nogoods_limit
Depth limit for extraction of no-goods.
Definition search.hh:763
double threads
Number of threads to use.
Definition search.hh:751
Search engine statistics
Definition search.hh:147
Base-class for Stop-object.
Definition search.hh:799
static Stop * node(unsigned long int l)
Stop if node limit l has been exceeded.
Definition stop.cpp:43
static Stop * time(unsigned long int l)
Stop if time limit l (in milliseconds) has been exceeded.
Definition stop.cpp:51
static Stop * fail(unsigned long int l)
Stop if failure limit l has been exceeded.
Definition stop.cpp:47
Stop-object based on time
Definition search.hh:871
Computation spaces.
Definition core.hpp:1744
#define GECODE_DRIVER_EXPORT
Definition driver.hh:61
const int * pi[]
Definition photo.cpp:14262
Heap heap
The single global heap.
Definition heap.cpp:44
@ SM_STAT
Print statistics for script.
Definition driver.hh:97
@ SM_GIST
Run script in Gist.
Definition driver.hh:98
@ SM_CPPROFILER
Run script with CP-profiler.
Definition driver.hh:99
@ SM_TIME
Measure average runtime.
Definition driver.hh:96
@ RM_CONSTANT
Restart with constant sequence.
Definition driver.hh:108
@ RM_LINEAR
Restart with linear sequence.
Definition driver.hh:109
@ RM_LUBY
Restart with Luby sequence.
Definition driver.hh:110
@ RM_NONE
No restarts.
Definition driver.hh:107
@ RM_GEOMETRIC
Restart with geometric sequence.
Definition driver.hh:111
Driver::ScriptBase< Driver::IgnoreStepOption< Space > > Script
Base-class for scripts.
Definition driver.hh:801
int bab(Space *root, const Gist::Options &opt=Gist::Options::def)
Create a new stand-alone Gist for branch-and-bound search of root.
Definition gist.hpp:208
int dfs(Space *root, const Gist::Options &opt=Gist::Options::def)
Create a new stand-alone Gist for root.
Definition gist.hpp:203
Script commandline driver.
double dev(double t[], unsigned int n)
Compute deviation of n elements in t.
Definition script.cpp:84
void stop(Support::Timer &timer, std::ostream &os)
Get time since start of timer and print user friendly time information.
Definition script.cpp:42
Search::Cutoff * createCutoff(const Options &o)
Create cutoff object from options.
Definition script.hpp:153
double am(double t[], unsigned int n)
Compute arithmetic mean of n elements in t.
Definition script.cpp:74
Gecode toplevel namespace
Post propagator for SetVar SetOpType SetVar SetRelType r
Definition set.hh:773
Gecode::IntArgs i({1, 2, 3, 4})
Gecode::IntSet d(v, 7)
#define forceinline
Definition config.hpp:194
#define GECODE_NEVER
Assert that this command is never executed.
Definition macros.hpp:56