minimize_constraint.h
Go to the documentation of this file.
00001 // 
00002 // Copyright (c) 2010-2012, Benjamin Kaufmann
00003 // 
00004 // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ 
00005 // 
00006 // Clasp is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU General Public License as published by
00008 // the Free Software Foundation; either version 2 of the License, or
00009 // (at your option) any later version.
00010 // 
00011 // Clasp is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 // 
00016 // You should have received a copy of the GNU General Public License
00017 // along with Clasp; if not, write to the Free Software
00018 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019 //
00020 #ifndef CLASP_MINIMIZE_CONSTRAINT_H_INCLUDED
00021 #define CLASP_MINIMIZE_CONSTRAINT_H_INCLUDED
00022 
00023 #ifdef _MSC_VER
00024 #pragma warning (disable : 4200) // nonstandard extension used : zero-sized array
00025 #pragma once
00026 #endif
00027 
00028 #include <clasp/constraint.h>
00029 #include <clasp/util/atomic.h>
00030 #include <clasp/util/misc_types.h>
00031 #include <cassert>
00032 
00033 namespace Clasp {
00034 class MinimizeConstraint;
00035 class WeightConstraint;
00036 
00038 
00044 struct MinimizeMode_t {
00045         enum Mode {
00046                 ignore    = 0, 
00047                 optimize  = 1, 
00048                 enumerate = 2, 
00049                 enumOpt   = 3, 
00050         };
00051 };
00052 typedef MinimizeMode_t::Mode MinimizeMode;
00053 
00055 
00058 class SharedMinimizeData {
00059 public:
00060         typedef SharedMinimizeData ThisType;
00062 
00067         struct LevelWeight {
00068                 LevelWeight(uint32 l, weight_t w) : level(l), next(0), weight(w) {}
00069                 uint32   level : 31; 
00070                 uint32   next  :  1; 
00071                 weight_t weight;     
00072         };
00074         typedef PodVector<LevelWeight>::type WeightVec;
00075         explicit SharedMinimizeData(const SumVec& lhsAdjust, MinimizeMode m = MinimizeMode_t::optimize);
00077         ThisType*      share()               { ++count_; return this; }
00079         void           release()             { if (--count_ == 0) destroy(); }
00081         uint32         numRules()       const{ return static_cast<uint32>(adjust_.size()); }
00082         uint32         maxLevel()       const{ return numRules()-1; }
00083         static wsum_t  maxBound()            { return INT64_MAX; }
00085         MinimizeMode   mode()           const{ return mode_; }
00087         bool           optimize()       const{ return optGen_ ? checkNext() : mode_ != MinimizeMode_t::enumerate; }
00089         wsum_t         lower(uint32 x)  const{ return lower_[x]; }
00090         const wsum_t*  lower()          const{ return &lower_[0]; }
00092         wsum_t         upper(uint32 x)  const{ return upper()[x]; }
00093         const wsum_t*  upper()          const{ return &(opt_ + (gCount_ & 1u))->front(); }
00095         wsum_t         adjust(uint32 x) const{ return adjust_[x]; }
00097         wsum_t         optimum(uint32 x)const{ return adjust(x) + (mode_ != MinimizeMode_t::enumerate ? upper(x) : opt_[1][x]); }
00099         uint32         level(uint32 i)  const{ return numRules() == 1 ? 0 : weights[lits[i].second].level; }
00101         weight_t       weight(uint32 i) const{ return numRules() == 1 ? lits[i].second : weights[lits[i].second].weight; }
00102         uint32         generation()     const{ return gCount_; }
00104         bool           checkNext()      const{ return mode() != MinimizeMode_t::enumerate && generation() != optGen_; }
00106         bool heuristic(Solver& s, bool full) const;
00112         
00114 
00118         bool setMode(MinimizeMode m, const wsum_t* bound = 0, uint32 boundSize = 0);
00119         bool setMode(MinimizeMode m, const SumVec& bound) { return setMode(m, bound.empty() ? 0 : &bound[0], (uint32)bound.size()); }
00120         void resetBounds();
00121         
00123 
00129         MinimizeConstraint* attach(Solver& s, uint32 strat = UINT32_MAX, bool addRef = true);
00130         
00132 
00135         const SumVec* setOptimum(const wsum_t* opt);
00137         void          setLower(uint32 lev, wsum_t low);
00139 
00143         void          markOptimal();
00145 
00150 
00151         void add(wsum_t* lhs, const WeightLiteral& lit) const { if (weights.empty()) *lhs += lit.second; else add(lhs, &weights[lit.second]); }
00152         void add(wsum_t* lhs, const LevelWeight* w)     const { do { lhs[w->level] += w->weight; } while (w++->next); }
00154         void sub(wsum_t* lhs, const WeightLiteral& lit, uint32& aLev) const { if (weights.empty()) *lhs -= lit.second; else sub(lhs, &weights[lit.second], aLev); }
00155         void sub(wsum_t* lhs, const LevelWeight* w, uint32& aLev)     const;
00157         bool imp(wsum_t* lhs, const WeightLiteral& lit, const wsum_t* rhs, uint32& lev) const {
00158                 return weights.empty() ? (*lhs+lit.second) > *rhs : imp(lhs, &weights[lit.second],  rhs, lev);
00159         }
00160         bool imp(wsum_t* lhs, const LevelWeight* w, const wsum_t* rhs, uint32& lev) const;
00162         weight_t weight(const WeightLiteral& lit, uint32 lev) const {
00163                 if (numRules() == 1) { return lit.second * (lev == 0); }
00164                 const LevelWeight* w = &weights[lit.second];
00165                 do { if (w->level == lev) return w->weight; } while (w++->next);
00166                 return 0;
00167         }
00169 private:
00170         typedef Clasp::atomic<uint32> Atomic;
00171         SumVec       adjust_;  // initial bound adjustments
00172         SumVec       lower_;   // (unadjusted) lower bound of constraint
00173         SumVec       opt_[2];  // buffers for update via "double buffering"
00174         MinimizeMode mode_;    // how to compare assignments?
00175         Atomic       count_;   // number of refs to this object
00176         Atomic       gCount_;  // generation count - used when updating optimum
00177         uint32       optGen_;  // generation of optimal bound
00178 public:
00179         WeightVec     weights; // sparse vectors of weights - only used for multi-level constraints
00180         WeightLiteral lits[0]; // (shared) literals - terminated with posLit(0)
00181 private: 
00182         ~SharedMinimizeData();
00183         void destroy() const;
00184         SharedMinimizeData(const SharedMinimizeData&);
00185         SharedMinimizeData& operator=(const SharedMinimizeData&);
00186 };
00187 
00189 class MinimizeBuilder {
00190 public:
00191         typedef SharedMinimizeData SharedData;
00192         MinimizeBuilder();
00193         ~MinimizeBuilder();
00194         
00195         bool             hasRules() const { return !adjust_.empty(); }
00196         uint32           numRules() const { return (uint32)adjust_.size(); }
00197         uint32           numLits()  const { return (uint32)lits_.size(); }
00199 
00203         MinimizeBuilder& addRule(const WeightLitVec& lits, wsum_t adjustSum = 0);
00204         MinimizeBuilder& addLit(uint32 lev, WeightLiteral lit);
00205         
00207 
00215         SharedData*      build(SharedContext& ctx);
00216         void clear();
00217 private:
00218         struct Weight {
00219                 Weight(uint32 lev, weight_t w) : level(lev), weight(w), next(0) {}
00220                 uint32   level;
00221                 weight_t weight;
00222                 Weight*  next;
00223                 static void free(Weight*& w);
00224         };
00225         typedef std::pair<Literal, Weight*> LitRep;
00226         typedef PodVector<LitRep>::type     LitRepVec;
00227         struct CmpByLit {
00228                 bool operator()(const LitRep& lhs, const LitRep& rhs) const;
00229         };
00230         struct CmpByWeight {
00231                 bool operator()(const LitRep& lhs, const LitRep& rhs) const;
00232                 int  compare   (const LitRep& lhs, const LitRep& rhs) const;
00233         };
00234         void     unfreeze();
00235         bool     prepare(SharedContext& ctx);
00236         void     addTo(LitRep l, SumVec& vec);
00237         void     mergeReduceWeight(LitRep& x, LitRep& by);
00238         weight_t addFlattened(SharedData::WeightVec& x, const Weight& w);
00239         bool     eqWeight(const SharedData::LevelWeight* lhs, const Weight& rhs);
00240         weight_t addLitImpl(uint32 lev, WeightLiteral lit) {
00241                 if (lit.second > 0) { lits_.push_back(LitRep(lit.first, new Weight(lev, lit.second)));   return 0; }
00242                 if (lit.second < 0) { lits_.push_back(LitRep(~lit.first, new Weight(lev, -lit.second))); return lit.second; }
00243                 return 0;
00244         }
00245         LitRepVec lits_;  // all literals
00246         SumVec    adjust_;// lhs adjustments
00247         bool      ready_; // prepare was called
00248 };
00249 
00251 
00272 class MinimizeConstraint : public Constraint {
00273 public:
00274         typedef SharedMinimizeData       SharedData;
00275         typedef const SharedData*        SharedDataP;
00277         SharedDataP shared()  const { return shared_; } 
00279         virtual bool attach(Solver& s)    = 0;
00281         virtual bool integrate(Solver& s) = 0;
00283 
00286         virtual bool relax(Solver& s, bool reset) = 0;
00288 
00292         virtual bool handleModel(Solver& s) = 0;
00294         virtual bool handleUnsat(Solver& s, bool upShared, LitVec& restore) = 0;
00295 
00296         void         destroy(Solver*, bool);
00297         Constraint*  cloneAttach(Solver& other);
00298 protected:
00299         MinimizeConstraint(SharedData* s);
00300         ~MinimizeConstraint();
00301         bool prepare(Solver& s, bool useTag);
00302         SharedData* shared_; // common shared data
00303         Literal     tag_;    // (optional) literal for tagging reasons
00304 };
00305 
00307 
00311 class DefaultMinimize : public MinimizeConstraint {
00312 public:
00313         explicit DefaultMinimize(SharedData* d, uint32 strat);
00314         // base interface
00316 
00321         bool       attach(Solver& s);
00322         bool       integrate(Solver& s)           { return integrateBound(s); }
00323         bool       relax(Solver&, bool reset)     { return relaxBound(reset); }
00324         bool       handleModel(Solver& s)         { commitUpperBound(s); return true; }
00325         bool       handleUnsat(Solver& s, bool up, LitVec& out);
00326         // constraint interface
00327         PropResult propagate(Solver& s, Literal p, uint32& data);
00328         void       undoLevel(Solver& s);
00329         void       reason(Solver& s, Literal p, LitVec& lits);
00330         bool       minimize(Solver& s, Literal p, CCMinRecursive* r);
00331         void       destroy(Solver*, bool);
00332         // own interface
00333         bool       active()  const { return *opt() != SharedData::maxBound(); }
00335         uint32     numRules()const { return size_; }
00337 
00354         bool       integrateBound(Solver& s);
00355 
00357 
00363         void       commitUpperBound(const Solver& s);
00365 
00374         bool       commitLowerBound(const Solver& s, bool upShared);
00375         
00377 
00380         bool       relaxBound(bool full = false);
00381 
00382         bool       more() const { return step_.lev != size_; }
00383 
00384         // FOR TESTING ONLY!
00385         wsum_t sum(uint32 i, bool adjust) const { return sum()[i] + (adjust ? shared_->adjust(i):0); }
00386 private:
00387         enum PropMode  { propagate_new_sum, propagate_new_opt };
00388         union UndoInfo;
00389         typedef const WeightLiteral* Iter;
00390         ~DefaultMinimize();
00391         // bound operations
00392         wsum_t* opt() const { return bounds_; }
00393         wsum_t* sum() const { return bounds_ + size_; }
00394         wsum_t* temp()const { return bounds_ + (size_*2); }
00395         wsum_t* end() const { return bounds_ + (size_*3); }
00396         void    assign(wsum_t* lhs, wsum_t* rhs)  const;
00397         bool    greater(wsum_t* lhs, wsum_t* rhs, uint32 len, uint32& aLev) const;
00398         // propagation & undo
00399         uint32  lastUndoLevel(const Solver& s) const;
00400         bool    litSeen(uint32 i) const;
00401         bool    propagateImpl(Solver& s, PropMode m);
00402         uint32  computeImplicationSet(const Solver& s, const WeightLiteral& it, uint32& undoPos);
00403         void    pushUndo(Solver& s, uint32 litIdx);
00404         bool    updateBounds(bool applyStep);
00405         // step
00406         wsum_t& stepLow() const { return *(end() + step_.lev); }
00407         void    stepInit(uint32 n);
00408         wsum_t*      bounds_;  // [upper,sum,temp[,lower]]
00409         Iter         pos_;     // position of literal to look at next
00410         UndoInfo*    undo_;    // one "seen" flag for each literal +
00411         uint32       undoTop_; // undo stack holding assigned literals
00412         uint32       posTop_;  // stack of saved "look at" positions
00413         const uint32 size_;    // number of rules
00414         uint32       actLev_;  // first level to look at when comparing bounds
00415         struct Step {          // how to reduce next tentative bound
00416         uint32 size;           //   size of step
00417         uint32 lev : 30;       //   level on which step is applied
00418         uint32 type:  2;       //   type of step (one of SolverStrategies::OptStrategy)
00419         }            step_;
00420 };
00421 
00423 class UncoreMinimize : public MinimizeConstraint {
00424 public:
00425         // constraint interface
00426         PropResult propagate(Solver& s, Literal p, uint32& data);
00427         void       reason(Solver& s, Literal p, LitVec& lits);
00428         void       destroy(Solver*, bool);
00429         bool       simplify(Solver& s, bool reinit = false);
00430         // base interface
00431         bool       attach(Solver& s);
00432         bool       integrate(Solver& s);
00433         bool       relax(Solver&, bool reset);
00434         bool       valid(Solver& s);
00435         bool       handleModel(Solver& s);
00436         bool       handleUnsat(Solver& s, bool up, LitVec& out);
00437 private:
00438         friend class SharedMinimizeData;
00439         explicit UncoreMinimize(SharedData* d, bool preprocess);
00440         typedef DefaultMinimize* EnumPtr;
00441         struct LitData {
00442                 LitData(weight_t w, bool as, uint32 c) : weight(w), coreId(c), assume((uint32)as) {}
00443                 weight_t weight;
00444                 uint32   coreId : 31;
00445                 uint32   assume :  1;
00446         };
00447         struct LitPair {
00448                 LitPair(Literal p, uint32 dataId) : lit(p), id(dataId) {}
00449                 Literal lit;
00450                 uint32  id;
00451         };
00452         struct Core {
00453                 Core(WeightConstraint* c, weight_t b, weight_t w) : con(c), bound(b), weight(w) {}
00454                 uint32  size()       const;
00455                 Literal at(uint32 i) const;
00456                 Literal tag()        const;
00457                 WeightConstraint* con;
00458                 weight_t          bound;
00459                 weight_t          weight;
00460         };
00461         struct WCTemp {
00462                 typedef WeightLitVec WLitVec;
00463                 void     start(weight_t b){ lits.clear(); bound = b; }
00464                 void     add(Solver& s, Literal p);
00465                 bool     unsat() const { return bound > 0 && static_cast<uint32>(bound) > static_cast<uint32>(lits.size()); }
00466                 weight_t bound;
00467                 WLitVec  lits;
00468         };
00469         typedef PodVector<LitData>::type     LitTable;
00470         typedef PodVector<Core>::type        CoreTable;
00471         typedef PodVector<Constraint*>::type ConTable;
00472         typedef PodVector<LitPair>::type     LitSet;
00473         // literal and core management
00474         bool     hasCore(const LitData& x) const { return x.coreId != 0; }
00475         LitData& getData(uint32 id)              { return litData_[id-1];}
00476         Core&    getCore(const LitData& x)       { return open_[x.coreId-1]; }
00477         LitData& addLit(Literal p, weight_t w);
00478         void     releaseLits();
00479         bool     addCore(Solver& s, const LitPair* lits, uint32 size, weight_t weight);
00480         bool     addCore(Solver& s, const WCTemp& wc, weight_t w);
00481         bool     closeCore(Solver& s, LitData& x, bool sat);
00482         uint32   allocCore(WeightConstraint* con, weight_t bound, weight_t weight, bool open);
00483         // algorithm
00484         void     init();
00485         uint32   initRoot(Solver& s);
00486         bool     initLevel(Solver& s);
00487         uint32   analyze(Solver& s, LitVec& cfl, weight_t& minW, LitVec& poppedOther);
00488         bool     pushPath(Solver& s);
00489         void     integrateOpt(Solver& s);
00490         bool     popPath(Solver& s, uint32 dl, LitVec& out);
00491         bool     fixLit(Solver& s, Literal p);
00492         bool     fixLevel(Solver& s);
00493         void     detach(Solver* s, bool b);
00494         wsum_t*  computeSum(Solver& s) const;
00495         void     setLower(wsum_t x) {
00496                 if (!pre_ && x > lower_) { lower_ = x; }
00497         }
00498         bool    validLowerBound() const {
00499                 wsum_t cmp = lower_ - upper_;
00500                 return cmp < 0 || (cmp == 0 && level_ == shared_->maxLevel() && !shared_->checkNext());
00501         }
00502         // data
00503         EnumPtr   enum_;      // for supporting (optimal) model enumeration in parallel mode
00504         wsum_t*   sum_;       // costs of active model
00505         LitTable  litData_;   // data for active literals (tag lits for cores + lits from active minimize)
00506         CoreTable open_;      // open cores, i.e. relaxable and referenced by an assumption
00507         ConTable  closed_;    // closed cores represented as weight constraints
00508         LitSet    assume_;    // current set of assumptions
00509         LitSet    todo_;      // core(s) not yet represented as constraint
00510         LitVec    fix_;       // set of fixed literals
00511         LitVec    conflict_;  // current conflict
00512         WCTemp    temp_;      // temporary: used for creating weight constraints
00513         wsum_t    lower_;     // lower bound of active level
00514         wsum_t    upper_;     // upper bound of active level
00515         uint32    auxInit_;   // number of solver aux vars on attach
00516         uint32    auxAdd_;    // number of aux vars added for cores
00517         uint32    gen_;       // active generation
00518         uint32    level_ : 25;// active level
00519         uint32    valid_ :  1;// valid w.r.t active generation?
00520         uint32    hasPre_:  1;// use preprocessing?
00521         uint32    sat_   :  1;// update because of model
00522         uint32    pre_   :  1;// preprocessing active?
00523         uint32    path_  :  1;// push path?
00524         uint32    next_  :  1;// assume next level?
00525         uint32    init_  :  1;// init constraint?
00526         uint32    eRoot_;     // saved root level of solver (initial gp)
00527         uint32    aTop_;      // saved assumption level (added by us)
00528         uint32    freeOpen_;  // head of open core free list
00529 };
00530 
00531 } // end namespace Clasp
00532 
00533 #endif


clasp
Author(s): Benjamin Kaufmann
autogenerated on Thu Aug 27 2015 12:41:39