00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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_;
00172 SumVec lower_;
00173 SumVec opt_[2];
00174 MinimizeMode mode_;
00175 Atomic count_;
00176 Atomic gCount_;
00177 uint32 optGen_;
00178 public:
00179 WeightVec weights;
00180 WeightLiteral lits[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_;
00246 SumVec adjust_;
00247 bool ready_;
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_;
00303 Literal tag_;
00304 };
00305
00307
00311 class DefaultMinimize : public MinimizeConstraint {
00312 public:
00313 explicit DefaultMinimize(SharedData* d, uint32 strat);
00314
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
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
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
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
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
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
00406 wsum_t& stepLow() const { return *(end() + step_.lev); }
00407 void stepInit(uint32 n);
00408 wsum_t* bounds_;
00409 Iter pos_;
00410 UndoInfo* undo_;
00411 uint32 undoTop_;
00412 uint32 posTop_;
00413 const uint32 size_;
00414 uint32 actLev_;
00415 struct Step {
00416 uint32 size;
00417 uint32 lev : 30;
00418 uint32 type: 2;
00419 } step_;
00420 };
00421
00423 class UncoreMinimize : public MinimizeConstraint {
00424 public:
00425
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
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
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
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
00503 EnumPtr enum_;
00504 wsum_t* sum_;
00505 LitTable litData_;
00506 CoreTable open_;
00507 ConTable closed_;
00508 LitSet assume_;
00509 LitSet todo_;
00510 LitVec fix_;
00511 LitVec conflict_;
00512 WCTemp temp_;
00513 wsum_t lower_;
00514 wsum_t upper_;
00515 uint32 auxInit_;
00516 uint32 auxAdd_;
00517 uint32 gen_;
00518 uint32 level_ : 25;
00519 uint32 valid_ : 1;
00520 uint32 hasPre_: 1;
00521 uint32 sat_ : 1;
00522 uint32 pre_ : 1;
00523 uint32 path_ : 1;
00524 uint32 next_ : 1;
00525 uint32 init_ : 1;
00526 uint32 eRoot_;
00527 uint32 aTop_;
00528 uint32 freeOpen_;
00529 };
00530
00531 }
00532
00533 #endif