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, 2007
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 <gecode/int/channel.hh>
35
36namespace Gecode { namespace Int { namespace Channel {
37
38 /// Iterates the values to be removed as defined by an array of Boolean views
39 class BoolIter {
40 private:
41 /// The array of Boolean views
42 const ViewArray<BoolView>& x;
43 /// The offset
44 const int o;
45 /// Current position in the array
46 int i;
47 public:
48 /// Initialize iterator
49 BoolIter(const ViewArray<BoolView>& x0, int o0);
50 /// Test whether further values available
51 bool operator ()(void) const;
52 /// Return value
53 int val(void) const;
54 /// Move to the next value
55 void operator ++(void);
56 };
57
58 forceinline
59 BoolIter::BoolIter(const ViewArray<BoolView>& x0, int o0) :
60 x(x0), o(o0), i(0) {
61 while ((i<x.size()) && !x[i].zero())
62 i++;
63 }
64 forceinline bool
65 BoolIter::operator ()(void) const {
66 return i<x.size();
67 }
68 forceinline int
69 BoolIter::val(void) const {
70 assert(x[i].zero());
71 return i+o;
72 }
73 forceinline void
74 BoolIter::operator ++(void) {
75 do {
76 i++;
77 } while ((i<x.size()) && !x[i].zero());
78 }
79
80
81 Actor*
82 LinkMulti::copy(Space& home) {
83 return new (home) LinkMulti(home,*this);
84 }
85
86 forceinline size_t
87 LinkMulti::dispose(Space& home) {
88 Advisors<Advisor> as(c);
89 x.cancel(home,as.advisor());
90 c.dispose(home);
91 (void) MixNaryOnePropagator<BoolView,PC_BOOL_NONE,IntView,PC_INT_DOM>
92 ::dispose(home);
93 return sizeof(*this);
94 }
95
96 PropCost
97 LinkMulti::cost(const Space&, const ModEventDelta& med) const {
98 if ((status == S_ONE) || (IntView::me(med) == ME_INT_VAL))
99 return PropCost::unary(PropCost::LO);
100 else
101 return PropCost::linear(PropCost::LO, x.size());
102 }
103
104 void
105 LinkMulti::reschedule(Space& home) {
106 if (status == S_ONE)
107 BoolView::schedule(home,*this,ME_BOOL_VAL);
108 y.reschedule(home,*this,PC_INT_DOM);
109 }
110
111 ExecStatus
112 LinkMulti::advise(Space&, Advisor&, const Delta& d) {
113 if (status == S_RUN)
114 return ES_FIX;
115 // Detect a one
116 if (BoolView::one(d))
117 status = S_ONE;
118 return ES_NOFIX;
119 }
120
121 ExecStatus
122 LinkMulti::propagate(Space& home, const ModEventDelta& med) {
123 int n = x.size();
124
125 // Always maintain the invariant that y lies inside the x-array
126 assert((y.min()-o >= 0) && (y.max()-o < n));
127
128 if (y.assigned()) {
129 status = S_RUN;
130 int j=y.val()-o;
131 GECODE_ME_CHECK(x[j].one(home));
132 for (int i=0; i<j; i++)
133 GECODE_ME_CHECK(x[i].zero(home));
134 for (int i=j+1; i<n; i++)
135 GECODE_ME_CHECK(x[i].zero(home));
136 return home.ES_SUBSUMED(*this);
137 }
138
139 // Check whether there is a one
140 if (status == S_ONE) {
141 status = S_RUN;
142 for (int i=0; true; i++)
143 if (x[i].one()) {
144 for (int j=0; j<i; j++)
145 GECODE_ME_CHECK(x[j].zero(home));
146 for (int j=i+1; j<n; j++)
147 GECODE_ME_CHECK(x[j].zero(home));
148 GECODE_ME_CHECK(y.eq(home,i+o));
149 return home.ES_SUBSUMED(*this);
150 }
151 GECODE_NEVER;
152 }
153
154 status = S_RUN;
155
156 redo:
157
158 // Assign all Boolean views to zero that are outside bounds
159 {
160 int min=y.min()-o;
161 for (int i=0; i<min; i++)
162 GECODE_ME_CHECK(x[i].zero(home));
163 x.drop_fst(min); o += min; n = x.size();
164
165 int max=y.max()-o;
166 for (int i=max+1; i<n; i++)
167 GECODE_ME_CHECK(x[i].zero(home));
168 x.drop_lst(max); n = x.size();
169 }
170
171 {
172 // Remove zeros on the left
173 int i=0;
174 while ((i < n) && x[i].zero()) i++;
175 if (i >= n)
176 return ES_FAILED;
177 x.drop_fst(i); o += i; n = x.size();
178 }
179
180 {
181 // Remove zeros on the right
182 int i=n-1;
183 while ((i >= 0) && x[i].zero()) i--;
184 assert(i >= 0);
185 x.drop_lst(i); n = x.size();
186 }
187
188 assert(n >= 1);
189
190 // Is there only one left?
191 if (n == 1) {
192 GECODE_ME_CHECK(x[0].one(home));
193 GECODE_ME_CHECK(y.eq(home,o));
194 return home.ES_SUBSUMED(*this);
195 }
196
197 // Update bounds
198 GECODE_ME_CHECK(y.gq(home,o));
199 GECODE_ME_CHECK(y.lq(home,o+n-1));
200 if ((y.min() > o) || (y.max() < o+n-1))
201 goto redo;
202
203 assert((n >= 2) && x[0].none() && x[n-1].none());
204 assert((y.min()-o == 0) && (y.max()-o == n-1));
205
206 // Propagate from y to Boolean views
207 if ((IntView::me(med) == ME_INT_BND) || (IntView::me(med) == ME_INT_DOM)) {
208 ViewValues<IntView> v(y);
209 int i=0;
210 do {
211 int j = v.val()-o;
212 if (i < j) {
213 GECODE_ME_CHECK(x[i].zero(home));
214 ++i;
215 } else if (i > j) {
216 ++v;
217 } else {
218 assert(i == j);
219 ++i; ++v;
220 }
221 } while (v() && (i < n));
222 }
223
224 // Propagate from Boolean views to y
225 if (BoolView::me(med) == ME_BOOL_VAL) {
226 BoolIter bv(x,o);
227 GECODE_ME_CHECK(y.minus_v(home,bv,false));
228 }
229 status = S_NONE;
230 return ES_FIX;
231 }
232
233}}}
234
235// STATISTICS: int-prop
236