Exemple #1
0
// dump any new clause
void
dumpnewclause(const Clause &cl1, const Clause &cl2, const Clause &newcl)
{
	cout << "((p1,l1), (p2,l2)) = ((";
	cout << cl1.getNumber() << "," << cl1.getTotalMembers() << "),(";
	cout << cl2.getNumber() << "," << cl2.getTotalMembers() << ")) = ";
	cout << newcl << endl;
	return;
}
Exemple #2
0
int
subsumes(const Clause &cl1, const Clause &cl2, Substitutions &s)
{
	// clear substitution list
	s.clear();

	// make sure the clauses are not the same one.
	// this check works since the index in literals
	// are never reassigned.
	//
	if (cl1 == cl2)
	{
		return(NOMATCH);
	}

	// check that every class in clause 1 exists in clause 2. 
	if (subset(cl1, cl2) != OK)
	{
		return(NOMATCH);
	}

	// now start the actual subsumption algorithm.
	Substitutions subs;
	Clause clause2(cl2);
	if (groundSubstitutions(clause2, subs) != OK)
	{
		ERROR("groundSubstitutions failed.", errno);
		return(NOTOK);
	}

	// convert second clause to a ground clause
	if (subs.applyTo(clause2) != OK)
	{
		ERROR("applyTo failed.", errno);
		return(NOTOK);
	}

	// copy clauses to arrays
	Array<Literal> clarray1(1, cl1.getTotalMembers());
	ClauseIterator cl1Iter(cl1);
	for (int i=1; !cl1Iter.done(); i++, cl1Iter++)
	{
		clarray1[i] = cl1Iter();
	}
	Array<Literal> clarray2(1, cl2.getTotalMembers());
	ClauseIterator cl2Iter(clause2);
#ifdef SC42
	for (i=1; !cl2Iter.done(); i++, cl2Iter++)
#else
	for (int i=1; !cl2Iter.done(); i++, cl2Iter++)
#endif
	{
		clarray2[i] = cl2Iter();
	}

	// use Stillman's algorithm
	statistics[AttemptedStillmanSubsumptionTests] += 1;
	totalstatistics[TotalAttemptedStillmanSubsumptionTests] += 1;
	int status = ST(clarray1, clarray2, 1, 1, s);
	if (status == OK && verbose)
	{
		cout << endl;
		cout << "clause1 subsumes clause2 ..." << endl;
		cout << "clause1: " << cl1 << endl;
		cout << "clause2: " << cl2 << endl;
	}
	return(status);
}
Exemple #3
0
// check if a clause is a subset of another. only compares 
// equivalent sets.
//
int
subset(const Clause &cl1, const Clause &cl2)
{
	// verify smaller clause subsumes larger clause
	if (cl1.getTotalMembers() > cl2.getTotalMembers())
	{
		return(NOMATCH);
	}

	// certain types of clauses cannot subsume others,
	// p = positive, n = negative, m = mixed.
	// 
	//	clause 1	clause 2	can 
	//	type		type		subsume?
	//	-------------------------------------------
	//	P		P		yes
	//	P		N		no
	//	P		M		yes
	//	N		P		no
	//	N		N		yes
	//	N		M		yes
	//	M		P		yes
	//	M		N		yes
	//	M		M		yes
	//
	if (((cl1.getType() == Clause::Positive) &&
	    (cl2.getType() == Clause::Negative)) ||
	    ((cl1.getType() == Clause::Negative) &&
	    (cl2.getType() == Clause::Positive)))
	{
		return(NOMATCH);
	}

	// start checking every literal equivalent class. every equivalent 
	// class in clause 1 should be in clause2. absolute equality
	// is checked with unification.
	//
	ClauseIterator cl1Iter(cl1);
	ClauseIterator cl2Iter(cl2);
	for ( ; !cl1Iter.done(); cl1Iter++)
	{
		// search for literal in clause 2
		int found = 0;
		while (!cl2Iter.done() && !found)
		{
			if (cl2Iter().lt(cl1Iter()))
			{
				cl2Iter++;
			}
			else if (cl2Iter().gt(cl1Iter()))
			{
				return(NOMATCH);
			}
			else
			{
				found = 1;
			}
		}
		if (!found)
		{
			return(NOMATCH);
		}
	}

	// all done
	return(OK);
}
Exemple #4
0
// resolve two clauses, if possible.
int
resolveClauses(Array<BinaryTree_AVL<Clause> > &clausesArray, 
	Clause &cl1, Clause &cl2, int &clausesAdded, unsigned int currentDepth)
{
	// check if any of the clauses are empty
	statistics[ResolutionsAttempted] += 1;
	totalstatistics[TotalResolutionsAttempted] += 1;
	if (cl1.isEmpty() || cl2.isEmpty())
	{
		return(VALID);
	}

	// check if clauses can be resolved
	if (!cl1.getSOS() && !cl2.getSOS())
	{
		// one clause must be in the set-of-support
		return(NOMATCH);
	}
	if ((cl1.getType() == Clause::Negative && 
	     cl2.getType() == Clause::Negative) ||
	    (cl1.getType() == Clause::Positive && 
	     cl2.getType() == Clause::Positive))
	{
		// two positive clauses or two negative clauses
		// can not be resolved.
		return(NOMATCH);
	}

	// attempt to resolve two clauses. use A-ordering resolution,
	// try to resolve maximal literals.
	//
	Literal maxlit1;
	if (cl1.getMaximalLiteral(maxlit1) != OK)
	{
		ERROR("getMaximalLiteral failed.", errno);
		return(NOTOK);
	}
	Literal maxlit2;
	if (cl2.getMaximalLiteral(maxlit2) != OK)
	{
		ERROR("getMaximalLiteral failed.", errno);
		return(NOTOK);
	}
	if ((cl1.getTotalMembers() > maxliterals) ||
	    (cl2.getTotalMembers() > maxliterals))
	{
		statistics[MaximumLiteralsClausesRejected] += 1;
		totalstatistics[TotalMaximumLiteralsClausesRejected] += 1;
		return(NOMATCH);
	}
	if (maxlit1.unify_ne(~maxlit2))
	{
		return(NOMATCH);
	}

	// factor clauses
	Substitutions subs;
	if (factor(maxlit1, cl1, subs) == NOTOK)
	{
		ERROR("factor failed.", errno);
		return(NOTOK);
	}
	if (factor(maxlit2, cl2, subs) == NOTOK)
	{
		ERROR("factor failed.", errno);
		return(NOTOK);
	}

	// attempt to unify the clauses
	subs.clear();
	int status = unify(maxlit1, ~maxlit2, subs);
	switch (status)
	{
	case OK:
		if (verbose)
		{
			cout << endl;
			Literal ml1(maxlit1);
			cout << "max literal 1 (before subs): " << ml1 << endl;
			subs.applyTo(ml1);
			cout << "max literal 1 (after subs): " << ml1 << endl;
			Literal ml2(maxlit2);
			cout << "max literal 2 (before subs): " << ml2 << endl;
			subs.applyTo(ml2);
			cout << "max literal 2 (after subs): " << ml2 << endl;
			MustBeTrue(equal(ml1, ~ml2));
		}
		break;
	case NOMATCH:
		return(NOMATCH);
	default:
		ERROR("unify failed.", errno);
		return(status);
	}

	// can resolve, remove literals from clauses
	Clause newcl1(cl1);
	if (newcl1.remove(maxlit1) != OK)
	{
		ERROR("remove failed.", errno);
		return(NOTOK);
	}
	if (subs.applyTo(newcl1) != OK)
	{
		ERROR("applyTo failed.", errno);
		return(NOTOK);
	}
	Clause newcl2(cl2);
	if (newcl2.remove(maxlit2) != OK)
	{
		ERROR("remove failed.", errno);
		return(NOTOK);
	}
	if (subs.applyTo(newcl2) != OK)
	{
		ERROR("applyTo failed.", errno);
		return(NOTOK);
	}

	// store new clause and update flag
	Clause newcl = newcl1+newcl2;
	if (newcl.renameVariables() != OK)
	{
		ERROR("renameVariables failed.", errno);
		return(NOTOK);
	}
	newcl.setDepth(currentDepth+1);
	newcl.setNumber(nextClause++);
	if (clausesArray[currentDepth+1].insert(newcl) != OK)
	{
		ERROR("insert failed.", errno);
		return(NOTOK);
	}
	clausesAdded = 1;

	// indicate the clauses that were resolved
	statistics[ClausesGenerated] += 1;
	totalstatistics[TotalClausesGenerated] += 1;
	dumpnewclause(cl1, cl2, newcl);

	// check if we found an empty clause
	if (newcl.isEmpty())
	{
		return(VALID);
	}
	else
	{
		return(OK);
	}
}