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, 2004, 2016 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 Search { namespace Seq { 35 36 /* 37 * Nodes for the probing engine (just remember next alternative 38 * to try) 39 * 40 */ 41 42 template<class Tracer> 43 forceinline 44 Probe<Tracer>::Node::Node(void) {} 45 46 template<class Tracer> 47 forceinline 48 Probe<Tracer>::Node::Node(Space* s, const Choice* c, unsigned int a, 49 unsigned int nid) 50 : _space(s), _choice(c), _alt(a), _nid(nid) {} 51 52 template<class Tracer> 53 forceinline Space* 54 Probe<Tracer>::Node::space(void) const { 55 return _space; 56 } 57 58 template<class Tracer> 59 forceinline const Choice* 60 Probe<Tracer>::Node::choice(void) const { 61 return _choice; 62 } 63 64 template<class Tracer> 65 forceinline unsigned int 66 Probe<Tracer>::Node::alt(void) const { 67 return _alt; 68 } 69 70 template<class Tracer> 71 forceinline unsigned int 72 Probe<Tracer>::Node::nid(void) const { 73 return _nid; 74 } 75 76 template<class Tracer> 77 forceinline void 78 Probe<Tracer>::Node::next(void) { 79 _alt--; 80 } 81 82 83 /* 84 * The probing engine: computes all solutions with 85 * exact number of discrepancies (solutions with 86 * fewer discrepancies are discarded) 87 * 88 */ 89 90 template<class Tracer> 91 forceinline 92 Probe<Tracer>::Probe(const Options& opt) 93 : tracer(opt.tracer), ds(heap) { 94 tracer.engine(SearchTracer::EngineType::LDS, 1U); 95 tracer.worker(); 96 } 97 98 template<class Tracer> 99 forceinline void 100 Probe<Tracer>::init(Space* s) { 101 cur = s; d = 0U; exhausted = true; 102 if (tracer) 103 tracer.ei()->invalidate(); 104 } 105 106 template<class Tracer> 107 forceinline void 108 Probe<Tracer>::reset(Space* s, unsigned int d0) { 109 tracer.round(); 110 delete cur; 111 while (!ds.empty()) 112 delete ds.pop().space(); 113 cur = s; d = d0; exhausted = true; 114 if (tracer) 115 tracer.ei()->invalidate(); 116 Worker::reset(0); 117 } 118 119 template<class Tracer> 120 forceinline Statistics 121 Probe<Tracer>::statistics(void) const { 122 return *this; 123 } 124 125 template<class Tracer> 126 forceinline bool 127 Probe<Tracer>::done(void) const { 128 return exhausted; 129 } 130 131 template<class Tracer> 132 forceinline 133 Probe<Tracer>::~Probe(void) { 134 tracer.done(); 135 delete cur; 136 while (!ds.empty()) 137 delete ds.pop().space(); 138 } 139 140 template<class Tracer> 141 forceinline Space* 142 Probe<Tracer>::next(const Options& opt) { 143 start(); 144 while (true) { 145 if (cur == nullptr) { 146 backtrack: 147 if (ds.empty()) 148 return nullptr; 149 if (stop(opt)) 150 return nullptr; 151 unsigned int a = ds.top().alt(); 152 const Choice* ch = ds.top().choice(); 153 unsigned int nid = ds.top().nid(); 154 if (a == 0) { 155 cur = ds.pop().space(); 156 if (tracer) 157 tracer.ei()->init(tracer.wid(), nid, 0, *cur, *ch); 158 cur->commit(*ch,0); 159 delete ch; 160 } else { 161 ds.top().next(); 162 cur = ds.top().space()->clone(); 163 if (tracer) 164 tracer.ei()->init(tracer.wid(), nid, a, *cur, *ch); 165 cur->commit(*ch,a); 166 } 167 node++; 168 d++; 169 } 170 check_discrepancy: 171 if (d == 0) { 172 Space* s = cur; 173 while (s->status(*this) == SS_BRANCH) { 174 if (stop(opt)) { 175 cur = s; 176 return nullptr; 177 } 178 const Choice* ch = s->choice(); 179 if (ch->alternatives() > 1) 180 exhausted = false; 181 if (tracer) { 182 unsigned int nid = tracer.nid(); 183 SearchTracer::NodeInfo ni(SearchTracer::NodeType::BRANCH, 184 tracer.wid(), nid, *s, ch); 185 tracer.node(*tracer.ei(),ni); 186 if (tracer) 187 tracer.ei()->init(tracer.wid(), nid, 0, *cur, *ch); 188 } 189 s->commit(*ch,0); 190 node++; 191 delete ch; 192 } 193 cur = nullptr; 194 if (s->failed()) { 195 if (tracer) { 196 SearchTracer::NodeInfo ni(SearchTracer::NodeType::FAILED, 197 tracer.wid(), tracer.nid(), *s); 198 tracer.node(*tracer.ei(),ni); 199 } 200 fail++; 201 delete s; 202 goto backtrack; 203 } else { 204 if (tracer) { 205 SearchTracer::NodeInfo ni(SearchTracer::NodeType::SOLVED, 206 tracer.wid(), tracer.nid(), *s); 207 tracer.node(*tracer.ei(),ni); 208 } 209 // Deletes all pending branchings 210 (void) s->choice(); 211 return s; 212 } 213 } else { 214 node++; 215 switch (cur->status(*this)) { 216 case SS_FAILED: 217 if (tracer) { 218 SearchTracer::NodeInfo ni(SearchTracer::NodeType::FAILED, 219 tracer.wid(), tracer.nid(), *cur); 220 tracer.node(*tracer.ei(),ni); 221 } 222 fail++; 223 delete cur; 224 cur = nullptr; 225 goto backtrack; 226 case SS_SOLVED: 227 if (tracer) { 228 tracer.skip(*tracer.ei()); 229 } 230 delete cur; 231 cur = nullptr; 232 goto backtrack; 233 case SS_BRANCH: 234 { 235 const Choice* ch = cur->choice(); 236 unsigned int alt = ch->alternatives(); 237 unsigned int nid = tracer.nid(); 238 if (tracer) { 239 SearchTracer::NodeInfo ni(SearchTracer::NodeType::BRANCH, 240 tracer.wid(), nid, *cur, ch); 241 tracer.node(*tracer.ei(),ni); 242 } 243 if (alt > 1) { 244 if (d < alt-1) 245 exhausted = false; 246 unsigned int d_a = (d >= alt-1) ? alt-1 : d; 247 Space* cc = cur->clone(); 248 Node sn(cc,ch,d_a-1,nid); 249 ds.push(sn); 250 stack_depth(static_cast<unsigned long int>(ds.entries())); 251 if (tracer) 252 tracer.ei()->init(tracer.wid(), nid, d_a, *cur, *ch); 253 cur->commit(*ch,d_a); 254 d -= d_a; 255 } else { 256 if (tracer) 257 tracer.ei()->init(tracer.wid(), nid, 0, *cur, *ch); 258 cur->commit(*ch,0); 259 node++; 260 delete ch; 261 } 262 goto check_discrepancy; 263 } 264 default: GECODE_NEVER; 265 } 266 } 267 } 268 } 269 270 template<class Tracer> 271 forceinline 272 LDS<Tracer>::LDS(Space* s, const Options& o) 273 : opt(o), e(opt), root(nullptr), d(0) { 274 e.node = 1; 275 if (s->status(e) == SS_FAILED) { 276 e.fail++; 277 e.init(nullptr); 278 } else { 279 Space* c = snapshot(s,opt); 280 if (opt.d_l > 0) { 281 root = c->clone(); 282 } 283 e.init(c); 284 } 285 } 286 287 template<class Tracer> 288 Space* 289 LDS<Tracer>::next(void) { 290 while (true) { 291 Space* s = e.next(opt); 292 if (s != nullptr) 293 return s; 294 if (((s == nullptr) && e.stopped()) || (++d > opt.d_l) || e.done()) 295 break; 296 if (d == opt.d_l) { 297 if (root != nullptr) 298 e.reset(root,d); 299 root = nullptr; 300 } else if (root != nullptr) { 301 e.reset(root->clone(),d); 302 } 303 } 304 return nullptr; 305 } 306 307 template<class Tracer> 308 bool 309 LDS<Tracer>::stopped(void) const { 310 return e.stopped(); 311 } 312 313 template<class Tracer> 314 Statistics 315 LDS<Tracer>::statistics(void) const { 316 return e.statistics(); 317 } 318 319 320 template<class Tracer> 321 forceinline void 322 LDS<Tracer>::reset(Space* s) { 323 delete root; root=nullptr; d=0; 324 e.node = 1; 325 if ((s == nullptr) || (s->status(e) == SS_FAILED)) { 326 delete s; 327 e.fail++; 328 e.reset(nullptr,0); 329 } else { 330 if (opt.d_l > 0) { 331 root = s->clone(); 332 } 333 e.reset(s,0); 334 } 335 } 336 337 template<class Tracer> 338 forceinline void 339 LDS<Tracer>::constrain(const Space& b) { 340 (void) b; 341 assert(false); 342 } 343 344 template<class Tracer> 345 LDS<Tracer>::~LDS(void) { 346 delete root; 347 } 348 349}}} 350 351// STATISTICS: search-seq