this repo has no description
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, 2012
8 *
9 * This file is part of Gecode, the generic constraint
10 * development environment:
11 * http://www.gecode.org
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining
14 * a copy of this software and associated documentation files (the
15 * "Software"), to deal in the Software without restriction, including
16 * without limitation the rights to use, copy, modify, merge, publish,
17 * distribute, sublicense, and/or sell copies of the Software, and to
18 * permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be
22 * included in all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 *
32 */
33
34#include <cfloat>
35
36namespace Gecode {
37
38 /**
39 * \brief Class for action management
40 *
41 */
42 class Action : public SharedHandle {
43 protected:
44 template<class View, bool p, bool f>
45 class Recorder;
46 /// Object for storing action values
47 class GECODE_VTABLE_EXPORT Storage : public SharedHandle::Object {
48 public:
49 /// Mutex to synchronize globally shared access
50 GECODE_KERNEL_EXPORT static Support::Mutex m;
51 /// Number of action values
52 int n;
53 /// Inverse decay factor
54 double invd;
55 /// Action values (more follow)
56 double* a;
57 /// Initialize action values
58 template<class View>
59 Storage(Home home, ViewArray<View>& x, double d,
60 typename BranchTraits<typename View::VarType>::Merit bm);
61 /// Update action value at position \a i
62 void update(int i);
63 /// Delete object
64 GECODE_KERNEL_EXPORT
65 ~Storage(void);
66 };
67 /// Return object of correct type
68 Storage& object(void) const;
69 /// Set object to \a o
70 void object(Storage& o);
71 /// Update action value at position \a i
72 void update(int i);
73 /// Acquire mutex
74 void acquire(void);
75 /// Release mutex
76 void release(void);
77 public:
78 /// \name Constructors and initialization
79 //@{
80 /**
81 * \brief Construct as not yet intialized
82 *
83 * The only member functions that can be used on a constructed but not
84 * yet initialized action storage is init and the assignment operator.
85 *
86 */
87 Action(void);
88 /// Copy constructor
89 GECODE_KERNEL_EXPORT
90 Action(const Action& a);
91 /// Assignment operator
92 GECODE_KERNEL_EXPORT
93 Action& operator =(const Action& a);
94 /**
95 * \brief Initialize for views \a x and decay factor \a d and action as defined by \a bm
96 *
97 * Count propagation if \a p is true, count failure if \a f is true.
98 */
99 template<class View>
100 Action(Home home, ViewArray<View>& x, double d, bool p, bool f,
101 typename BranchTraits<typename View::VarType>::Merit bm);
102 /**
103 * \brief Initialize for views \a x and decay factor \a d and action as defined by \a bm
104 *
105 * Count propagation if \a p is true, count failure if \a f is true.
106 */
107 template<class View>
108 void init(Home home, ViewArray<View>& x, double d, bool p, bool f,
109 typename BranchTraits<typename View::VarType>::Merit bm);
110 /// Default (empty) action information
111 GECODE_KERNEL_EXPORT static const Action def;
112 //@}
113
114 /// Destructor
115 GECODE_KERNEL_EXPORT
116 ~Action(void);
117
118 /// \name Information access
119 //@{
120 /// Return action value at position \a i
121 double operator [](int i) const;
122 /// Return number of action values
123 int size(void) const;
124 //@}
125
126 /// \name Decay factor for aging
127 //@{
128 /// Set decay factor to \a d
129 GECODE_KERNEL_EXPORT
130 void decay(Space& home, double d);
131 /// Return decay factor
132 GECODE_KERNEL_EXPORT
133 double decay(const Space& home) const;
134 //@}
135 };
136
137 /// Propagator for recording action information
138 template<class View, bool p, bool f>
139 class Action::Recorder : public NaryPropagator<View,PC_GEN_NONE> {
140 protected:
141 using NaryPropagator<View,PC_GEN_NONE>::x;
142 /// Advisor with index and change information
143 class Idx : public Advisor {
144 protected:
145 /// Index and mark/failed information
146 unsigned int _info;
147 public:
148 /// Constructor for creation
149 Idx(Space& home, Propagator& r, Council<Idx>& c, int i);
150 /// Constructor for cloning \a a
151 Idx(Space& home, Idx& a);
152 /// Mark index as propagated
153 void propagate(void);
154 /// Mark index as failed
155 void fail(void);
156 /// Whether index has been propagated
157 bool propagated(void) const;
158 /// Whether index has been failed
159 bool failed(void) const;
160 /// Clear any information
161 void clear(void);
162 /// Get index of view
163 int idx(void) const;
164 };
165 /// Access to action information
166 Action a;
167 /// The advisor council
168 Council<Idx> c;
169 /// Constructor for cloning \a r
170 Recorder(Space& home, Recorder<View,p,f>& r);
171 public:
172 /// Constructor for creation
173 Recorder(Home home, ViewArray<View>& x, Action& a);
174 /// Copy propagator during cloning
175 virtual Propagator* copy(Space& home);
176 /// Cost function (record so that propagator runs last)
177 virtual PropCost cost(const Space& home, const ModEventDelta& med) const;
178 /// Schedule function
179 virtual void reschedule(Space& home);
180 /// Give advice to propagator
181 virtual ExecStatus advise(Space& home, Advisor& a, const Delta& d);
182 /// Give advice to propagator when \a home has failed
183 virtual void advise(Space& home, Advisor& a);
184 /// Perform propagation
185 virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
186 /// Delete propagator and return its size
187 virtual size_t dispose(Space& home);
188 /// Post action recorder propagator
189 static ExecStatus post(Home home, ViewArray<View>& x, Action& a);
190 };
191
192 /**
193 * \brief Print action values enclosed in curly brackets
194 * \relates Action
195 */
196 template<class Char, class Traits>
197 std::basic_ostream<Char,Traits>&
198 operator <<(std::basic_ostream<Char,Traits>& os,
199 const Action& a);
200
201
202 /*
203 * Advisor for action recorder
204 *
205 */
206 template<class View, bool p, bool f>
207 forceinline
208 Action::Recorder<View,p,f>::Idx::Idx(Space& home, Propagator& r,
209 Council<Idx>& c, int i)
210 : Advisor(home,r,c), _info(static_cast<unsigned int>(i) << 2U) {}
211 template<class View, bool p, bool f>
212 forceinline
213 Action::Recorder<View,p,f>::Idx::Idx(Space& home, Idx& a)
214 : Advisor(home,a), _info(a._info) {
215 }
216 template<class View, bool p, bool f>
217 forceinline void
218 Action::Recorder<View,p,f>::Idx::propagate(void) {
219 _info |= 1U;
220 }
221 template<class View, bool p, bool f>
222 forceinline void
223 Action::Recorder<View,p,f>::Idx::fail(void) {
224 _info |= 2U;
225 }
226 template<class View, bool p, bool f>
227 forceinline bool
228 Action::Recorder<View,p,f>::Idx::propagated(void) const {
229 return (_info & 1U) != 0;
230 }
231 template<class View, bool p, bool f>
232 forceinline bool
233 Action::Recorder<View,p,f>::Idx::failed(void) const {
234 return (_info & 2U) != 0;
235 }
236 template<class View, bool p, bool f>
237 forceinline void
238 Action::Recorder<View,p,f>::Idx::clear(void) {
239 _info &= ~3U;
240 }
241 template<class View, bool p, bool f>
242 forceinline int
243 Action::Recorder<View,p,f>::Idx::idx(void) const {
244 return static_cast<int>(_info >> 2);
245 }
246
247
248 /*
249 * Posting of action recorder propagator
250 *
251 */
252 template<class View, bool p, bool f>
253 forceinline
254 Action::Recorder<View,p,f>::Recorder(Home home, ViewArray<View>& x,
255 Action& a0)
256 : NaryPropagator<View,PC_GEN_NONE>(home,x), a(a0), c(home) {
257 home.notice(*this,AP_DISPOSE);
258 for (int i=0; i<x.size(); i++)
259 if (!x[i].assigned())
260 x[i].subscribe(home,*new (home) Idx(home,*this,c,i), true);
261 }
262
263 template<class View, bool p, bool f>
264 forceinline ExecStatus
265 Action::Recorder<View,p,f>::post(Home home, ViewArray<View>& x, Action& a) {
266 (void) new (home) Recorder<View,p,f>(home,x,a);
267 return ES_OK;
268 }
269
270
271 /*
272 * Action value storage
273 *
274 */
275
276 template<class View>
277 forceinline
278 Action::Storage::Storage(Home home, ViewArray<View>& x, double d,
279 typename
280 BranchTraits<typename View::VarType>::Merit bm)
281 : n(x.size()), invd(1.0 / d), a(heap.alloc<double>(x.size())) {
282 if (bm)
283 for (int i=0; i<n; i++) {
284 typename View::VarType xi(x[i].varimp());
285 a[i] = bm(home,xi,i);
286 }
287 else
288 for (int i=0; i<n; i++)
289 a[i] = 1.0;
290 }
291 forceinline void
292 Action::Storage::update(int i) {
293 /*
294 * The trick to inverse decay is from: An Extensible SAT-solver,
295 * Niklas Eén, Niklas Sörensson, SAT 2003.
296 */
297 assert((i >= 0) && (i < n));
298 a[i] = invd * (a[i] + 1.0);
299 if (a[i] > Kernel::Config::rescale_limit)
300 for (int j=0; j<n; j++)
301 a[j] *= Kernel::Config::rescale;
302 }
303
304
305 /*
306 * Action
307 *
308 */
309
310 forceinline Action::Storage&
311 Action::object(void) const {
312 return static_cast<Action::Storage&>(*SharedHandle::object());
313 }
314
315 forceinline void
316 Action::object(Action::Storage& o) {
317 SharedHandle::object(&o);
318 }
319
320 forceinline void
321 Action::update(int i) {
322 object().update(i);
323 }
324 forceinline double
325 Action::operator [](int i) const {
326 assert((i >= 0) && (i < object().n));
327 return object().a[i];
328 }
329 forceinline int
330 Action::size(void) const {
331 return object().n;
332 }
333 forceinline void
334 Action::acquire(void) {
335 object().m.acquire();
336 }
337 forceinline void
338 Action::release(void) {
339 object().m.release();
340 }
341
342
343 forceinline
344 Action::Action(void) {}
345
346 template<class View>
347 forceinline
348 Action::Action(Home home, ViewArray<View>& x, double d,
349 bool p, bool f,
350 typename BranchTraits<typename View::VarType>::Merit bm) {
351 assert(!*this);
352 if (!p && !f)
353 return;
354 object(*new Storage(home,x,d,bm));
355 if (p && f)
356 (void) Recorder<View,true,true>::post(home,x,*this);
357 else if (p && !f)
358 (void) Recorder<View,true,false>::post(home,x,*this);
359 else if (!p && f)
360 (void) Recorder<View,false,true>::post(home,x,*this);
361 }
362 template<class View>
363 forceinline void
364 Action::init(Home home, ViewArray<View>& x, double d,
365 bool p, bool f,
366 typename BranchTraits<typename View::VarType>::Merit bm) {
367 assert(!*this);
368 if (!p && !f)
369 return;
370 object(*new Storage(home,x,d,bm));
371 if (p && f)
372 (void) Recorder<View,true,true>::post(home,x,*this);
373 else if (p && !f)
374 (void) Recorder<View,true,false>::post(home,x,*this);
375 else if (!p && f)
376 (void) Recorder<View,false,true>::post(home,x,*this);
377 }
378
379 template<class Char, class Traits>
380 std::basic_ostream<Char,Traits>&
381 operator <<(std::basic_ostream<Char,Traits>& os,
382 const Action& a) {
383 std::basic_ostringstream<Char,Traits> s;
384 s.copyfmt(os); s.width(0);
385 s << '{';
386 if (a.size() > 0) {
387 s << a[0];
388 for (int i=1; i<a.size(); i++)
389 s << ", " << a[i];
390 }
391 s << '}';
392 return os << s.str();
393 }
394
395
396 /*
397 * Propagation for action recorder
398 *
399 */
400 template<class View, bool p, bool f>
401 forceinline
402 Action::Recorder<View,p,f>::Recorder(Space& home, Recorder<View,p,f>& r)
403 : NaryPropagator<View,PC_GEN_NONE>(home,r), a(r.a) {
404 c.update(home, r.c);
405 }
406
407 template<class View, bool p, bool f>
408 Propagator*
409 Action::Recorder<View,p,f>::copy(Space& home) {
410 return new (home) Recorder<View,p,f>(home, *this);
411 }
412
413 template<class View, bool p, bool f>
414 inline size_t
415 Action::Recorder<View,p,f>::dispose(Space& home) {
416 // Delete access to action information
417 home.ignore(*this,AP_DISPOSE);
418 a.~Action();
419 // Cancel remaining advisors
420 for (Advisors<Idx> as(c); as(); ++as)
421 x[as.advisor().idx()].cancel(home,as.advisor(),true);
422 c.dispose(home);
423 (void) NaryPropagator<View,PC_GEN_NONE>::dispose(home);
424 return sizeof(*this);
425 }
426
427 template<class View, bool p, bool f>
428 PropCost
429 Action::Recorder<View,p,f>::cost(const Space&, const ModEventDelta&) const {
430 return PropCost::record();
431 }
432
433 template<class View, bool p, bool f>
434 void
435 Action::Recorder<View,p,f>::reschedule(Space& home) {
436 View::schedule(home,*this,ME_GEN_ASSIGNED);
437 }
438
439 template<class View, bool p, bool f>
440 ExecStatus
441 Action::Recorder<View,p,f>::advise(Space& home, Advisor& _a, const Delta&) {
442 Idx& a = static_cast<Idx&>(_a);
443 if (p) {
444 a.propagate();
445 return ES_NOFIX;
446 } else {
447 return x[a.idx()].assigned() ? home.ES_FIX_DISPOSE(c,a) : ES_FIX;
448 }
449 }
450
451 template<class View, bool p, bool f>
452 void
453 Action::Recorder<View,p,f>::advise(Space&, Advisor& _a) {
454 Idx& a = static_cast<Idx&>(_a);
455 if (f)
456 a.fail();
457 }
458
459 template<class View, bool p, bool f>
460 ExecStatus
461 Action::Recorder<View,p,f>::propagate(Space& home, const ModEventDelta&) {
462 // Lock action information
463 a.acquire();
464 for (Advisors<Idx> as(c); as(); ++as) {
465 int i = as.advisor().idx();
466 if (p && as.advisor().propagated()) {
467 as.advisor().clear();
468 a.update(i);
469 if (x[i].assigned())
470 as.advisor().dispose(home,c);
471 }
472 if (f && as.advisor().failed()) {
473 as.advisor().clear();
474 a.update(i);
475 if (x[i].assigned())
476 as.advisor().dispose(home,c);
477 }
478 }
479 a.release();
480 return c.empty() ? home.ES_SUBSUMED(*this) : ES_FIX;
481 }
482
483
484}
485
486// STATISTICS: kernel-branch