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 * Contributing authors: 7 * Guido Tack <tack@gecode.org> 8 * 9 * Copyright: 10 * Christian Schulte, 2004 11 * Guido Tack, 2004 12 * 13 * This file is part of Gecode, the generic constraint 14 * development environment: 15 * http://www.gecode.org 16 * 17 * Permission is hereby granted, free of charge, to any person obtaining 18 * a copy of this software and associated documentation files (the 19 * "Software"), to deal in the Software without restriction, including 20 * without limitation the rights to use, copy, modify, merge, publish, 21 * distribute, sublicense, and/or sell copies of the Software, and to 22 * permit persons to whom the Software is furnished to do so, subject to 23 * the following conditions: 24 * 25 * The above copyright notice and this permission notice shall be 26 * included in all copies or substantial portions of the Software. 27 * 28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 29 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 31 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 32 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 33 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 34 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 35 * 36 */ 37 38namespace Gecode { namespace Search { namespace Seq { 39 40 template<class Tracer> 41 forceinline 42 BAB<Tracer>::BAB(Space* s, const Options& o) 43 : tracer(o.tracer), opt(o), path(opt.nogoods_limit), d(0), mark(0), 44 best(nullptr) { 45 if (tracer) { 46 tracer.engine(SearchTracer::EngineType::BAB, 1U); 47 tracer.worker(); 48 } 49 if ((s == nullptr) || (s->status(*this) == SS_FAILED)) { 50 fail++; 51 cur = nullptr; 52 if (!o.clone) 53 delete s; 54 } else { 55 cur = snapshot(s,opt); 56 } 57 } 58 59 template<class Tracer> 60 forceinline Space* 61 BAB<Tracer>::next(void) { 62 /* 63 * The engine maintains the following invariant: 64 * - If the current space (cur) is not nullptr, the path always points 65 * to exactly that space. 66 * - If the current space (cur) is nullptr, the path always points 67 * to the next space (if there is any). 68 * 69 * This invariant is needed so that no-goods can be extracted properly 70 * when the engine is stopped or has found a solution. 71 * 72 * An additional invariant maintained by the engine is: 73 * For all nodes stored at a depth less than mark, there 74 * is no guarantee of betterness. For those above the mark, 75 * betterness is guaranteed. 76 * 77 */ 78 start(); 79 while (true) { 80 if (stop(opt)) 81 return nullptr; 82 // Recompute and add constraint if necessary 83 while (cur == nullptr) { 84 if (path.empty()) 85 return nullptr; 86 cur = path.recompute(d,opt.a_d,*this,*best,mark,tracer); 87 if (cur != nullptr) 88 break; 89 path.next(); 90 } 91 node++; 92 SearchTracer::EdgeInfo ei; 93 if (tracer && (path.entries() > 0)) { 94 typename Path<Tracer>::Edge& top = path.top(); 95 ei.init(tracer.wid(), top.nid(), top.truealt(), *cur, *top.choice()); 96 } 97 unsigned int nid = tracer.nid(); 98 switch (cur->status(*this)) { 99 case SS_FAILED: 100 if (tracer) { 101 SearchTracer::NodeInfo ni(SearchTracer::NodeType::FAILED, 102 tracer.wid(), nid, *cur); 103 tracer.node(ei,ni); 104 } 105 fail++; 106 delete cur; 107 cur = nullptr; 108 path.next(); 109 break; 110 case SS_SOLVED: 111 { 112 if (tracer) { 113 SearchTracer::NodeInfo ni(SearchTracer::NodeType::SOLVED, 114 tracer.wid(), nid, *cur); 115 tracer.node(ei,ni); 116 } 117 // Deletes all pending branchers 118 (void) cur->choice(); 119 delete best; 120 best = cur; 121 cur = nullptr; 122 path.next(); 123 mark = path.entries(); 124 } 125 return best->clone(); 126 case SS_BRANCH: 127 { 128 Space* c; 129 if ((d == 0) || (d >= opt.c_d)) { 130 c = cur->clone(); 131 d = 1; 132 } else { 133 c = nullptr; 134 d++; 135 } 136 const Choice* ch = path.push(*this,cur,c,nid); 137 if (tracer) { 138 SearchTracer::NodeInfo ni(SearchTracer::NodeType::BRANCH, 139 tracer.wid(), nid, *cur, ch); 140 tracer.node(ei,ni); 141 } 142 cur->commit(*ch,0); 143 break; 144 } 145 default: 146 GECODE_NEVER; 147 } 148 } 149 GECODE_NEVER; 150 return nullptr; 151 } 152 153 template<class Tracer> 154 forceinline Statistics 155 BAB<Tracer>::statistics(void) const { 156 return *this; 157 } 158 159 template<class Tracer> 160 forceinline void 161 BAB<Tracer>::constrain(const Space& b) { 162 if (best != nullptr) { 163 // Check whether b is in fact better than best 164 best->constrain(b); 165 if (best->status(*this) != SS_FAILED) 166 return; 167 else 168 delete best; 169 } 170 best = b.clone(); 171 if (cur != nullptr) 172 cur->constrain(b); 173 mark = path.entries(); 174 } 175 176 template<class Tracer> 177 forceinline void 178 BAB<Tracer>::reset(Space* s) { 179 tracer.round(); 180 delete best; 181 best = nullptr; 182 path.reset(); 183 d = 0; 184 mark = 0; 185 delete cur; 186 if ((s == nullptr) || (s->status(*this) == SS_FAILED)) { 187 delete s; 188 cur = nullptr; 189 } else { 190 cur = s; 191 } 192 Worker::reset(); 193 } 194 195 template<class Tracer> 196 forceinline NoGoods& 197 BAB<Tracer>::nogoods(void) { 198 return path; 199 } 200 201 template<class Tracer> 202 forceinline 203 BAB<Tracer>::~BAB(void) { 204 tracer.done(); 205 path.reset(); 206 delete best; 207 delete cur; 208 } 209 210}}} 211 212// STATISTICS: search-seq