this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Christopher Mears <chris.mears@monash.edu>
5 *
6 * Copyright:
7 * Christopher Mears, 2012
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
34namespace Gecode { namespace Set { namespace LDSB {
35
36 template<class View, int n, class Val, unsigned int a,
37 class Filter, class Print>
38 LDSBSetBrancher<View,n,Val,a,Filter,Print>
39 ::LDSBSetBrancher(Home home, ViewArray<View>& x,
40 ViewSel<View>* vs[n],
41 ValSelCommitBase<View,Val>* vsc,
42 SymmetryImp<View>** syms, int nsyms,
43 BranchFilter<typename LDSBSetBrancher<View,n,Val,a,Filter,Print>::Var> bf,
44 VarValPrint<typename LDSBSetBrancher<View,n,Val,a,Filter,Print>::Var,Val> vvp)
45 : LDSBBrancher<View,n,Val,a,Filter,Print>
46 (home, x, vs, vsc, syms, nsyms, bf, vvp),
47 _prevPos(-1),
48 _copiedSyms(nullptr),
49 _nCopiedSyms(0),
50 _stable(false) {
51 // Put all the value symmetries at the end of the list.
52 int seen = 0;
53 int dest = this->_nsyms - 1;
54 for (int i = 0 ; i < this->_nsyms - seen ; i++) {
55 if (dynamic_cast<ValueSymmetryImp<View>*>(this->_syms[i])) {
56 SymmetryImp<View>* t = this->_syms[i];
57 this->_syms[i] = this->_syms[dest];
58 this->_syms[dest] = t;
59 dest--;
60 seen++;
61 }
62 }
63 _nValueSymmetries = seen;
64 _nNonValueSymmetries = this->_nsyms - seen;
65 }
66
67 template<class View, int n, class Val, unsigned int a,
68 class Filter, class Print>
69 LDSBSetBrancher<View,n,Val,a,Filter,Print>::
70 LDSBSetBrancher(Space& home,
71 LDSBSetBrancher<View,n,Val,a,Filter,Print>& b)
72 : LDSBBrancher<View,n,Val,a,Filter,Print>(home,b),
73 _prevPos(b._prevPos),
74 _nNonValueSymmetries(b._nNonValueSymmetries),
75 _nValueSymmetries(b._nValueSymmetries),
76 _nCopiedSyms(b._nCopiedSyms),
77 _leftBranchValues(b._leftBranchValues),
78 _stable(b._stable) {
79 if (_nCopiedSyms > 0) {
80 _copiedSyms = home.alloc<ValueSymmetryImp<View>*>(_nCopiedSyms);
81 for (int i = 0 ; i < _nCopiedSyms ; i++)
82 _copiedSyms[i] = static_cast<ValueSymmetryImp<View>*>(
83 b._copiedSyms[i]->copy(home));
84 } else {
85 _copiedSyms = nullptr;
86 }
87 }
88
89 /**
90 * \brief Bulk update of a value symmetry \a s, using \a usedValues
91 *
92 * Calculates the intersection and difference of the values in the
93 * symmetry and \a usedValues, updates the symmetry to eliminate the
94 * used values, and makes a new symmetry containing the intersection
95 * values, if there are at least two. Returns the new symmetry, or
96 * nullptr if the intersection has fewer than two elements.
97 */
98 template <class View>
99 ValueSymmetryImp<View>*
100 specialUpdate(Space& home, ValueSymmetryImp<View>* s, IntSet usedValues) {
101 // Calculate intersection and difference.
102 IntArgs intersection;
103 IntArgs difference;
104 int n = 0;
105 for (int i = s->values.next(s->values.offset()) ;
106 i <= s->values.max_bit() ; i = s->values.next(i+1)) {
107 n++;
108 if (usedValues.in(i))
109 intersection << i;
110 else
111 difference << i;
112 }
113
114 for (IntSetValues v(usedValues) ; v() ; ++v) {
115 s->update(Literal(0, v.val()));
116 }
117
118 if (intersection.size() < 2)
119 return nullptr;
120 int *a = new int[intersection.size()];
121 for (int i = 0 ; i < intersection.size() ; i++) {
122 a[i] = intersection[i];
123 }
124 ValueSymmetryImp<View>* ns =
125 new (home) ValueSymmetryImp<View>(home, a, intersection.size());
126 delete [] a;
127 return ns;
128 }
129
130 template<class View, int n, class Val, unsigned int a,
131 class Filter, class Print>
132 void
133 LDSBSetBrancher<View,n,Val,a,Filter,Print>::
134 updatePart1(Space& home, int choicePos) {
135 if (_nValueSymmetries > 0) {
136 // If this is a different variable from the last commit, restore
137 // the old value symmetries and update the copy.
138 if (choicePos != _prevPos) {
139 if (_prevPos != -1) {
140 int i = 0;
141 for (int j = _nNonValueSymmetries ; j < this->_nsyms ; j++) {
142 this->_syms[j] = _copiedSyms[i];
143 i++;
144 }
145
146 for (int i = 0 ; i < _nCopiedSyms ; i++) {
147 ValueSymmetryImp<View>* ns =
148 specialUpdate(home, _copiedSyms[i], _leftBranchValues);
149 if (ns) {
150 this->_syms = home.realloc<SymmetryImp<View>*>(this->_syms,
151 this->_nsyms,
152 this->_nsyms+1);
153 this->_syms[this->_nsyms] = ns;
154 this->_nsyms++;
155 this->_nValueSymmetries++;
156 }
157 }
158 }
159
160 // Reset for current variable, make copy of value symmetries
161 _leftBranchValues = IntSet::empty;
162 _prevPos = choicePos;
163 if (_nCopiedSyms > 0) home.free(_copiedSyms, _nCopiedSyms);
164 _nCopiedSyms = _nValueSymmetries;
165 _copiedSyms = home.alloc<ValueSymmetryImp<View>*>(_nCopiedSyms);
166 {
167 int i = 0;
168 for (int j = _nNonValueSymmetries ; j < this->_nsyms ; j++) {
169 ValueSymmetryImp<View>* vsi =
170 static_cast<ValueSymmetryImp<View>*>(this->_syms[j]);
171 _copiedSyms[i] =
172 static_cast<ValueSymmetryImp<View>*>(vsi->copy(home));
173 i++;
174 }
175 }
176 }
177 }
178 }
179
180 // Compute choice
181 template<class View, int n, class Val, unsigned int a,
182 class Filter, class Print>
183 const Choice*
184 LDSBSetBrancher<View,n,Val,a,Filter,Print>::choice(Space& home) {
185 // Making the PVC here is not so nice, I think.
186 const Choice* c = ViewValBrancher<View,n,Val,a,Filter,Print>::choice(home);
187 const PosValChoice<Val>* pvc = static_cast<const PosValChoice<Val>* >(c);
188
189 // Compute symmetries.
190
191 int choicePos = pvc->pos().pos;
192 delete c;
193
194 assert(!_stable);
195 updatePart1(home, choicePos);
196
197 return LDSBBrancher<View,n,Val,a,Filter,Print>::choice(home);
198 }
199
200 template<class View, int n, class Val, unsigned int a,
201 class Filter, class Print>
202 ExecStatus
203 LDSBSetBrancher<View,n,Val,a,Filter,Print>
204 ::commit(Space& home, const Choice& c, unsigned int b) {
205 const LDSBChoice<Val>& pvc
206 = static_cast<const LDSBChoice<Val>&>(c);
207 int choicePos = pvc.pos().pos;
208 int choiceVal = pvc.val();
209
210 if (!_stable)
211 updatePart1(home, choicePos);
212
213 if (b == 0) {
214 IntArgs ia;
215 for (IntSetValues v(_leftBranchValues) ; v() ; ++v) {
216 ia << v.val();
217 }
218 ia << choiceVal;
219 _leftBranchValues = IntSet(ia);
220
221 // Post the branching constraint.
222 ExecStatus fromBase = ViewValBrancher<View,n,Val,a,Filter,Print>
223 ::commit(home, c, b);
224 GECODE_ES_CHECK(fromBase);
225 for (int i = 0 ; i < this->_nsyms ; i++)
226 this->_syms[i]->update(Literal(choicePos, choiceVal));
227 } else if (b == 1) {
228 // Post the branching constraint.
229 ExecStatus fromBase = ViewValBrancher<View,n,Val,a,Filter,Print>
230 ::commit(home, c, b);
231 GECODE_ES_CHECK(fromBase);
232
233 // Post prunings.
234 int nliterals = pvc.nliterals();
235 const Literal* literals = pvc.literals();
236 for (int i = 0 ; i < nliterals ; i++) {
237 const Literal& l = literals[i];
238 ModEvent me = prune<View>(home, this->x[l._variable], l._value);
239 GECODE_ME_CHECK(me);
240 }
241 }
242
243 return ES_OK;
244 }
245
246 template<class View, int n, class Val, unsigned int a,
247 class Filter, class Print>
248 Actor*
249 LDSBSetBrancher<View,n,Val,a,Filter,Print>::copy(Space& home) {
250 return new (home) LDSBSetBrancher<View,n,Val,a,Filter,Print>
251 (home,*this);
252 }
253
254 template<class View, int n, class Val, unsigned int a,
255 class Filter, class Print>
256 forceinline void
257 LDSBSetBrancher<View,n,Val,a,Filter,Print>::
258 post(Home home, ViewArray<View>& x,
259 ViewSel<View>* vs[n], ValSelCommitBase<View,Val>* vsc,
260 SymmetryImp<View>** syms, int nsyms,
261 BranchFilter<typename LDSBSetBrancher<View,n,Val,a,Filter,Print>::Var> bf,
262 VarValPrint<typename LDSBSetBrancher<View,n,Val,a,Filter,Print>::Var,Val> vvp) {
263 (void) new (home) LDSBSetBrancher<View,n,Val,a,Filter,Print>
264 (home,x,vs,vsc,syms,nsyms,bf,vvp);
265 }
266
267 template<class View, int n, class Val, unsigned int a>
268 forceinline void
269 postldsbsetbrancher(Home home,
270 ViewArray<View>& x,
271 ViewSel<View>* vs[n],
272 ValSelCommitBase<View,Val>* vsc,
273 SymmetryImp<View>** syms, int nsyms,
274 BranchFilter<typename View::VarType> bf,
275 VarValPrint<typename View::VarType,Val> vvp) {
276 if (bf) {
277 if (vvp) {
278 LDSBSetBrancher<View,n,Val,a,BrancherFilter<View>,BrancherPrint<View,Val> >
279 ::post(home,x,vs,vsc,syms,nsyms,bf,vvp);
280 } else {
281 LDSBSetBrancher<View,n,Val,a,BrancherFilter<View>,BrancherNoPrint<View,Val> >
282 ::post(home,x,vs,vsc,syms,nsyms,bf,vvp);
283 }
284 } else {
285 if (vvp) {
286 LDSBSetBrancher<View,n,Val,a,BrancherNoFilter<View>,BrancherPrint<View,Val> >
287 ::post(home,x,vs,vsc,syms,nsyms,bf,vvp);
288 } else {
289 LDSBSetBrancher<View,n,Val,a,BrancherNoFilter<View>,BrancherNoPrint<View,Val> >
290 ::post(home,x,vs,vsc,syms,nsyms,bf,vvp);
291 }
292 }
293 }
294
295}}}
296
297// STATISTICS: set-branch