File: extensional.hh

package info (click to toggle)
gecode-snapshot 6.2.0%2Bgit20240207-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 35,308 kB
  • sloc: cpp: 475,516; perl: 2,077; makefile: 1,816; sh: 198
file content (686 lines) | stat: -rwxr-xr-x 23,941 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
 *  Main authors:
 *     Linnea Ingmar <linnea.ingmar@hotmail.com>
 *     Mikael Lagerkvist <lagerkvist@gecode.org>
 *     Christian Schulte <schulte@gecode.org>
 *
 *  Copyright:
 *     Linnea Ingmar, 2017
 *     Mikael Lagerkvist, 2007
 *     Christian Schulte, 2004
 *
 *  This file is part of Gecode, the generic constraint
 *  development environment:
 *     http://www.gecode.org
 *
 *  Permission is hereby granted, free of charge, to any person obtaining
 *  a copy of this software and associated documentation files (the
 *  "Software"), to deal in the Software without restriction, including
 *  without limitation the rights to use, copy, modify, merge, publish,
 *  distribute, sublicense, and/or sell copies of the Software, and to
 *  permit persons to whom the Software is furnished to do so, subject to
 *  the following conditions:
 *
 *  The above copyright notice and this permission notice shall be
 *  included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#ifndef GECODE_INT_EXTENSIONAL_HH
#define GECODE_INT_EXTENSIONAL_HH

#include <gecode/int.hh>

#include <gecode/int/rel.hh>

/**
 * \namespace Gecode::Int::Extensional
 * \brief %Extensional propagators
 */

namespace Gecode { namespace Int { namespace Extensional {

  /**
   * \brief Domain consistent layered graph (regular) propagator
   *
   * The algorithm for the regular propagator is based on:
   *   Gilles Pesant, A Regular Language Membership Constraint
   *   for Finite Sequences of Variables, CP 2004.
   *   Pages 482-495, LNCS 3258, Springer-Verlag, 2004.
   *
   * The propagator is not capable of dealing with multiple occurrences
   * of the same view.
   *
   * Requires \code #include <gecode/int/extensional.hh> \endcode
   * \ingroup FuncIntProp
   */
  template<class View, class Val, class Degree, class StateIdx>
  class LayeredGraph : public Propagator {
  protected:
    /// States are described by number of incoming and outgoing edges
    class State {
    public:
      Degree i_deg; ///< The in-degree (number of incoming edges)
      Degree o_deg; ///< The out-degree (number of outgoing edges)
      /// Initialize with zeroes
      void init(void);
    };
    /// %Edge defined by in-state and out-state
    class Edge {
    public:
      StateIdx i_state; ///< Number of in-state
      StateIdx o_state; ///< Number of out-state
    };
    /// %Support information for a value
    class Support {
    public:
      Val val; ///< Supported value
      Degree n_edges; ///< Number of supporting edges
      Edge* edges; ///< Supporting edges in layered graph
    };
    /// Type for support size
    typedef typename Gecode::Support::IntTypeTraits<Val>::utype ValSize;
    /// %Layer for a view in the layered graph
    class Layer {
    public:
      View x; ///< Integer view
      StateIdx n_states; ///< Number of states used by outgoing edges
      ValSize size; ///< Number of supported values
      State* states; ///< States used by outgoing edges
      Support* support; ///< Supported values
    };
    /// Iterator for telling variable domains by scanning support
    class LayerValues {
    private:
      const Support* s1; ///< Current support
      const Support* s2; ///< End of support
    public:
      /// Default constructor
      LayerValues(void);
      /// Initialize for support of layer \a l
      LayerValues(const Layer& l);
      /// Initialize for support of layer \a l
      void init(const Layer& l);
      /// Test whether more values supported
      bool operator ()(void) const;
      /// Move to next supported value
      void operator ++(void);
      /// Return supported value
      int val(void) const;
    };
    /// %Advisors for views (by position in array)
    class Index : public Advisor {
    public:
      /// The position of the view in the view array
      int i;
      /// Create index advisor
      Index(Space& home, Propagator& p, Council<Index>& c, int i);
      /// Clone index advisor \a a
      Index(Space& home, Index& a);
    };
    /// Range approximation of which positions have changed
    class IndexRange {
    private:
      int _fst; ///< First index
      int _lst; ///< Last index
    public:
      /// Initialize range as empty
      IndexRange(void);
      /// Reset range to be empty
      void reset(void);
      /// Add index \a i to range
      void add(int i);
      /// Add index range \a ir to range
      void add(const IndexRange& ir);
      /// Shift index range by \a n elements to the left
      void lshift(int n);
      /// Test whether range is empty
      bool empty(void) const;
      /// Return first position
      int fst(void) const;
      /// Return last position
      int lst(void) const;
    };
    /// The advisor council
    Council<Index> c;
    /// Number of layers (and views)
    int n;
    /// The layers of the graph
    Layer* layers;
    /// Maximal number of states per layer
    StateIdx max_states;
    /// Total number of states
    unsigned int n_states;
    /// Total number of edges
    unsigned int n_edges;
    /// Index range with in-degree modifications
    IndexRange i_ch;
    /// Index range with out-degree modifications
    IndexRange o_ch;
    /// Index range for any change (for compression)
    IndexRange a_ch;
    /// Return in state for layer \a i and state index \a is
    State& i_state(int i, StateIdx is);
    /// Return in state for layer \a i and in state of edge \a e
    State& i_state(int i, const Edge& e);
    /// Decrement out degree for in state of edge \a e for layer \a i
    bool i_dec(int i, const Edge& e);
    /// Return out state for layer \a i and state index \a os
    State& o_state(int i, StateIdx os);
    /// Return state for layer \a i and out state of edge \a e
    State& o_state(int i, const Edge& e);
    /// Decrement in degree for out state of edge \a e for layer \a i
    bool o_dec(int i, const Edge& e);
    /// Perform consistency check on data structures
    void audit(void);
    /// Initialize layered graph
    template<class Var>
    ExecStatus initialize(Space& home,
                          const VarArgArray<Var>& x, const DFA& dfa);
    /// Constructor for cloning \a p
    LayeredGraph(Space& home, LayeredGraph<View,Val,Degree,StateIdx>& p);
  public:
    /// Constructor for posting
    template<class Var>
    LayeredGraph(Home home,
                 const VarArgArray<Var>& x, const DFA& dfa);
    /// Copy propagator during cloning
    virtual Actor* copy(Space& home);
    /// Cost function (defined as high linear)
    virtual PropCost cost(const Space& home, const ModEventDelta& med) const;
    /// Schedule function
    virtual void reschedule(Space& home);
    /// Give advice to propagator
    virtual ExecStatus advise(Space& home, Advisor& a, const Delta& d);
    /// Perform propagation
    virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
    /// Delete propagator and return its size
    virtual size_t dispose(Space& home);
    /// Post propagator on views \a x and DFA \a dfa
    template<class Var>
    static ExecStatus post(Home home,
                           const VarArgArray<Var>& x, const DFA& dfa);
  };

  /// Select small types for the layered graph propagator
  template<class Var>
  ExecStatus post_lgp(Home home,
                      const VarArgArray<Var>& x, const DFA& dfa);

}}}

#include <gecode/int/extensional/layered-graph.hpp>

namespace Gecode { namespace Int { namespace Extensional {

  /// Import type
  typedef Gecode::Support::BitSetData BitSetData;

  /*
   * Forward declarations
   */
  template<unsigned int size> class TinyBitSet;

  /// Bit-set
  template<class IndexType>
  class BitSet {
    template<class> friend class BitSet;
    template<unsigned int> friend class TinyBitSet;
  protected:
    /// Limit
    IndexType _limit;
    /// Indices
    IndexType* _index;
    /// Words
    BitSetData* _bits;
    /// Replace the \a i th word with \a w, decrease \a limit if \a w is zero
    void replace_and_decrease(IndexType i, BitSetData w);
  public:
    /// Initialize bit set for a number of words \a n
    BitSet(Space& home, unsigned int n);
    /// Initialize during cloning
    template<class OldIndexType>
    BitSet(Space& home, const BitSet<OldIndexType>& bs);
    /// Initialize during cloning (unused)
    BitSet(Space& home, const TinyBitSet<1U>& tbs);
    /// Initialize during cloning (unused)
    BitSet(Space& home, const TinyBitSet<2U>& tbs);
    /// Initialize during cloning (unused)
    BitSet(Space& home, const TinyBitSet<3U>& tbs);
    /// Initialize during cloning (unused)
    BitSet(Space& home, const TinyBitSet<4U>& tbs);
    /// Get the limit
    unsigned int limit(void) const;
    /// Check whether the set is empty
    bool empty(void) const;
    /// Make the set empty
    void flush(void);
    /// Return the highest active index
    unsigned int width(void) const;
    /// Clear the first \a limit words in \a mask
    void clear_mask(BitSetData* mask) const;
    /// Add \b to \a mask
    void add_to_mask(const BitSetData* b, BitSetData* mask) const;
    /// Intersect with \a mask, sparse mask if \a sparse is true
    template<bool sparse>
    void intersect_with_mask(const BitSetData* mask);
    /// Intersect with the "or" of \a and \a b
    void intersect_with_masks(const BitSetData* a, const BitSetData* b);
    /// Check if \a has a non-empty intersection with the set
    bool intersects(const BitSetData* b) const;
    /// Perform "nand" with \a b
    void nand_with_mask(const BitSetData* b);
    /// Return the number of ones
    unsigned long long int ones(void) const;
    /// Return the number of ones after intersection with \a b
    unsigned long long int ones(const BitSetData* b) const;
    /// Return an upper bound on the number of bits
    unsigned long long int bits(void) const;
    /// Return the number of required bit set words
    unsigned int words(void) const;
    /// Return the number of required bit set words
    unsigned int size(void) const;
  };

}}}

#include <gecode/int/extensional/bit-set.hpp>

namespace Gecode { namespace Int { namespace Extensional {

  /// Tiny bit-set
  template<unsigned int _size>
  class TinyBitSet {
    template<unsigned int> friend class TinyBitSet;
  protected:
    /// Words
    BitSetData _bits[_size];
  public:
    /// Initialize sparse bit set for a number of words \a n
    TinyBitSet(Space& home, unsigned int n);
    /// Initialize during cloning
    template<unsigned int largersize>
    TinyBitSet(Space& home, const TinyBitSet<largersize>& tbs);
    /// Initialize during cloning
    template<class IndexType>
    TinyBitSet(Space& home, const BitSet<IndexType>& bs);
    /// Get the limit
    int limit(void) const;
    /// Check whether the set is empty
    bool empty(void) const;
    /// Make the set empty
    void flush(void);
    /// Return the highest active index
    unsigned int width(void) const;
    /// Clear the first \a limit words in \a mask
    void clear_mask(BitSetData* mask);
    /// Add \b to \a mask
    void add_to_mask(const BitSetData* b, BitSetData* mask) const;
    /// Intersect with \a mask, sparse mask if \a sparse is true
    template<bool sparse>
    void intersect_with_mask(const BitSetData* mask);
    /// Intersect with the "or" of \a and \a b
    void intersect_with_masks(const BitSetData* a, const BitSetData* b);
    /// Check if \a has a non-empty intersection with the set
    bool intersects(const BitSetData* b);
    /// Perform "nand" with \a b
    void nand_with_mask(const BitSetData* b);
    /// Perform "nand" with and the "or" of \a a and \a b
    void nand_with_masks(const BitSetData* a, const BitSetData* b);
    /// Return the number of ones
    unsigned long long int ones(void) const;
    /// Return the number of ones after intersection with \a b
    unsigned long long int ones(const BitSetData* b) const;
    /// Return an upper bound on the number of bits
    unsigned long long int bits(void) const;
    /// Return the number of required bit set words
    unsigned int words(void) const;
    /// Return the total number of words
    unsigned int size(void) const;
  };
      
}}}

#include <gecode/int/extensional/tiny-bit-set.hpp>

namespace Gecode { namespace Int { namespace Extensional {

  /// Tuple type
  typedef TupleSet::Tuple Tuple;

  /// Base class for compact table propagator
  template<class View, bool pos>
  class Compact : public Propagator {
  protected:
    /// Range type for supports
    typedef TupleSet::Range Range;
    /// Advisor for updating current table
    class CTAdvisor : public ViewAdvisor<View> {
    public:
      using ViewAdvisor<View>::view;
    protected:
      /// First range of support data structure
      const Range* _fst;
      /// Last range of support data structure
      const Range* _lst;
    public:
      /// \name Constructors
      //@{
      /// Initialise from parameters
      CTAdvisor(Space& home, Propagator& p, Council<CTAdvisor>& c,
                const TupleSet& ts, View x0, int i);
      /// Clone advisor \a a
      CTAdvisor(Space& home, CTAdvisor& a);
      //@}
      /// Adjust supports
      void adjust(void);
      /// Return first range of support data structure
      const Range* fst(void) const;
      /// Return lasst range of support data structure
      const Range* lst(void) const;
      /// Dispose advisor
      void dispose(Space& home, Council<CTAdvisor>& c);
    };
    //@}
    /// \name Support iterators
    //@{
    /// Iterator over valid supports
    class ValidSupports {
    protected:
      /// Number of words
      const unsigned int n_words;
      /// Maximal value
      int max;
      /// Range iterator
      ViewRanges<View> xr;
      /// Support iterator
      const Range* sr;
      /// The last range
      const Range* lst;
      /// The value
      int n;
      /// The value's support
      const BitSetData* s;
      /// Find a new value (only for negative case)
      void find(void);
    public:
      /// Initialize from initialized propagator
      ValidSupports(const Compact<View,pos>& p, CTAdvisor& a);
      /// Initialize during initialization
      ValidSupports(const TupleSet& ts, int i, View x);
      /// Move to next supports
      void operator ++(void);
      /// Whether there are still supports left
      bool operator ()(void) const;
      /// Return supports
      const BitSetData* supports(void) const;
      /// Return supported value
      int val(void) const;
    };
    /// Iterator over lost supports
    class LostSupports {
    protected:
      /// Number of words
      const unsigned int n_words;
      /// Range information
      const Range* r;
      /// Last range
      const Range* lst;
      /// Low value
      int l;
      /// High value
      int h;
      /// The lost value's support
      const BitSetData* s;
    public:
      /// Initialize iterator for values between \a l and \a h
      LostSupports(const Compact<View,pos>& p, CTAdvisor& a,
                   int l, int h);
      /// Move iterator to next value
      void operator ++(void);
      /// Whether iterator is done
      bool operator ()(void) const;
      /// Provide access to corresponding supports
      const BitSetData* supports(void) const;
    };
    //@}
    /// \name Testing the number of unassigned variables
    //@{
    /// Whether all variables are assigned
    bool all(void) const;
    /// Whether at most one variable is unassigned
    bool atmostone(void) const;
    //@}
  protected:
    /// Number of words in supports
    const unsigned int n_words;
    /// The tuple set
    TupleSet ts;
    /// The advisor council
    Council<CTAdvisor> c;
    /// Constructor for cloning \a p
    Compact(Space& home, Compact& p);
    /// Constructor for posting
    Compact(Home home, const TupleSet& ts);
    /// Setup the actual table
    template<class Table>
    void setup(Space& home, Table& table, ViewArray<View>& x);
    /// Check whether the table covers the whole Cartedion product
    template<class Table>
    bool full(const Table& table) const;
    /// Find range for \a n
    const Range* range(CTAdvisor& a, int n);
    /// Return supports for value \a n
    const BitSetData* supports(CTAdvisor& a, int n);
  public:
    /// Cost function
    virtual PropCost cost(const Space& home, const ModEventDelta& med) const;
    /// Delete propagator and return its size
    size_t dispose(Space& home);
  };

  /**
   * \brief Domain consistent positive extensional propagator
   *
   * This propagator implements the compact-table propagation
   * algorithm based on:
   *   J. Demeulenaere et. al., Compact-Table: Efficiently
   *   filtering table constraints with reversible sparse
   *   bit-sets, CP 2016.
   *
   * Requires \code #include <gecode/int/extensional.hh> \endcode
   * \ingroup FuncIntProp
   */
  template<class View, class Table>
  class PosCompact : public Compact<View,true> {
  public:
    typedef typename Compact<View,true>::ValidSupports ValidSupports;
    typedef typename Compact<View,true>::Range Range;
    typedef typename Compact<View,true>::CTAdvisor CTAdvisor;
    typedef typename Compact<View,true>::LostSupports LostSupports;

    using Compact<View,true>::setup;
    using Compact<View,true>::supports;
    using Compact<View,true>::all;
    using Compact<View,true>::atmostone;
    using Compact<View,true>::c;
    using Compact<View,true>::ts;

    /// \name Status management
    //@{ 
    /// Type of status
    enum StatusType {
      SINGLE      = 0, ///< A single view has been touched
      MULTIPLE    = 1, ///< Multiple view have been touched
      NONE        = 2, ///< No view has been touched
      PROPAGATING = 3  ///< The propagator is currently running
    };
    /// Status management
    class Status {
    protected:
      /// A tagged pointer for storing the status
      ptrdiff_t s;
    public:
      /// Initialize with type \a t (either NONE or SEVERAL)
      Status(StatusType t);
      /// Copy constructor
      Status(const Status& s);
      /// Return status type
      StatusType type(void) const;
      /// Check whether status is single and equal to \a a
      bool single(CTAdvisor& a) const;
      /// Set status to SINGLE or MULTIPLE depending on \a a
      void touched(CTAdvisor& a);
      /// Set status to NONE
      void none(void);
      /// Set status to PROPAGATING
      void propagating(void);
    };
    /// Propagator status
    Status status;
    /// Current table
    Table table;
    /// Check whether the table is empty
    bool empty(void) const;
    /// Constructor for cloning \a p
    template<class TableProp>
    PosCompact(Space& home, TableProp& p);
    /// Constructor for posting
    PosCompact(Home home, ViewArray<View>& x, const TupleSet& ts);
  public:
    /// Schedule function
    virtual void reschedule(Space& home);
    /// Perform propagation
    virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
    /// Copy propagator during cloning
    virtual Actor* copy(Space& home);
    /// Post propagator for views \a x and table \a t
    static ExecStatus post(Home home, ViewArray<View>& x, const TupleSet& ts);
    /// Delete propagator and return its size
    size_t dispose(Space& home);
    /// Give advice to propagator
    virtual ExecStatus advise(Space& home, Advisor& a, const Delta& d);
  };

  /// Post function for positive compact table propagator
  template<class View>
  ExecStatus postposcompact(Home home, ViewArray<View>& x, const TupleSet& ts);

  /**
   * \brief Domain consistent negative extensional propagator
   *
   * This propagator implements the compact-table propagation
   * algorithm based on:
   *   J. Demeulenaere et. al., Compact-Table: Efficiently
   *   filtering table constraints with reversible sparse
   *   bit-sets, CP 2016.
   * and (negative tables) on:
   *   H. Verhaeghe et al., Extending Compact-Table to
   *   Negative and Short Tables. AAAI 2017.
   *
   * Requires \code #include <gecode/int/extensional.hh> \endcode
   * \ingroup FuncIntProp
   */
  template<class View, class Table>
  class NegCompact : public Compact<View,false> {
  public:
    typedef typename Compact<View,false>::ValidSupports ValidSupports;
    typedef typename Compact<View,false>::Range Range;
    typedef typename Compact<View,false>::CTAdvisor CTAdvisor;

    using Compact<View,false>::setup;
    using Compact<View,false>::full;
    using Compact<View,false>::supports;
    using Compact<View,false>::atmostone;
    using Compact<View,false>::c;
    using Compact<View,false>::ts;

    /// Current table
    Table table;
    /// Constructor for cloning \a p
    template<class TableProp>
    NegCompact(Space& home, TableProp& p);
    /// Constructor for posting
    NegCompact(Home home, ViewArray<View>& x, const TupleSet& ts);
  public:
    /// Schedule function
    virtual void reschedule(Space& home);
    /// Perform propagation
    virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
    /// Copy propagator during cloning
    virtual Actor* copy(Space& home);
    /// Post propagator for views \a x and table \a t
    static ExecStatus post(Home home, ViewArray<View>& x, const TupleSet& ts);
    /// Delete propagator and return its size
    size_t dispose(Space& home);
    /// Give advice to propagator
    virtual ExecStatus advise(Space& home, Advisor& a, const Delta& d);
  };

  /// Post function for compact table propagator
  template<class View>
  ExecStatus postnegcompact(Home home, ViewArray<View>& x, const TupleSet& ts);


  /// Domain consistent reified extensional propagator
  template<class View, class Table, class CtrlView, ReifyMode rm>
  class ReCompact : public Compact<View,false> {
  public:
    typedef typename Compact<View,false>::ValidSupports ValidSupports;
    typedef typename Compact<View,false>::Range Range;
    typedef typename Compact<View,false>::CTAdvisor CTAdvisor;

    using Compact<View,false>::setup;
    using Compact<View,false>::full;
    using Compact<View,false>::supports;
    using Compact<View,false>::c;
    using Compact<View,false>::ts;

    /// Current table
    Table table;
    /// Boolean control view
    CtrlView b;
    /// The views (for rewriting)
    ViewArray<View> y;
    /// Constructor for cloning \a p
    template<class TableProp>
    ReCompact(Space& home, TableProp& p);
    /// Constructor for posting
    ReCompact(Home home, ViewArray<View>& x, const TupleSet& ts, CtrlView b);
  public:
    /// Schedule function
    virtual void reschedule(Space& home);
    /// Perform propagation
    virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
    /// Copy propagator during cloning
    virtual Actor* copy(Space& home);
    /// Post propagator for views \a x and table \a t
    static ExecStatus post(Home home, ViewArray<View>& x, const TupleSet& ts,
                           CtrlView b);
    /// Delete propagator and return its size
    size_t dispose(Space& home);
    /// Give advice to propagator
    virtual ExecStatus advise(Space& home, Advisor& a, const Delta& d);
  };

  /// Post function for compact table propagator
  template<class View, class CtrlView, ReifyMode rm>
  ExecStatus postrecompact(Home home, ViewArray<View>& x, const TupleSet& ts,
                           CtrlView b);

}}}

#include <gecode/int/extensional/compact.hpp>

#endif

// STATISTICS: int-prop