Generated on Mon Aug 25 11:35:40 2008 for Gecode by doxygen 1.5.6

lds.cc

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Christian Schulte, 2004
00008  *
00009  *  Bugfixes provided by:
00010  *     Stefano Gualandi
00011  *
00012  *  Last modified:
00013  *     $Date: 2008-02-05 22:18:28 +0100 (Tue, 05 Feb 2008) $ by $Author: schulte $
00014  *     $Revision: 6072 $
00015  *
00016  *  This file is part of Gecode, the generic constraint
00017  *  development environment:
00018  *     http://www.gecode.org
00019  *
00020  *  Permission is hereby granted, free of charge, to any person obtaining
00021  *  a copy of this software and associated documentation files (the
00022  *  "Software"), to deal in the Software without restriction, including
00023  *  without limitation the rights to use, copy, modify, merge, publish,
00024  *  distribute, sublicense, and/or sell copies of the Software, and to
00025  *  permit persons to whom the Software is furnished to do so, subject to
00026  *  the following conditions:
00027  *
00028  *  The above copyright notice and this permission notice shall be
00029  *  included in all copies or substantial portions of the Software.
00030  *
00031  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00032  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00033  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00034  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00035  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00036  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00037  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00038  *
00039  */
00040 
00041 #include "gecode/search.hh"
00042 
00043 namespace Gecode { namespace Search {
00044 
00045   /*
00046    * Nodes for the probing engine (just remember next alternative
00047    * to try)
00048    *
00049    */
00050 
00051   forceinline
00052   ProbeEngine::ProbeNode
00053   ::ProbeNode(Space* s, const BranchingDesc* d, unsigned int a)
00054     : _space(s), _desc(d), _alt(a) {}
00055 
00056   forceinline Space*
00057   ProbeEngine::ProbeNode::space(void) const {
00058     return _space;
00059   }
00060 
00061   forceinline const BranchingDesc*
00062   ProbeEngine::ProbeNode::desc(void) const {
00063     return _desc;
00064   }
00065 
00066   forceinline unsigned int
00067   ProbeEngine::ProbeNode::alt(void) const {
00068     return _alt;
00069   }
00070 
00071   forceinline void
00072   ProbeEngine::ProbeNode::next(void) {
00073     _alt--;
00074   }
00075 
00076 
00077   /*
00078    * The probing engine: computes all solutions with
00079    * exact number of discrepancies (solutions with
00080    * fewer discrepancies are discarded)
00081    *
00082    */
00083 
00084   forceinline
00085   ProbeEngine::ProbeEngine(Stop* st, size_t sz)
00086     : EngineCtrl(st,sz) {}
00087 
00088   forceinline void
00089   ProbeEngine::init(Space* s, unsigned int d0) {
00090     cur       = s;
00091     d         = d0;
00092     exhausted = true;
00093   }
00094 
00095   forceinline void
00096   ProbeEngine::reset(Space* s, unsigned int d0) {
00097     delete cur;
00098     assert(ds.empty());
00099     cur       = s;
00100     d         = d0;
00101     exhausted = true;
00102     EngineCtrl::reset(s);
00103   }
00104 
00105   forceinline size_t
00106   ProbeEngine::stacksize(void) const {
00107     return ds.size();
00108   }
00109 
00110   forceinline bool
00111   ProbeEngine::done(void) const {
00112     return exhausted;
00113   }
00114 
00115   forceinline
00116   ProbeEngine::~ProbeEngine(void) {
00117     delete cur;
00118     while (!ds.empty())
00119       delete ds.pop().space();
00120   }
00121 
00122   forceinline Space*
00123   ProbeEngine::explore(void) {
00124     start();
00125     while (true) {
00126       if (cur == NULL) {
00127       backtrack:
00128         if (ds.empty())
00129           return NULL;
00130         if (stop(stacksize()))
00131           return NULL;
00132         unsigned int a            = ds.top().alt();
00133         const BranchingDesc* desc = ds.top().desc();
00134         if (a == 0) {
00135           cur = ds.pop().space();
00136           EngineCtrl::pop(cur,desc);
00137           cur->commit(desc,0);
00138           delete desc;
00139         } else {
00140           ds.top().next();
00141           cur = ds.top().space()->clone();
00142           clone++;
00143           cur->commit(desc,a);
00144         }
00145         EngineCtrl::current(cur);
00146         d++;
00147       }
00148     check_discrepancy:
00149       if (d == 0) {
00150         Space* s = cur;
00151         while (s->status(propagate) == SS_BRANCH) {
00152           const BranchingDesc* desc = s->description();
00153           if (desc->alternatives() > 1)
00154             exhausted = false;
00155           s->commit(desc,0);
00156           delete desc;
00157         }
00158         cur = NULL;
00159         EngineCtrl::current(NULL);
00160         if (s->failed()) {
00161           delete s;
00162           goto backtrack;
00163         }
00164         return s;
00165       }
00166       switch (cur->status(propagate)) {
00167       case SS_FAILED:
00168         fail++;
00169       case SS_SOLVED:        
00170         delete cur;
00171         cur = NULL;
00172         EngineCtrl::current(NULL);
00173         goto backtrack;
00174       case SS_BRANCH:
00175         {
00176           const BranchingDesc* desc = cur->description();
00177           unsigned int alt          = desc->alternatives();
00178           if (alt > 1) {
00179             if (d < alt-1)
00180               exhausted = false;
00181             unsigned int d_a = (d >= alt-1) ? alt-1 : d;
00182             Space* cc = cur->clone();
00183             EngineCtrl::push(cc,desc);
00184             ProbeNode sn(cc,desc,d_a-1);
00185             clone++;
00186             ds.push(sn);
00187             cur->commit(desc,d_a);
00188             d -= d_a;
00189           } else {
00190             cur->commit(desc,0);
00191             delete desc;
00192           }
00193           commit++;
00194           goto check_discrepancy;
00195         }
00196       default: GECODE_NEVER;
00197       }
00198     }
00199   }
00200 
00201 
00202   /*
00203    * The LDS engine proper
00204    *
00205    */
00206 
00207   LDS::LDS(Space* s, unsigned int d, Stop* st, size_t sz)
00208     : root(NULL), d_cur(0), d_max(d), e(st,sz) {
00209     if (s->status(e.propagate) == SS_FAILED) {
00210       e.init(NULL,0);
00211       e.fail += 1;
00212       e.current(s);
00213     } else {
00214       e.clone++;;
00215       Space* c = s->clone();
00216       if (d_max > 0) {
00217         root = c->clone();
00218         e.clone++;
00219       }
00220       e.init(c,0);
00221       e.current(s);
00222       e.current(NULL);
00223       e.current(c);
00224     }
00225   }
00226 
00227   LDS::~LDS(void) {
00228     delete root;
00229   }
00230 
00231   Space*
00232   LDS::next(void) {
00233     while (true) {
00234       Space* s = e.explore();
00235       if (s != NULL)
00236         return s;
00237       if (((s == NULL) && e.stopped()) || (++d_cur > d_max) || e.done())
00238         break;
00239       if (d_cur == d_max) {
00240         if (root != NULL)
00241           e.reset(root,d_cur);
00242         root = NULL;
00243       } else if (root != NULL) {
00244         e.clone++;
00245         e.reset(root->clone(),d_cur);
00246       }
00247     }
00248     return NULL;
00249   }
00250 
00251   bool
00252   LDS::stopped(void) const {
00253     return e.stopped();
00254   }
00255 
00256   Statistics
00257   LDS::statistics(void) const {
00258     Statistics s = e;
00259     s.memory += e.stacksize();
00260     return e;
00261   }
00262 
00263 }}
00264 
00265 // STATISTICS: search-any