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, 2009 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 template<class Tracer> 37 forceinline 38 DFS<Tracer>::DFS(Space* s, const Options& o) 39 : tracer(o.tracer), opt(o), path(opt.nogoods_limit), d(0) { 40 if (tracer) { 41 tracer.engine(SearchTracer::EngineType::DFS, 1U); 42 tracer.worker(); 43 } 44 if ((s == nullptr) || (s->status(*this) == SS_FAILED)) { 45 fail++; 46 cur = nullptr; 47 if (!opt.clone) 48 delete s; 49 } else { 50 cur = snapshot(s,opt); 51 } 52 } 53 54 template<class Tracer> 55 forceinline void 56 DFS<Tracer>::reset(Space* s) { 57 tracer.round(); 58 delete cur; 59 path.reset(); 60 d = 0; 61 if ((s == nullptr) || (s->status(*this) == SS_FAILED)) { 62 delete s; 63 cur = nullptr; 64 } else { 65 cur = s; 66 } 67 Worker::reset(); 68 } 69 70 template<class Tracer> 71 forceinline NoGoods& 72 DFS<Tracer>::nogoods(void) { 73 return path; 74 } 75 76 template<class Tracer> 77 forceinline Space* 78 DFS<Tracer>::next(void) { 79 /* 80 * The engine maintains the following invariant: 81 * - If the current space (cur) is not nullptr, the path always points 82 * to exactly that space. 83 * - If the current space (cur) is nullptr, the path always points 84 * to the next space (if there is any). 85 * 86 * This invariant is needed so that no-goods can be extracted properly 87 * when the engine is stopped or has found a solution. 88 * 89 */ 90 start(); 91 while (true) { 92 if (stop(opt)) 93 return nullptr; 94 while (cur == nullptr) { 95 if (path.empty()) 96 return nullptr; 97 cur = path.recompute(d,opt.a_d,*this,tracer); 98 if (cur != nullptr) 99 break; 100 path.next(); 101 } 102 node++; 103 SearchTracer::EdgeInfo ei; 104 if (tracer && (path.entries() > 0)) { 105 typename Path<Tracer>::Edge& top = path.top(); 106 ei.init(tracer.wid(), top.nid(), top.truealt(), *cur, *top.choice()); 107 } 108 unsigned int nid = tracer.nid(); 109 switch (cur->status(*this)) { 110 case SS_FAILED: 111 if (tracer) { 112 SearchTracer::NodeInfo ni(SearchTracer::NodeType::FAILED, 113 tracer.wid(), nid, *cur); 114 tracer.node(ei,ni); 115 } 116 fail++; 117 delete cur; 118 cur = nullptr; 119 path.next(); 120 break; 121 case SS_SOLVED: 122 { 123 if (tracer) { 124 SearchTracer::NodeInfo ni(SearchTracer::NodeType::SOLVED, 125 tracer.wid(), nid, *cur); 126 tracer.node(ei,ni); 127 } 128 // Deletes all pending branchers 129 (void) cur->choice(); 130 Space* s = cur; 131 cur = nullptr; 132 path.next(); 133 return s; 134 } 135 case SS_BRANCH: 136 { 137 Space* c; 138 if ((d == 0) || (d >= opt.c_d)) { 139 c = cur->clone(); 140 d = 1; 141 } else { 142 c = nullptr; 143 d++; 144 } 145 const Choice* ch = path.push(*this,cur,c,nid); 146 if (tracer) { 147 SearchTracer::NodeInfo ni(SearchTracer::NodeType::BRANCH, 148 tracer.wid(), nid, *cur, ch); 149 tracer.node(ei,ni); 150 } 151 cur->commit(*ch,0); 152 break; 153 } 154 default: 155 GECODE_NEVER; 156 } 157 } 158 GECODE_NEVER; 159 return nullptr; 160 } 161 162 template<class Tracer> 163 forceinline Statistics 164 DFS<Tracer>::statistics(void) const { 165 return *this; 166 } 167 168 template<class Tracer> 169 forceinline void 170 DFS<Tracer>::constrain(const Space& b) { 171 (void) b; 172 assert(false); 173 } 174 175 template<class Tracer> 176 forceinline 177 DFS<Tracer>::~DFS(void) { 178 delete cur; 179 tracer.done(); 180 path.reset(); 181 } 182 183}}} 184 185// STATISTICS: search-seq