示例#1
0
/////////////////////////////////////////////////////////////////////////////////////////
// solve
/////////////////////////////////////////////////////////////////////////////////////////
bool solve(Solver& s, const SolveParams& p) {
	s.stats.solve.reset();
	if (s.hasConflict()) return false;
	double maxLearnts   = p.computeReduceBase(s);
	double boundLearnts = p.reduce.max();
	RestartStrategy rs(p.restart);
	ValueRep result;
	uint32 randRuns = p.randRuns();
	double randFreq = randRuns == 0 ? p.randomProbability() : 1.0;
	uint64 maxCfl   = randRuns == 0 ? rs.next() : p.randConflicts();
	uint32 shuffle  = p.shuffleBase();
	do {
		result    = p.enumerator()->search(s, maxCfl, (uint32)maxLearnts, randFreq, p.restart.local);
		if ((result & value_true) != 0) {
			if (!p.enumerator()->backtrackFromModel(s)) {
				break; // No more models requested
			}
			else {
				// continue enumeration
				// but cancel remaining probings
				randRuns = 0;        
				randFreq = p.randomProbability();
				if (p.restart.resetOnModel) {
					rs.reset();
					maxCfl = rs.next();
				}
				if (!p.restart.bounded && s.backtrackLevel() > 0) {
					// After the first solution was found, we allow further restarts only if this
					// is compatible with the enumerator used. 
					maxCfl = static_cast<uint64>(-1);	
				}
			}
		}
		else if (result == value_free){  // restart search
			if (randRuns == 0) {
				maxCfl = rs.next();
				if (p.reduce.reduceOnRestart) { s.reduceLearnts(.33f); }
				if (maxLearnts != (double)std::numeric_limits<uint32>::max() && maxLearnts < boundLearnts && (s.numLearntConstraints()+maxCfl) > maxLearnts) {
					maxLearnts = std::min(maxLearnts*p.reduce.inc(), (double)std::numeric_limits<uint32>::max());
				}
				if (++s.stats.solve.restarts == shuffle) {
					shuffle += p.shuffleNext();
					s.shuffleOnNextSimplify();
				}
			}
			else if (--randRuns == 0) {
				maxCfl    = rs.next();
				randFreq  = p.randomProbability();
			} 
		}
	} while (result < value_false);
	store_clear_bit(result, Enumerator::LIMIT_BIT);
	bool more = result == value_free || s.decisionLevel() > s.rootLevel();
	p.enumerator()->endSearch(s, !more);
	s.undoUntil(0);
	return more;
}
示例#2
0
ValueRep SolveAlgorithm::solvePath(Solver& s, const SolveParams& p, SolveLimits& lim) {
	if (s.hasConflict()) return value_false;
	if (lim.reached())   return value_free;
	struct  ConflictLimits {
		uint64 restart; // current restart limit
		uint64 reduce;  // current reduce limit
		uint64 grow;    // current limit for next growth operation
		uint64 global;  // current global limit
		uint64 min()      const { return std::min(std::min(restart, grow), std::min(reduce, global)); }
		void  update(uint64 x)  { restart -= x; reduce -= x; grow -= x; global -= x; }
	}            cLimit;
	typedef Range<double> RangeD;
	typedef SolvePathEvent EventType;
	SearchLimits sLimit;
	WeightLitVec inDegree;
	ScheduleStrategy ds = p.reduce.cflSched;
	ScheduleStrategy dg = p.reduce.growSched;
	ScheduleStrategy rs = p.restart.sched;
	Solver::DBInfo   db = {0,0,0};
	ValueRep result     = value_free;
	uint64 lastC        = s.stats.conflicts;
	uint64 lastR        = s.stats.restarts;
	uint64 nextUp       = 16000;
	s.stats.cflLast     = s.stats.analyzed;
	uint32 shuffle      = p.restart.shuffle;
	RangeD dbSizeLimit  = !dg.disabled() || dg.defaulted() 
	                    ? RangeD(p.reduce.initLimit(*s.sharedContext()), p.reduce.maxLimit(*s.sharedContext())) 
	                    : RangeD(p.reduce.maxRange, p.reduce.maxRange);
	uint32 dbRedInit    = ds.disabled() ? 0 : p.reduce.initLimit(*s.sharedContext());
	if (dbSizeLimit.lo < s.numLearntConstraints()) { dbSizeLimit.lo = dbSizeLimit.clamp(s.numLearntConstraints() + p.reduce.initRange.lo); }
	if (dbSizeLimit.lo > p.reduce.maxRange)        { dbSizeLimit.lo = p.reduce.maxRange; }
	if (dbSizeLimit.hi > p.reduce.maxRange)        { dbSizeLimit.hi = p.reduce.maxRange; }
	if (dbRedInit && ds.type != ScheduleStrategy::luby_schedule) {
		if (dbRedInit < ds.base) {
			dbRedInit = std::min(ds.base, std::max(dbRedInit,(uint32)5000));
			ds.grow   = dbRedInit != ds.base ? std::min(ds.grow, dbRedInit/2.0f) : ds.grow;
			ds.base   = dbRedInit;
		}
		dbRedInit   = 0;
	}
	double dbMax        = dbSizeLimit.lo;
	cLimit.grow         = dg.current(); 
	cLimit.reduce       = ds.current() + dbRedInit; 
	cLimit.global       = lim.conflicts;
	cLimit.restart      = UINT64_MAX;
	uint64& rsLimit     = p.restart.local() ? sLimit.local : cLimit.restart;
	uint64 nRestart     = 0;
	rsLimit             = rs.current();
	if (p.restart.dynamic()) {
		s.stats.enableQueue(rs.base);
		s.stats.queue->reset();
		sLimit.xLbd = (float)rs.grow;
		rsLimit     = nextUp;
	}
	EventType progress(s, SolvePathEvent::event_restart, 0, 0);
	while (result == value_free && cLimit.global) {
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_testcancel();
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
		uint64 minLimit = cLimit.min(); assert(minLimit);
		sLimit.learnts  = (uint32)dbSizeLimit.clamp(dbMax + (db.pinned*p.reduce.strategy.noGlue));
		sLimit.conflicts= minLimit;
		progress.cLimit = std::min(minLimit, sLimit.local);
		progress.lLimit = sLimit.learnts;
		if (progress.evType) { s.sharedContext()->reportProgress(progress); }
		result     = s.search(sLimit, p.randomProbability());
		minLimit   = (minLimit - sLimit.conflicts); // number of actual conflicts
		cLimit.update(minLimit);
		if (result == value_true && backtrackFromModel(s)) {
			result   = value_free; // continue enumeration
			if (p.restart.resetOnModel()) {
				rs.reset();
			}
			// After the first solution was found, we allow further restarts only if this
			// is compatible with the enumerator used. 
			cLimit.restart  = std::max(cLimit.restart, rs.current());
			cLimit.reduce   = ds.current() + dbRedInit;
			cLimit.grow     = std::max(cLimit.grow, uint64(1));
			progress.evType = SolvePathEvent::event_model;
			if (!p.restart.bounded() && s.backtrackLevel() > s.rootLevel()) {
				sLimit        = SearchLimits();
				cLimit.restart= UINT64_MAX;
			}
		}
		else if (result == value_free){  // limit reached
			minLimit        = 0;
			progress.evType = SolvePathEvent::event_none;
			if (rsLimit == 0 || sLimit.dynamicRestart(s.stats)) {
				// restart reached - do restart
				++s.stats.restarts; ++nRestart;
				if (p.restart.counterRestart && (nRestart % p.restart.counterRestart) == 0 ) {
					inDegree.clear();
					s.heuristic()->bump(s, inDegree, p.restart.counterBump / (double)s.inDegree(inDegree));
				}
				if (p.restart.dynamic()) {
					uint64 num = s.stats.restarts  - lastR;
					uint64 cfl = s.stats.conflicts - lastC;
					if (cfl   >=  nextUp) {
						float& lim = sLimit.xLbd != 0.0f ? sLimit.xLbd : sLimit.xCfl;
						double avg = cfl / double(num);
						bool   sx  = (s.stats.analyzed - s.stats.cflLast) >= nextUp;
						bool   tog = rs.len != 0 && (s.stats.avgLbd() > rs.len) == (lim == sLimit.xLbd);
						lastR      = s.stats.restarts;
						lastC      = s.stats.conflicts;
						if      (avg >= 16000.0) { lim += 0.1f;  nextUp = 16000; }
						else if (sx)             { lim += 0.05f; nextUp = std::max(uint64(16000), nextUp-10000); }
						else if (avg >= 4000.0)  { lim += 0.05f; }
						else if (avg >= 1000.0)  { nextUp += 10000u; }
						else if (lim > rs.grow)  { lim -= 0.05f; }
						if (tog) {
							lim    = (float)rs.grow;
							nextUp = 16000;
							std::swap(sLimit.xLbd, sLimit.xCfl);
						}
					}
					rsLimit  = nextUp;;
					minLimit = s.stats.queue->samples;
					s.stats.queue->reset();
				}
				s.undoUntil(0);
				if (rsLimit == 0)              { rsLimit = rs.next(); }
				if (!minLimit)                 { minLimit= rs.current(); }
				if (p.reduce.strategy.fRestart){ db      = s.reduceLearnts(p.reduce.fRestart(), p.reduce.strategy); }
				if (nRestart == shuffle)       { shuffle+= p.restart.shuffleNext; s.shuffleOnNextSimplify();}
				if (nRestart == lim.restarts)  { break; }
				s.stats.cflLast = s.stats.analyzed;
				progress.evType = SolvePathEvent::event_restart;
			}	
			if (cLimit.reduce == 0 || s.learntLimit(sLimit)) {
				// reduction reached - remove learnt constraints
				db              = s.reduceLearnts(p.reduce.fReduce(), p.reduce.strategy);
				cLimit.reduce   = dbRedInit + (cLimit.reduce == 0 ? ds.next() : ds.current());
				progress.evType = std::max(progress.evType, SolvePathEvent::event_deletion);
				if (s.learntLimit(sLimit) || db.pinned >= dbMax) { 
					ReduceStrategy t; t.algo = 2; t.score = 2; t.glue = 0;
					db.pinned /= 2;
					db.size    = s.reduceLearnts(0.5f, t).size;
					if (db.size >= sLimit.learnts) { dbMax = dbSizeLimit.clamp(dbMax + std::max(100.0, s.numLearntConstraints()/10.0)); }
				}
			}
			if (cLimit.grow == 0 || (dg.defaulted() && progress.evType == SolvePathEvent::event_restart)) {
				// grow sched reached - increase max db size
				if (cLimit.grow == 0)                             { cLimit.grow = dg.next(); minLimit = cLimit.grow; }
				if ((s.numLearntConstraints() + minLimit) > dbMax){ dbMax  *= p.reduce.fGrow; progress.evType = std::max(progress.evType, SolvePathEvent::event_grow); }
				if (dbMax > dbSizeLimit.hi)                       { dbMax   = dbSizeLimit.hi; cLimit.grow = UINT64_MAX; dg = ScheduleStrategy::none(); }
			}
		}
	}
	s.stats.cflLast = s.stats.analyzed - s.stats.cflLast;
	if (lim.conflicts != UINT64_MAX) { lim.conflicts = cLimit.global; }
	if (lim.restarts  != UINT64_MAX) { lim.restarts -= nRestart;   }
	return result;
}