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, 2002
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 namespace Gecode { namespace Int {
35 
36   /**
37    * \defgroup TaskPropRePat Reified propagator patterns
38    *
39    * \ingroup TaskActor
40    */
41 
42   //@{
43   /**
44    * \brief Reified unary propagator
45    *
46    * Stores single view of type \a View with propagation condition \a pc
47    * and a Boolean control view of type \a CtrlView.
48    *
49    * If the propagation condition \a pc has the value PC_GEN_NONE, no
50    * subscriptions are created for \a View.
51    *
52    */
53   template<class View, PropCond pc, class CtrlView>
54   class ReUnaryPropagator : public Propagator {
55   protected:
56     /// Single view
57     View x0;
58     /// Boolean control view
59     CtrlView b;
60     /// Constructor for cloning \a p
61     ReUnaryPropagator(Space& home, ReUnaryPropagator& p);
62     /// Constructor for rewriting \a p during cloning
63     ReUnaryPropagator(Space& home, Propagator& p,
64                       View x0, CtrlView b);
65     /// Constructor for creation
66     ReUnaryPropagator(Home home, View x0, CtrlView b);
67   public:
68     /// Cost function (defined as low unary)
69     virtual PropCost cost(const Space& home, const ModEventDelta& med) const;
70     /// Schedule function
71     virtual void reschedule(Space& home);
72     /// Delete propagator and return its size
73     virtual size_t dispose(Space& home);
74   };
75 
76   /**
77    * \brief Reified binary propagator
78    *
79    * Stores two views of type \a View with propagation condition \a pc
80    * and a Boolean control view of type \a CtrlView.
81    *
82    * If the propagation condition \a pc has the value PC_GEN_NONE, no
83    * subscriptions are created for \a View.
84    *
85    */
86   template<class View, PropCond pc, class CtrlView>
87   class ReBinaryPropagator : public Propagator {
88   protected:
89     /// Two views
90     View x0, x1;
91     /// Boolean control view
92     CtrlView b;
93     /// Constructor for cloning \a p
94     ReBinaryPropagator(Space& home, ReBinaryPropagator& p);
95     /// Constructor for rewriting \a p during cloning
96     ReBinaryPropagator(Space& home, Propagator& p,
97                        View x0, View x1, CtrlView b);
98     /// Constructor for creation
99     ReBinaryPropagator(Home home, View x0, View x1, CtrlView b);
100   public:
101     /// Cost function (defined as low binary)
102     virtual PropCost cost(const Space& home, const ModEventDelta& med) const;
103     /// Schedule function
104     virtual void reschedule(Space& home);
105     /// Delete propagator and return its size
106     virtual size_t dispose(Space& home);
107   };
108   //@}
109 
110 
111   /**
112    * \brief Reified mixed binary propagator
113    *
114    * Stores two views of type \a View0 and \a View1 with propagation
115    * conditions \a pc0 and \a pc1 and a Boolean control view of type
116    * \a CtrlView.
117    *
118    * If the propagation conditions \a pc0 or \a pc1 have the values
119    * PC_GEN_NONE, no subscriptions are created.
120    *
121    */
122   template<class View0, PropCond pc0, class View1, PropCond pc1,
123            class CtrlView>
124   class ReMixBinaryPropagator : public Propagator {
125   protected:
126     /// View of type \a View0
127     View0 x0;
128     /// View of type \a View1
129     View1 x1;
130     /// Boolean control view
131     CtrlView b;
132     /// Constructor for cloning \a p
133     ReMixBinaryPropagator(Space& home, ReMixBinaryPropagator& p);
134     /// Constructor for creation
135     ReMixBinaryPropagator(Home home, View0 x0, View1 x1, CtrlView b);
136     /// Constructor for rewriting \a p during cloning
137     ReMixBinaryPropagator(Space& home, Propagator& p,
138                           View0 x0, View1 x1, CtrlView b);
139   public:
140     /// Cost function (defined as low binary)
141     virtual PropCost cost(const Space& home, const ModEventDelta& med) const;
142     /// Schedule function
143     virtual void reschedule(Space& home);
144     /// Delete propagator and return its size
145     virtual size_t dispose(Space& home);
146   };
147 
148 
149   /*
150    * Reified unary propagators
151    *
152    */
153   template<class View, PropCond pc, class CtrlView>
ReUnaryPropagator(Home home,View y0,CtrlView b0)154   ReUnaryPropagator<View,pc,CtrlView>::ReUnaryPropagator
155   (Home home, View y0, CtrlView b0)
156     : Propagator(home), x0(y0), b(b0) {
157     if (pc != PC_GEN_NONE)
158       x0.subscribe(home,*this,pc);
159     b.subscribe(home,*this,Int::PC_INT_VAL);
160   }
161 
162   template<class View, PropCond pc, class CtrlView>
163   forceinline
ReUnaryPropagator(Space & home,ReUnaryPropagator<View,pc,CtrlView> & p)164   ReUnaryPropagator<View,pc,CtrlView>::ReUnaryPropagator
165   (Space& home, ReUnaryPropagator<View,pc,CtrlView>& p)
166     : Propagator(home,p) {
167     x0.update(home,p.x0);
168     b.update(home,p.b);
169   }
170 
171   template<class View, PropCond pc, class CtrlView>
172   forceinline
ReUnaryPropagator(Space & home,Propagator & p,View y0,CtrlView b0)173   ReUnaryPropagator<View,pc,CtrlView>::ReUnaryPropagator
174   (Space& home, Propagator& p, View y0, CtrlView b0)
175     : Propagator(home,p) {
176     x0.update(home,y0);
177     b.update(home,b0);
178   }
179 
180   template<class View, PropCond pc, class CtrlView>
181   PropCost
cost(const Space &,const ModEventDelta &) const182   ReUnaryPropagator<View,pc,CtrlView>::cost(const Space&, const ModEventDelta&) const {
183     return PropCost::unary(PropCost::LO);
184   }
185 
186   template<class View, PropCond pc, class CtrlView>
187   void
reschedule(Space & home)188   ReUnaryPropagator<View,pc,CtrlView>::reschedule(Space& home) {
189     if (pc != PC_GEN_NONE)
190       x0.reschedule(home,*this,pc);
191     b.reschedule(home,*this,Int::PC_INT_VAL);
192   }
193 
194   template<class View, PropCond pc, class CtrlView>
195   forceinline size_t
dispose(Space & home)196   ReUnaryPropagator<View,pc,CtrlView>::dispose(Space& home) {
197     if (pc != PC_GEN_NONE)
198       x0.cancel(home,*this,pc);
199     b.cancel(home,*this,Int::PC_INT_VAL);
200     (void) Propagator::dispose(home);
201     return sizeof(*this);
202   }
203 
204   /*
205    * Reified binary propagators
206    *
207    */
208   template<class View, PropCond pc, class CtrlView>
ReBinaryPropagator(Home home,View y0,View y1,CtrlView b1)209   ReBinaryPropagator<View,pc,CtrlView>::ReBinaryPropagator
210   (Home home, View y0, View y1, CtrlView b1)
211     : Propagator(home), x0(y0), x1(y1), b(b1) {
212     if (pc != PC_GEN_NONE) {
213       x0.subscribe(home,*this,pc);
214       x1.subscribe(home,*this,pc);
215     }
216     b.subscribe(home,*this,Int::PC_INT_VAL);
217   }
218 
219   template<class View, PropCond pc, class CtrlView>
220   forceinline
ReBinaryPropagator(Space & home,ReBinaryPropagator<View,pc,CtrlView> & p)221   ReBinaryPropagator<View,pc,CtrlView>::ReBinaryPropagator
222   (Space& home, ReBinaryPropagator<View,pc,CtrlView>& p)
223     : Propagator(home,p) {
224     x0.update(home,p.x0);
225     x1.update(home,p.x1);
226     b.update(home,p.b);
227   }
228 
229   template<class View, PropCond pc, class CtrlView>
230   forceinline
ReBinaryPropagator(Space & home,Propagator & p,View y0,View y1,CtrlView b0)231   ReBinaryPropagator<View,pc,CtrlView>::ReBinaryPropagator
232   (Space& home, Propagator& p, View y0, View y1, CtrlView b0)
233     : Propagator(home,p) {
234     x0.update(home,y0);
235     x1.update(home,y1);
236     b.update(home,b0);
237   }
238 
239   template<class View, PropCond pc, class CtrlView>
240   PropCost
cost(const Space &,const ModEventDelta &) const241   ReBinaryPropagator<View,pc,CtrlView>::cost(const Space&, const ModEventDelta&) const {
242     return PropCost::binary(PropCost::LO);
243   }
244 
245   template<class View, PropCond pc, class CtrlView>
246   void
reschedule(Space & home)247   ReBinaryPropagator<View,pc,CtrlView>::reschedule(Space& home) {
248     if (pc != PC_GEN_NONE) {
249       x0.reschedule(home,*this,pc);
250       x1.reschedule(home,*this,pc);
251     }
252     b.reschedule(home,*this,Int::PC_INT_VAL);
253   }
254 
255   template<class View, PropCond pc, class CtrlView>
256   forceinline size_t
dispose(Space & home)257   ReBinaryPropagator<View,pc,CtrlView>::dispose(Space& home) {
258     if (pc != PC_GEN_NONE) {
259       x0.cancel(home,*this,pc);
260       x1.cancel(home,*this,pc);
261     }
262     b.cancel(home,*this,Int::PC_INT_VAL);
263     (void) Propagator::dispose(home);
264     return sizeof(*this);
265   }
266 
267   /*
268    * Reified mixed binary propagator
269    *
270    */
271   template<class View0, PropCond pc0, class View1, PropCond pc1,
272             class CtrlView>
273   ReMixBinaryPropagator<View0,pc0,View1,pc1,CtrlView>
ReMixBinaryPropagator(Home home,View0 y0,View1 y1,CtrlView b1)274   ::ReMixBinaryPropagator(Home home, View0 y0, View1 y1, CtrlView b1)
275     : Propagator(home), x0(y0), x1(y1), b(b1) {
276     if (pc0 != PC_GEN_NONE)
277       x0.subscribe(home,*this,pc0);
278     if (pc1 != PC_GEN_NONE)
279       x1.subscribe(home,*this,pc1);
280     b.subscribe(home,*this,Int::PC_INT_VAL);
281   }
282 
283   template<class View0, PropCond pc0, class View1, PropCond pc1,
284             class CtrlView>
285   forceinline
ReMixBinaryPropagator(Space & home,ReMixBinaryPropagator<View0,pc0,View1,pc1,CtrlView> & p)286   ReMixBinaryPropagator<View0,pc0,View1,pc1,CtrlView>::ReMixBinaryPropagator
287   (Space& home,
288    ReMixBinaryPropagator<View0,pc0,View1,pc1,CtrlView>& p)
289     : Propagator(home,p) {
290     x0.update(home,p.x0);
291     x1.update(home,p.x1);
292     b.update(home,p.b);
293   }
294 
295   template<class View0, PropCond pc0, class View1, PropCond pc1,
296             class CtrlView>
297   forceinline
298   ReMixBinaryPropagator<View0,pc0,View1,pc1,CtrlView>
ReMixBinaryPropagator(Space & home,Propagator & p,View0 y0,View1 y1,CtrlView b0)299   ::ReMixBinaryPropagator
300   (Space& home, Propagator& p, View0 y0, View1 y1, CtrlView b0)
301     : Propagator(home,p) {
302     x0.update(home,y0);
303     x1.update(home,y1);
304     b.update(home,b0);
305   }
306 
307   template<class View0, PropCond pc0, class View1, PropCond pc1,
308             class CtrlView>
309   PropCost
310   ReMixBinaryPropagator<View0,pc0,View1,pc1,CtrlView>
cost(const Space &,const ModEventDelta &) const311   ::cost(const Space&, const ModEventDelta&) const {
312     return PropCost::binary(PropCost::LO);
313   }
314 
315   template<class View0, PropCond pc0, class View1, PropCond pc1,
316             class CtrlView>
317   void
reschedule(Space & home)318   ReMixBinaryPropagator<View0,pc0,View1,pc1,CtrlView>::reschedule(Space& home) {
319     if (pc0 != PC_GEN_NONE)
320       x0.reschedule(home,*this,pc0);
321     if (pc1 != PC_GEN_NONE)
322       x1.reschedule(home,*this,pc1);
323     b.reschedule(home,*this,Int::PC_INT_VAL);
324   }
325 
326   template<class View0, PropCond pc0, class View1, PropCond pc1,
327             class CtrlView>
328   forceinline size_t
dispose(Space & home)329   ReMixBinaryPropagator<View0,pc0,View1,pc1,CtrlView>::dispose(Space& home) {
330     if (pc0 != PC_GEN_NONE)
331       x0.cancel(home,*this,pc0);
332     if (pc1 != PC_GEN_NONE)
333       x1.cancel(home,*this,pc1);
334     b.cancel(home,*this,Int::PC_INT_VAL);
335     (void) Propagator::dispose(home);
336     return sizeof(*this);
337   }
338 
339 }}
340 
341 // STATISTICS: int-prop
342 
343