Exemple #1
0
Coord Solver::advise(BaseField &field, float &probability)
{
    Coord point;
    probability = 1;
    delete d->facts;
    d->facts = new AdviseFast::FactSet(&field);
    delete d->rules;
    d->rules = new AdviseFast::RuleSet(d->facts);

    if( AdviseFast::adviseFast(&point, d->facts, d->rules) ) return point;

    CoordSet surePoints;
    AdviseFull::ProbabilityMap probabilities;
    AdviseFull::adviseFull(d->facts, &surePoints, &probabilities);

    // return one of the sure point (random choice to limit the tropism) [NH]
    if( !surePoints.empty() ) {
        KRandomSequence r;
        uint k = r.getLong(surePoints.size());
        CoordSet::iterator it = surePoints.begin();
        for (uint i=0; i<k; i++) ++it;
        return *it;
    }

    // Just a minimum probability logic here
    if( !probabilities.empty() ) {
        probability = probabilities.begin()->first;
        return probabilities.begin()->second;
    }

    // Otherwise the Field is already solved :)
    return Coord(-1,-1);
}
Exemple #2
0
void AdviseFast::FactSet::addFact(
	Coord const &point,
	Fact const &fact)
{
	if(this->count(point)) this->deleteFact(point);

	Fact &f = ((*this)[point] = fact);


	// Remove marked points
	CoordSet marked;
	set_intersection(
		f.pointSet.begin(),
		f.pointSet.end(),
		_marked.begin(),
		_marked.end(),
		inserter(marked, marked.begin()));

	CoordSet::iterator i;
	for(i=marked.begin(); i!=marked.end(); ++i)
		f.pointSet.erase(*i);
	f.mines -= marked.size();

	// Don't insert empty fact
	if(f.pointSet.empty()) { this->erase(point); return;}

	for(i=f.pointSet.begin(); i!=f.pointSet.end(); ++i)
		_containingFacts[*i].insert(point);
}
Exemple #3
0
void AdviseFull::EquationSet::normalize()
{
	short i=0;
	set<short> empty;
	for(i=0; i<_maxPointSet; ++i){
		if(!_pointSets.count(i)) continue;
		if(_pointSets[i].empty()){
			this->substitute(i, empty);
			continue;
		}
		for(short j=i+1;j<_maxPointSet; ++j){
			if(!_pointSets.count(j)) continue;
			if(_pointSets[j].empty()){
				this->substitute(j, empty);
				continue;
			}

			CoordSet intersect;
			set_intersection(
				_pointSets[i].begin(),
				_pointSets[i].end(),
				_pointSets[j].begin(),
				_pointSets[j].end(),
				inserter(intersect, intersect.begin()));
			if(intersect.empty()) continue;

			CoordSet _i, _j;
			set_difference(
				_pointSets[i].begin(),
				_pointSets[i].end(),
				_pointSets[j].begin(),
				_pointSets[j].end(),
				inserter(_i, _i.begin()));
			set_difference(
				_pointSets[j].begin(),
				_pointSets[j].end(),
				_pointSets[i].begin(),
				_pointSets[i].end(),
				inserter(_j, _j.begin()));

			set<short> _ip, _jp;
			_ip.insert(_maxPointSet);
			_jp.insert(_maxPointSet);
			_pointSets[_maxPointSet++] = intersect;
			_ip.insert(_maxPointSet);
			_pointSets[_maxPointSet++] = _i;
			_jp.insert(_maxPointSet);
			_pointSets[_maxPointSet++] = _j;

			this->substitute(i, _ip);
			this->substitute(j, _jp);
			break;
		}
	}
}
Exemple #4
0
bool Solver::solveStep()
{
    if ( _field->isSolved() ) {
        emit solvingDone(true);
        return true;
    }

    d->rules->solve();

#ifdef DEBUG
    PRINT_ELAPSED("fast rules")
#endif

    if( _field->isSolved() ) {
        emit solvingDone(true);
        return true;
    }

    CoordSet surePoints;
    AdviseFull::ProbabilityMap probabilities;
    AdviseFull::adviseFull(d->facts, &surePoints, &probabilities);

#ifdef DEBUG
    PRINT_ELAPSED("full rules")
#endif

    if(!surePoints.empty()) {
        CoordSet::iterator i;
        for(i=surePoints.begin(); i!=surePoints.end(); ++i) {
            bool b = d->rules->reveal(*i);
            assert(b);
        }
    } else if ( !_noGuess ) {
#ifdef DEBUG
        cout << "Applying heuristics!" << endl;
        cout << *_field << endl;
#endif
        // Minimum probability logic
        assert(!probabilities.empty());
#ifdef DEBUG
        AdviseFull::ProbabilityMap::iterator i=probabilities.begin();
        cout << "Probability is " << i->first << endl;
#endif
        bool success = d->rules->reveal(probabilities.begin()->second);
        if ( !success ) {
            emit solvingDone(false);
            return false;
        }
    }

    if (_inOneStep) return solveStep();
    else QTimer::singleShot(0, this, SLOT(solveStep()));
    return false;
}
Exemple #5
0
bool AdviseFast::FactSet::reveal(
	Coord point,
	CoordSet *affectedFacts)
{
	// Tolerate :)
	if( !_field->isCovered(point) ) return true; // :)

	CoordList tmp;
	if(_field->doReveal(point, &tmp, 0) == false)
		// Blew up :(
		return false;

    CoordSet autorevealed;
    for (CoordList::const_iterator it = tmp.begin(); it!=tmp.end(); ++it)
        autorevealed.insert(*it);
	autorevealed.insert(point);
	affectedFacts->insert(autorevealed.begin(), autorevealed.end());

	CoordSet::const_iterator i;
	for(i=autorevealed.begin(); i!=autorevealed.end(); ++i)
	{
		// I still think that each poing will belong to
		// at least one fact, but don't want to waste time
		// proving it :)
		if(_containingFacts.count(*i)){
			CoordSet const &affF = _containingFacts[*i];
			affectedFacts->insert(
				affF.begin(), affF.end());
			for(CoordSet::const_iterator j=affF.begin();
				j!=affF.end();
				++j)
			{
				(*this)[*j].pointSet.erase(*i);
				if((*this)[*j].pointSet.empty())
					this->erase(*j);
			}
			_containingFacts.erase(*i);
		}

		Fact f; retrieveFact(*i, &f);
		this->addFact(*i, f);
	}

	return true;
}
Exemple #6
0
void AdviseFull::adviseFull(
	AdviseFast::FactSet *facts,
	CoordSet *surePoints,
	ProbabilityMap *probabilities)
{
	EquationSet eqs(*facts);

#if defined(DEBUG) && DEBUG >= 2
	eqs.prettyprint();
#endif

	eqs.normalize();
#if defined(DEBUG) && DEBUG >= 2
	eqs.prettyprint();
#endif

	list<EquationSet> eqss;
	eqs.separate(&eqss);
#ifdef DEBUG
	{list<EquationSet>::iterator i;
		for(i=eqss.begin(); i!=eqss.end(); ++i)
			i->prettyprint();
	}
#endif


	// OK, uneffective, but simple :(
	surePoints->clear();
	probabilities->clear();

	// Get a fraction;
	float fraction;
	{ BaseField const *f = facts->getField();
		fraction = ((float)f->nbMines()) / (f->width() * f->height());
	}

	/* From now on the first equation set on the list includes
	* the equation corresponding to "total" fact.  This is the
	* first equation on the set.
	*
	* Give it a special treatment ;) */
	if(!eqss.empty()) do {
		EquationSet prime = eqss.front();
		EquationSet::Equation total = prime._equations.front();
		prime._equations.pop_front();

		list<EquationSet> prime_sep;
		prime.separate(&prime_sep);

		// Find a pool
		list<EquationSet::Equation>::iterator i = prime._equations.begin();
		while(!prime._equations.empty()){
			set<short>::iterator j;
			for(	j = i->pointSets.begin();
				j != i->pointSets.end();
				++j)
				prime._pointSets.erase(*j);
			i = prime._equations.erase(i);
		}

		assert(prime._pointSets.size() <= 1);
		if(prime._pointSets.size() == 0) break;

		short pool = prime._pointSets.begin()->first;
		CoordSet const &p = prime._pointSets[pool];
#ifdef DEBUG
		cout << "Prime equation set:" << endl <<
			"	separated into " << prime_sep.size() << endl <<
			"	pool size is " << p.size() << endl;
#endif
		// Euristic
		// if( prime_sep.size () > 6 && p.size() >= prime_sep.size() * 10){
		if(p.size() < (prime_sep.size()+1) * 10)
			// No special treatment!!
			break;


		// Actually, just substitute prime (!!!)
		eqss.pop_front();
		eqss.insert(eqss.begin(),
			prime_sep.begin(),
			prime_sep.end());

		prime._equations.clear();
		EquationSet::Equation o;
		o.pointSets.insert(pool);
        // #### is the convertion right ? (NH)
		o.mines = (ushort)(fraction * p.size());
		// A precaution
		if(o.mines == 0) o.mines = 1; // ;)

		prime._equations.push_front(o);
		eqss.push_front(prime);


#ifdef DEBUG
			cout << "Specially treated:" << endl;
	{
		list<EquationSet>::iterator i;
		for(i=eqss.begin(); i!=eqss.end(); ++i)
			i->prettyprint();
	}
#endif
	} while (false);

	list<EquationSet>::const_iterator i;
	for(i=eqss.begin(); i!=eqss.end(); ++i){
		CoordSet sp; ProbabilityMap pb;

		list<EquationSet::Solution> solutions;
		map<short, CoordSet> const &m = i->solve(&solutions);
#ifdef DEBUG
		printf("Got solutions.\n");
#if defined(DEBUG) && DEBUG >= 2
		{ list<EquationSet::Solution>::iterator i;
			for(	i = solutions.begin();
				i != solutions.end();
				++i)
			{
				EquationSet::Solution::iterator j;
				for(j=i->begin(); j!=i->end(); ++j)
					printf("%d:\t%d\n",
						j->first, j->second);
				printf("\n");
			}
		}
#endif
#endif

		//bool sure =
        AdviseFull::surePoints(m, solutions, &sp);
		surePoints->insert(sp.begin(), sp.end());

		getProbabilities(m, solutions, &pb, fraction);
		probabilities->insert(pb.begin(), pb.end());
	}

	// That's it
	return;
}