this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Patrick Pekczynski <pekczynski@ps.uni-sb.de>
5 * Guido Tack <tack@gecode.org>
6 *
7 * Contributing authors:
8 * Christian Schulte <schulte@gecode.org>
9 *
10 * Copyright:
11 * Patrick Pekczynski, 2004
12 * Christian Schulte, 2009
13 * Guido Tack, 2006
14 *
15 * This file is part of Gecode, the generic constraint
16 * development environment:
17 * http://www.gecode.org
18 *
19 * Permission is hereby granted, free of charge, to any person obtaining
20 * a copy of this software and associated documentation files (the
21 * "Software"), to deal in the Software without restriction, including
22 * without limitation the rights to use, copy, modify, merge, publish,
23 * distribute, sublicense, and/or sell copies of the Software, and to
24 * permit persons to whom the Software is furnished to do so, subject to
25 * the following conditions:
26 *
27 * The above copyright notice and this permission notice shall be
28 * included in all copies or substantial portions of the Software.
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
31 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
32 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
33 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
34 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
35 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
36 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 *
38 */
39
40#include <gecode/int/gcc.hh>
41
42namespace Gecode {
43
44 namespace {
45
46 /// Comparison operator
47 template<class X>
48 struct LessP {
49 bool operator ()(const std::pair<X,int>& lhs,
50 const std::pair<X,int>& rhs) {
51 return lhs.second < rhs.second;
52 }
53 };
54
55 /// Make \a x and \a y equal
56 IntVar unify(Home home, IntVar x, IntVar y) {
57 rel(home, x, IRT_EQ, y);
58 return x;
59 }
60 /// Make \a x and \a y equal
61 IntSet unify(Home, const IntSet& x, const IntSet& y) {
62 IntSetRanges xr(x);
63 IntSetRanges yr(y);
64 Iter::Ranges::Inter<IntSetRanges,IntSetRanges> i(xr,yr);
65 IntSet z(i);
66 return z;
67 }
68
69 /// Remove dupliate entries in \a v from both \a v and \a c
70 template<class A>
71 void removeDuplicates(Home home, A& c, IntArgs& v) {
72 typedef typename A::value_type S;
73 typedef std::pair<S,int> P;
74 Region re;
75 P* a = re.alloc<P>(c.size());
76 for (int i=0; i<c.size(); i++)
77 a[i] = P(c[i],v[i]);
78 LessP<S> l;
79 Support::quicksort(a,c.size(),l);
80 A cc;
81 IntArgs vv;
82 int cur = a[0].second-1;
83 for (int i=0; i<c.size(); i++) {
84 if (a[i].second==cur) {
85 cc[cc.size()-1] = unify(home, cc[cc.size()-1], a[i].first);
86 } else {
87 cc << a[i].first;
88 vv << a[i].second;
89 cur = a[i].second;
90 }
91 }
92 re.free<P>(a,c.size());
93 c = cc;
94 v = vv;
95 }
96
97 }
98
99 void count(Home home, const IntVarArgs& x,
100 const IntVarArgs& _c, const IntArgs& _v,
101 IntPropLevel ipl) {
102 using namespace Int;
103 IntVarArgs c(_c);
104 IntArgs v(_v);
105 if (v.size() != c.size())
106 throw ArgumentSizeMismatch("Int::count");
107 if (same(x))
108 throw ArgumentSame("Int::count");
109
110 GECODE_POST;
111
112 removeDuplicates(home,c,v);
113
114 ViewArray<IntView> xv(home, x);
115 ViewArray<GCC::CardView> cv(home, c.size());
116 // set the cardinality
117 for (int i=0; i<v.size(); i++)
118 cv[i].init(c[i],v[i]);
119 switch (vbd(ipl)) {
120 case IPL_BND:
121 GECODE_ES_FAIL(
122 (GCC::Bnd<GCC::CardView>::post(home,xv,cv)));
123 break;
124 case IPL_DOM:
125 GECODE_ES_FAIL(
126 (GCC::Dom<GCC::CardView>::post(home,xv,cv)));
127 break;
128 default:
129 GECODE_ES_FAIL(
130 (GCC::Val<GCC::CardView>::post(home,xv,cv)));
131 }
132 }
133
134 // domain is 0..|cards|- 1
135 void count(Home home, const IntVarArgs& x, const IntVarArgs& c,
136 IntPropLevel ipl) {
137 IntArgs values(c.size());
138 for (int i=0; i<c.size(); i++)
139 values[i] = i;
140 count(home, x, c, values, ipl);
141 }
142
143 // constant cards
144 void count(Home home, const IntVarArgs& x,
145 const IntSetArgs& _c, const IntArgs& _v,
146 IntPropLevel ipl) {
147 using namespace Int;
148 IntSetArgs c(_c);
149 IntArgs v(_v);
150 if (v.size() != c.size())
151 throw ArgumentSizeMismatch("Int::count");
152 if (same(x))
153 throw ArgumentSame("Int::count");
154 for (int i=0; i<c.size(); i++) {
155 Limits::check(v[i],"Int::count");
156 Limits::check(c[i].min(),"Int::count");
157 Limits::check(c[i].max(),"Int::count");
158 }
159
160 GECODE_POST;
161
162 removeDuplicates(home,c,v);
163
164 ViewArray<IntView> xv(home, x);
165
166 for (int i=0; i<v.size(); i++) {
167 if (c[i].ranges() > 1) {
168 // Found hole, so create temporary variables
169 ViewArray<GCC::CardView> cv(home, v.size());
170 for (int j=0; j<v.size(); j++)
171 cv[j].init(home,c[j],v[j]);
172 switch (vbd(ipl)) {
173 case IPL_BND:
174 GECODE_ES_FAIL(
175 (GCC::Bnd<GCC::CardView>::post(home, xv, cv)));
176 break;
177 case IPL_DOM:
178 GECODE_ES_FAIL(
179 (GCC::Dom<GCC::CardView>::post(home, xv, cv)));
180 break;
181 default:
182 GECODE_ES_FAIL(
183 (GCC::Val<GCC::CardView>::post(home, xv, cv)));
184 }
185 return;
186 }
187 }
188
189 // No holes: create CardConsts
190 ViewArray<GCC::CardConst> cv(home, c.size());
191
192 for (int i=0; i<c.size(); i++)
193 cv[i].init(home,c[i].min(),c[i].max(),v[i]);
194
195 switch (vbd(ipl)) {
196 case IPL_BND:
197 GECODE_ES_FAIL(
198 (GCC::Bnd<GCC::CardConst>::post(home, xv, cv)));
199 break;
200 case IPL_DOM:
201 GECODE_ES_FAIL(
202 (GCC::Dom<GCC::CardConst>::post(home, xv, cv)));
203 break;
204 default:
205 GECODE_ES_FAIL(
206 (GCC::Val<GCC::CardConst>::post(home, xv, cv)));
207 }
208 }
209
210 // domain is 0..|cards|- 1
211 void count(Home home, const IntVarArgs& x, const IntSetArgs& c,
212 IntPropLevel ipl) {
213 IntArgs values(c.size());
214 for (int i=0; i<c.size(); i++)
215 values[i] = i;
216 count(home, x, c, values, ipl);
217 }
218
219 void count(Home home, const IntVarArgs& x,
220 const IntSet& c, const IntArgs& v,
221 IntPropLevel ipl) {
222 IntSetArgs cards(v.size());
223 for (int i=0; i<v.size(); i++)
224 cards[i] = c;
225 count(home, x, cards, v, ipl);
226 }
227
228}
229
230// STATISTICS: int-post