this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Linnea Ingmar <linnea.ingmar@hotmail.com>
5 * Mikael Lagerkvist <lagerkvist@gecode.org>
6 * Christian Schulte <schulte@gecode.org>
7 *
8 * Copyright:
9 * Linnea Ingmar, 2017
10 * Mikael Lagerkvist, 2007
11 * Christian Schulte, 2004
12 *
13 * This file is part of Gecode, the generic constraint
14 * development environment:
15 * http://www.gecode.org
16 *
17 * Permission is hereby granted, free of charge, to any person obtaining
18 * a copy of this software and associated documentation files (the
19 * "Software"), to deal in the Software without restriction, including
20 * without limitation the rights to use, copy, modify, merge, publish,
21 * distribute, sublicense, and/or sell copies of the Software, and to
22 * permit persons to whom the Software is furnished to do so, subject to
23 * the following conditions:
24 *
25 * The above copyright notice and this permission notice shall be
26 * included in all copies or substantial portions of the Software.
27 *
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 *
36 */
37
38#ifndef GECODE_INT_EXTENSIONAL_HH
39#define GECODE_INT_EXTENSIONAL_HH
40
41#include <gecode/int.hh>
42
43#include <gecode/int/rel.hh>
44
45/**
46 * \namespace Gecode::Int::Extensional
47 * \brief %Extensional propagators
48 */
49
50namespace Gecode { namespace Int { namespace Extensional {
51
52 /**
53 * \brief Domain consistent layered graph (regular) propagator
54 *
55 * The algorithm for the regular propagator is based on:
56 * Gilles Pesant, A Regular Language Membership Constraint
57 * for Finite Sequences of Variables, CP 2004.
58 * Pages 482-495, LNCS 3258, Springer-Verlag, 2004.
59 *
60 * The propagator is not capable of dealing with multiple occurences
61 * of the same view.
62 *
63 * Requires \code #include <gecode/int/extensional.hh> \endcode
64 * \ingroup FuncIntProp
65 */
66 template<class View, class Val, class Degree, class StateIdx>
67 class LayeredGraph : public Propagator {
68 protected:
69 /// States are described by number of incoming and outgoing edges
70 class State {
71 public:
72 Degree i_deg; ///< The in-degree (number of incoming edges)
73 Degree o_deg; ///< The out-degree (number of outgoing edges)
74 /// Initialize with zeroes
75 void init(void);
76 };
77 /// %Edge defined by in-state and out-state
78 class Edge {
79 public:
80 StateIdx i_state; ///< Number of in-state
81 StateIdx o_state; ///< Number of out-state
82 };
83 /// %Support information for a value
84 class Support {
85 public:
86 Val val; ///< Supported value
87 Degree n_edges; ///< Number of supporting edges
88 Edge* edges; ///< Supporting edges in layered graph
89 };
90 /// Type for support size
91 typedef typename Gecode::Support::IntTypeTraits<Val>::utype ValSize;
92 /// %Layer for a view in the layered graph
93 class Layer {
94 public:
95 View x; ///< Integer view
96 StateIdx n_states; ///< Number of states used by outgoing edges
97 ValSize size; ///< Number of supported values
98 State* states; ///< States used by outgoing edges
99 Support* support; ///< Supported values
100 };
101 /// Iterator for telling variable domains by scanning support
102 class LayerValues {
103 private:
104 const Support* s1; ///< Current support
105 const Support* s2; ///< End of support
106 public:
107 /// Default constructor
108 LayerValues(void);
109 /// Initialize for support of layer \a l
110 LayerValues(const Layer& l);
111 /// Initialize for support of layer \a l
112 void init(const Layer& l);
113 /// Test whether more values supported
114 bool operator ()(void) const;
115 /// Move to next supported value
116 void operator ++(void);
117 /// Return supported value
118 int val(void) const;
119 };
120 /// %Advisors for views (by position in array)
121 class Index : public Advisor {
122 public:
123 /// The position of the view in the view array
124 int i;
125 /// Create index advisor
126 Index(Space& home, Propagator& p, Council<Index>& c, int i);
127 /// Clone index advisor \a a
128 Index(Space& home, Index& a);
129 };
130 /// Range approximation of which positions have changed
131 class IndexRange {
132 private:
133 int _fst; ///< First index
134 int _lst; ///< Last index
135 public:
136 /// Initialize range as empty
137 IndexRange(void);
138 /// Reset range to be empty
139 void reset(void);
140 /// Add index \a i to range
141 void add(int i);
142 /// Add index range \a ir to range
143 void add(const IndexRange& ir);
144 /// Shift index range by \a n elements to the left
145 void lshift(int n);
146 /// Test whether range is empty
147 bool empty(void) const;
148 /// Return first position
149 int fst(void) const;
150 /// Return last position
151 int lst(void) const;
152 };
153 /// The advisor council
154 Council<Index> c;
155 /// Number of layers (and views)
156 int n;
157 /// The layers of the graph
158 Layer* layers;
159 /// Maximal number of states per layer
160 StateIdx max_states;
161 /// Total number of states
162 unsigned int n_states;
163 /// Total number of edges
164 unsigned int n_edges;
165 /// Index range with in-degree modifications
166 IndexRange i_ch;
167 /// Index range with out-degree modifications
168 IndexRange o_ch;
169 /// Index range for any change (for compression)
170 IndexRange a_ch;
171 /// Return in state for layer \a i and state index \a is
172 State& i_state(int i, StateIdx is);
173 /// Return in state for layer \a i and in state of edge \a e
174 State& i_state(int i, const Edge& e);
175 /// Decrement out degree for in state of edge \a e for layer \a i
176 bool i_dec(int i, const Edge& e);
177 /// Return out state for layer \a i and state index \a os
178 State& o_state(int i, StateIdx os);
179 /// Return state for layer \a i and out state of edge \a e
180 State& o_state(int i, const Edge& e);
181 /// Decrement in degree for out state of edge \a e for layer \a i
182 bool o_dec(int i, const Edge& e);
183 /// Perform consistency check on data structures
184 void audit(void);
185 /// Initialize layered graph
186 template<class Var>
187 ExecStatus initialize(Space& home,
188 const VarArgArray<Var>& x, const DFA& dfa);
189 /// Constructor for cloning \a p
190 LayeredGraph(Space& home, LayeredGraph<View,Val,Degree,StateIdx>& p);
191 public:
192 /// Constructor for posting
193 template<class Var>
194 LayeredGraph(Home home,
195 const VarArgArray<Var>& x, const DFA& dfa);
196 /// Copy propagator during cloning
197 virtual Actor* copy(Space& home);
198 /// Cost function (defined as high linear)
199 virtual PropCost cost(const Space& home, const ModEventDelta& med) const;
200 /// Schedule function
201 virtual void reschedule(Space& home);
202 /// Give advice to propagator
203 virtual ExecStatus advise(Space& home, Advisor& a, const Delta& d);
204 /// Perform propagation
205 virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
206 /// Delete propagator and return its size
207 virtual size_t dispose(Space& home);
208 /// Post propagator on views \a x and DFA \a dfa
209 template<class Var>
210 static ExecStatus post(Home home,
211 const VarArgArray<Var>& x, const DFA& dfa);
212 };
213
214 /// Select small types for the layered graph propagator
215 template<class Var>
216 ExecStatus post_lgp(Home home,
217 const VarArgArray<Var>& x, const DFA& dfa);
218
219}}}
220
221#include <gecode/int/extensional/layered-graph.hpp>
222
223namespace Gecode { namespace Int { namespace Extensional {
224
225 /// Import type
226 typedef Gecode::Support::BitSetData BitSetData;
227
228 /*
229 * Forward declarations
230 */
231 template<unsigned int size> class TinyBitSet;
232
233 /// Bit-set
234 template<class IndexType>
235 class BitSet {
236 template<class> friend class BitSet;
237 template<unsigned int> friend class TinyBitSet;
238 protected:
239 /// Limit
240 IndexType _limit;
241 /// Indices
242 IndexType* _index;
243 /// Words
244 BitSetData* _bits;
245 /// Replace the \a i th word with \a w, decrease \a limit if \a w is zero
246 void replace_and_decrease(IndexType i, BitSetData w);
247 public:
248 /// Initialize bit set for a number of words \a n
249 BitSet(Space& home, unsigned int n);
250 /// Initialize during cloning
251 template<class OldIndexType>
252 BitSet(Space& home, const BitSet<OldIndexType>& bs);
253 /// Initialize during cloning (unused)
254 BitSet(Space& home, const TinyBitSet<1U>& tbs);
255 /// Initialize during cloning (unused)
256 BitSet(Space& home, const TinyBitSet<2U>& tbs);
257 /// Initialize during cloning (unused)
258 BitSet(Space& home, const TinyBitSet<3U>& tbs);
259 /// Initialize during cloning (unused)
260 BitSet(Space& home, const TinyBitSet<4U>& tbs);
261 /// Get the limit
262 unsigned int limit(void) const;
263 /// Check whether the set is empty
264 bool empty(void) const;
265 /// Make the set empty
266 void flush(void);
267 /// Return the highest active index
268 unsigned int width(void) const;
269 /// Clear the first \a limit words in \a mask
270 void clear_mask(BitSetData* mask) const;
271 /// Add \b to \a mask
272 void add_to_mask(const BitSetData* b, BitSetData* mask) const;
273 /// Intersect with \a mask, sparse mask if \a sparse is true
274 template<bool sparse>
275 void intersect_with_mask(const BitSetData* mask);
276 /// Intersect with the "or" of \a and \a b
277 void intersect_with_masks(const BitSetData* a, const BitSetData* b);
278 /// Check if \a has a non-empty intersection with the set
279 bool intersects(const BitSetData* b) const;
280 /// Perform "nand" with \a b
281 void nand_with_mask(const BitSetData* b);
282 /// Return the number of ones
283 unsigned long long int ones(void) const;
284 /// Return the number of ones after intersection with \a b
285 unsigned long long int ones(const BitSetData* b) const;
286 /// Return an upper bound on the number of bits
287 unsigned long long int bits(void) const;
288 /// Return the number of required bit set words
289 unsigned int words(void) const;
290 /// Return the number of required bit set words
291 unsigned int size(void) const;
292 };
293
294}}}
295
296#include <gecode/int/extensional/bit-set.hpp>
297
298namespace Gecode { namespace Int { namespace Extensional {
299
300 /// Tiny bit-set
301 template<unsigned int _size>
302 class TinyBitSet {
303 template<unsigned int> friend class TinyBitSet;
304 protected:
305 /// Words
306 BitSetData _bits[_size];
307 public:
308 /// Initialize sparse bit set for a number of words \a n
309 TinyBitSet(Space& home, unsigned int n);
310 /// Initialize during cloning
311 template<unsigned int largersize>
312 TinyBitSet(Space& home, const TinyBitSet<largersize>& tbs);
313 /// Initialize during cloning
314 template<class IndexType>
315 TinyBitSet(Space& home, const BitSet<IndexType>& bs);
316 /// Get the limit
317 int limit(void) const;
318 /// Check whether the set is empty
319 bool empty(void) const;
320 /// Make the set empty
321 void flush(void);
322 /// Return the highest active index
323 unsigned int width(void) const;
324 /// Clear the first \a limit words in \a mask
325 void clear_mask(BitSetData* mask);
326 /// Add \b to \a mask
327 void add_to_mask(const BitSetData* b, BitSetData* mask) const;
328 /// Intersect with \a mask, sparse mask if \a sparse is true
329 template<bool sparse>
330 void intersect_with_mask(const BitSetData* mask);
331 /// Intersect with the "or" of \a and \a b
332 void intersect_with_masks(const BitSetData* a, const BitSetData* b);
333 /// Check if \a has a non-empty intersection with the set
334 bool intersects(const BitSetData* b);
335 /// Perform "nand" with \a b
336 void nand_with_mask(const BitSetData* b);
337 /// Perform "nand" with and the "or" of \a a and \a b
338 void nand_with_masks(const BitSetData* a, const BitSetData* b);
339 /// Return the number of ones
340 unsigned long long int ones(void) const;
341 /// Return the number of ones after intersection with \a b
342 unsigned long long int ones(const BitSetData* b) const;
343 /// Return an upper bound on the number of bits
344 unsigned long long int bits(void) const;
345 /// Return the number of required bit set words
346 unsigned int words(void) const;
347 /// Return the total number of words
348 unsigned int size(void) const;
349 };
350
351}}}
352
353#include <gecode/int/extensional/tiny-bit-set.hpp>
354
355namespace Gecode { namespace Int { namespace Extensional {
356
357 /// Tuple type
358 typedef TupleSet::Tuple Tuple;
359
360 /// Base class for compact table propagator
361 template<class View, bool pos>
362 class Compact : public Propagator {
363 protected:
364 /// Range type for supports
365 typedef TupleSet::Range Range;
366 /// Advisor for updating current table
367 class CTAdvisor : public ViewAdvisor<View> {
368 public:
369 using ViewAdvisor<View>::view;
370 protected:
371 /// First range of support data structure
372 const Range* _fst;
373 /// Last range of support data structure
374 const Range* _lst;
375 public:
376 /// \name Constructors
377 //@{
378 /// Initialise from parameters
379 CTAdvisor(Space& home, Propagator& p, Council<CTAdvisor>& c,
380 const TupleSet& ts, View x0, int i);
381 /// Clone advisor \a a
382 CTAdvisor(Space& home, CTAdvisor& a);
383 //@}
384 /// Adjust supports
385 void adjust(void);
386 /// Return first range of support data structure
387 const Range* fst(void) const;
388 /// Return lasst range of support data structure
389 const Range* lst(void) const;
390 /// Dispose advisor
391 void dispose(Space& home, Council<CTAdvisor>& c);
392 };
393 //@}
394 /// \name Support iterators
395 //@{
396 /// Iterator over valid supports
397 class ValidSupports {
398 protected:
399 /// Number of words
400 const unsigned int n_words;
401 /// Maximal value
402 int max;
403 /// Range iterator
404 ViewRanges<View> xr;
405 /// Support iterator
406 const Range* sr;
407 /// The last range
408 const Range* lst;
409 /// The value
410 int n;
411 /// The value's support
412 const BitSetData* s;
413 /// Find a new value (only for negative case)
414 void find(void);
415 public:
416 /// Initialize from initialized propagator
417 ValidSupports(const Compact<View,pos>& p, CTAdvisor& a);
418 /// Initialize during initialization
419 ValidSupports(const TupleSet& ts, int i, View x);
420 /// Move to next supports
421 void operator ++(void);
422 /// Whether there are still supports left
423 bool operator ()(void) const;
424 /// Return supports
425 const BitSetData* supports(void) const;
426 /// Return supported value
427 int val(void) const;
428 };
429 /// Iterator over lost supports
430 class LostSupports {
431 protected:
432 /// Number of words
433 const unsigned int n_words;
434 /// Range information
435 const Range* r;
436 /// Last range
437 const Range* lst;
438 /// Low value
439 int l;
440 /// High value
441 int h;
442 /// The lost value's support
443 const BitSetData* s;
444 public:
445 /// Initialize iterator for values between \a l and \a h
446 LostSupports(const Compact<View,pos>& p, CTAdvisor& a,
447 int l, int h);
448 /// Move iterator to next value
449 void operator ++(void);
450 /// Whether iterator is done
451 bool operator ()(void) const;
452 /// Provide access to corresponding supports
453 const BitSetData* supports(void) const;
454 };
455 //@}
456 /// \name Testing the number of unassigned variables
457 //@{
458 /// Whether all variables are assigned
459 bool all(void) const;
460 /// Whether at most one variable is unassigned
461 bool atmostone(void) const;
462 //@}
463 protected:
464 /// Number of words in supports
465 const unsigned int n_words;
466 /// The tuple set
467 TupleSet ts;
468 /// The advisor council
469 Council<CTAdvisor> c;
470 /// Constructor for cloning \a p
471 Compact(Space& home, Compact& p);
472 /// Constructor for posting
473 Compact(Home home, const TupleSet& ts);
474 /// Setup the actual table
475 template<class Table>
476 void setup(Space& home, Table& table, ViewArray<View>& x);
477 /// Check whether the table covers the whole Cartedion product
478 template<class Table>
479 bool full(const Table& table) const;
480 /// Find range for \a n
481 const Range* range(CTAdvisor& a, int n);
482 /// Return supports for value \a n
483 const BitSetData* supports(CTAdvisor& a, int n);
484 public:
485 /// Cost function
486 virtual PropCost cost(const Space& home, const ModEventDelta& med) const;
487 /// Delete propagator and return its size
488 size_t dispose(Space& home);
489 };
490
491 /**
492 * \brief Domain consistent positive extensional propagator
493 *
494 * This propagator implements the compact-table propagation
495 * algorithm based on:
496 * J. Demeulenaere et. al., Compact-Table: Efficiently
497 * filtering table constraints with reversible sparse
498 * bit-sets, CP 2016.
499 *
500 * Requires \code #include <gecode/int/extensional.hh> \endcode
501 * \ingroup FuncIntProp
502 */
503 template<class View, class Table>
504 class PosCompact : public Compact<View,true> {
505 public:
506 typedef typename Compact<View,true>::ValidSupports ValidSupports;
507 typedef typename Compact<View,true>::Range Range;
508 typedef typename Compact<View,true>::CTAdvisor CTAdvisor;
509 typedef typename Compact<View,true>::LostSupports LostSupports;
510
511 using Compact<View,true>::setup;
512 using Compact<View,true>::supports;
513 using Compact<View,true>::all;
514 using Compact<View,true>::atmostone;
515 using Compact<View,true>::c;
516 using Compact<View,true>::ts;
517
518 /// \name Status management
519 //@{
520 /// Type of status
521 enum StatusType {
522 SINGLE = 0, ///< A single view has been touched
523 MULTIPLE = 1, ///< Multiple view have been touched
524 NONE = 2, ///< No view has been touched
525 PROPAGATING = 3 ///< The propagator is currently running
526 };
527 /// Status management
528 class Status {
529 protected:
530 /// A tagged pointer for storing the status
531 ptrdiff_t s;
532 public:
533 /// Initialize with type \a t (either NONE or SEVERAL)
534 Status(StatusType t);
535 /// Copy constructor
536 Status(const Status& s);
537 /// Return status type
538 StatusType type(void) const;
539 /// Check whether status is single and equal to \a a
540 bool single(CTAdvisor& a) const;
541 /// Set status to SINGLE or MULTIPLE depending on \a a
542 void touched(CTAdvisor& a);
543 /// Set status to NONE
544 void none(void);
545 /// Set status to PROPAGATING
546 void propagating(void);
547 };
548 /// Propagator status
549 Status status;
550 /// Current table
551 Table table;
552 /// Check whether the table is empty
553 bool empty(void) const;
554 /// Constructor for cloning \a p
555 template<class TableProp>
556 PosCompact(Space& home, TableProp& p);
557 /// Constructor for posting
558 PosCompact(Home home, ViewArray<View>& x, const TupleSet& ts);
559 public:
560 /// Schedule function
561 virtual void reschedule(Space& home);
562 /// Perform propagation
563 virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
564 /// Copy propagator during cloning
565 virtual Actor* copy(Space& home);
566 /// Post propagator for views \a x and table \a t
567 static ExecStatus post(Home home, ViewArray<View>& x, const TupleSet& ts);
568 /// Delete propagator and return its size
569 size_t dispose(Space& home);
570 /// Give advice to propagator
571 virtual ExecStatus advise(Space& home, Advisor& a, const Delta& d);
572 };
573
574 /// Post function for positive compact table propagator
575 template<class View>
576 ExecStatus postposcompact(Home home, ViewArray<View>& x, const TupleSet& ts);
577
578 /**
579 * \brief Domain consistent negative extensional propagator
580 *
581 * This propagator implements the compact-table propagation
582 * algorithm based on:
583 * J. Demeulenaere et. al., Compact-Table: Efficiently
584 * filtering table constraints with reversible sparse
585 * bit-sets, CP 2016.
586 * and (negative tables) on:
587 * H. Verhaeghe et al., Extending Compact-Table to
588 * Negative and Short Tables. AAAI 2017.
589 *
590 * Requires \code #include <gecode/int/extensional.hh> \endcode
591 * \ingroup FuncIntProp
592 */
593 template<class View, class Table>
594 class NegCompact : public Compact<View,false> {
595 public:
596 typedef typename Compact<View,false>::ValidSupports ValidSupports;
597 typedef typename Compact<View,false>::Range Range;
598 typedef typename Compact<View,false>::CTAdvisor CTAdvisor;
599
600 using Compact<View,false>::setup;
601 using Compact<View,false>::full;
602 using Compact<View,false>::supports;
603 using Compact<View,false>::atmostone;
604 using Compact<View,false>::c;
605 using Compact<View,false>::ts;
606
607 /// Current table
608 Table table;
609 /// Constructor for cloning \a p
610 template<class TableProp>
611 NegCompact(Space& home, TableProp& p);
612 /// Constructor for posting
613 NegCompact(Home home, ViewArray<View>& x, const TupleSet& ts);
614 public:
615 /// Schedule function
616 virtual void reschedule(Space& home);
617 /// Perform propagation
618 virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
619 /// Copy propagator during cloning
620 virtual Actor* copy(Space& home);
621 /// Post propagator for views \a x and table \a t
622 static ExecStatus post(Home home, ViewArray<View>& x, const TupleSet& ts);
623 /// Delete propagator and return its size
624 size_t dispose(Space& home);
625 /// Give advice to propagator
626 virtual ExecStatus advise(Space& home, Advisor& a, const Delta& d);
627 };
628
629 /// Post function for compact table propagator
630 template<class View>
631 ExecStatus postnegcompact(Home home, ViewArray<View>& x, const TupleSet& ts);
632
633
634 /// Domain consistent reified extensional propagator
635 template<class View, class Table, class CtrlView, ReifyMode rm>
636 class ReCompact : public Compact<View,false> {
637 public:
638 typedef typename Compact<View,false>::ValidSupports ValidSupports;
639 typedef typename Compact<View,false>::Range Range;
640 typedef typename Compact<View,false>::CTAdvisor CTAdvisor;
641
642 using Compact<View,false>::setup;
643 using Compact<View,false>::full;
644 using Compact<View,false>::supports;
645 using Compact<View,false>::c;
646 using Compact<View,false>::ts;
647
648 /// Current table
649 Table table;
650 /// Boolean control view
651 CtrlView b;
652 /// The views (for rewriting)
653 ViewArray<View> y;
654 /// Constructor for cloning \a p
655 template<class TableProp>
656 ReCompact(Space& home, TableProp& p);
657 /// Constructor for posting
658 ReCompact(Home home, ViewArray<View>& x, const TupleSet& ts, CtrlView b);
659 public:
660 /// Schedule function
661 virtual void reschedule(Space& home);
662 /// Perform propagation
663 virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
664 /// Copy propagator during cloning
665 virtual Actor* copy(Space& home);
666 /// Post propagator for views \a x and table \a t
667 static ExecStatus post(Home home, ViewArray<View>& x, const TupleSet& ts,
668 CtrlView b);
669 /// Delete propagator and return its size
670 size_t dispose(Space& home);
671 /// Give advice to propagator
672 virtual ExecStatus advise(Space& home, Advisor& a, const Delta& d);
673 };
674
675 /// Post function for compact table propagator
676 template<class View, class CtrlView, ReifyMode rm>
677 ExecStatus postrecompact(Home home, ViewArray<View>& x, const TupleSet& ts,
678 CtrlView b);
679
680}}}
681
682#include <gecode/int/extensional/compact.hpp>
683
684#endif
685
686// STATISTICS: int-prop