2012-10-22 23:01:13 +01:00
|
|
|
|
#include <fstream>
|
|
|
|
|
|
|
|
|
|
#include "LiftedCircuit.h"
|
|
|
|
|
|
|
|
|
|
|
2012-10-25 12:22:52 +01:00
|
|
|
|
double
|
|
|
|
|
OrNode::weight (void) const
|
|
|
|
|
{
|
|
|
|
|
double lw = leftBranch_->weight();
|
|
|
|
|
double rw = rightBranch_->weight();
|
|
|
|
|
return Globals::logDomain ? Util::logSum (lw, rw) : lw + rw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double
|
|
|
|
|
AndNode::weight (void) const
|
|
|
|
|
{
|
|
|
|
|
double lw = leftBranch_->weight();
|
|
|
|
|
double rw = rightBranch_->weight();
|
|
|
|
|
return Globals::logDomain ? lw + rw : lw * rw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-11-04 18:02:40 +00:00
|
|
|
|
stack<pair<unsigned, unsigned>> SetOrNode::nrGrsStack;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-10-27 00:13:11 +01:00
|
|
|
|
double
|
|
|
|
|
SetOrNode::weight (void) const
|
|
|
|
|
{
|
2012-11-01 22:34:28 +00:00
|
|
|
|
double weightSum = LogAware::addIdenty();
|
|
|
|
|
for (unsigned i = 0; i < nrGroundings_ + 1; i++) {
|
2012-11-06 14:15:21 +00:00
|
|
|
|
nrGrsStack.push (make_pair (nrGroundings_ - i, i));
|
2012-11-01 22:34:28 +00:00
|
|
|
|
if (Globals::logDomain) {
|
|
|
|
|
double w = std::log (Util::nrCombinations (nrGroundings_, i));
|
|
|
|
|
weightSum = Util::logSum (weightSum, w + follow_->weight());
|
|
|
|
|
} else {
|
2012-11-06 14:15:21 +00:00
|
|
|
|
cout << endl;
|
|
|
|
|
cout << "nr groundings = " << nrGroundings_ << endl;
|
|
|
|
|
cout << "nr positives = " << nrPositives() << endl;
|
|
|
|
|
cout << "nr negatives = " << nrNegatives() << endl;
|
|
|
|
|
cout << "i = " << i << endl;
|
|
|
|
|
cout << "nr combos = " << Util::nrCombinations (nrGroundings_, i) << endl;
|
|
|
|
|
double w = follow_->weight();
|
|
|
|
|
cout << "weight = " << w << endl;
|
|
|
|
|
weightSum += Util::nrCombinations (nrGroundings_, i) * w;
|
2012-11-01 22:34:28 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return weightSum;
|
2012-10-27 00:13:11 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double
|
|
|
|
|
SetAndNode::weight (void) const
|
|
|
|
|
{
|
2012-10-29 15:39:56 +00:00
|
|
|
|
double w = follow_->weight();
|
2012-10-27 00:13:11 +01:00
|
|
|
|
return Globals::logDomain
|
2012-10-30 00:21:10 +00:00
|
|
|
|
? w * nrGroundings_
|
|
|
|
|
: std::pow (w, nrGroundings_);
|
2012-10-27 00:13:11 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-10-30 01:51:10 +00:00
|
|
|
|
double
|
|
|
|
|
IncExcNode::weight (void) const
|
|
|
|
|
{
|
|
|
|
|
double w = 0.0;
|
|
|
|
|
if (Globals::logDomain) {
|
|
|
|
|
w = Util::logSum (plus1Branch_->weight(), plus2Branch_->weight());
|
|
|
|
|
w = std::log (std::exp (w) - std::exp (minusBranch_->weight()));
|
|
|
|
|
} else {
|
|
|
|
|
w = plus1Branch_->weight() + plus2Branch_->weight();
|
|
|
|
|
w -= minusBranch_->weight();
|
|
|
|
|
}
|
|
|
|
|
return w;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-10-25 12:22:52 +01:00
|
|
|
|
double
|
|
|
|
|
LeafNode::weight (void) const
|
|
|
|
|
{
|
|
|
|
|
assert (clauses().size() == 1);
|
|
|
|
|
assert (clauses()[0].isUnit());
|
|
|
|
|
Clause c = clauses()[0];
|
2012-11-06 14:15:21 +00:00
|
|
|
|
double weight = c.literals()[0].isPositive()
|
|
|
|
|
? lwcnf_.posWeight (c.literals().front().lid())
|
|
|
|
|
: lwcnf_.negWeight (c.literals().front().lid());
|
2012-11-01 22:34:28 +00:00
|
|
|
|
LogVarSet lvs = c.constr().logVarSet();
|
|
|
|
|
lvs -= c.ipgLogVars();
|
2012-11-07 15:28:33 +00:00
|
|
|
|
lvs -= c.posCountedLogVars();
|
|
|
|
|
lvs -= c.negCountedLogVars();
|
2012-10-29 15:39:56 +00:00
|
|
|
|
unsigned nrGroundings = 1;
|
|
|
|
|
if (lvs.empty() == false) {
|
|
|
|
|
ConstraintTree ct = c.constr();
|
|
|
|
|
ct.project (lvs);
|
|
|
|
|
nrGroundings = ct.size();
|
|
|
|
|
}
|
2012-11-06 15:56:52 +00:00
|
|
|
|
// cout << "calc weight for " << clauses().front() << endl;
|
2012-11-07 15:28:33 +00:00
|
|
|
|
if (c.posCountedLogVars().empty() == false) {
|
2012-11-06 15:56:52 +00:00
|
|
|
|
// cout << " -> nr pos = " << SetOrNode::nrPositives() << endl;
|
2012-11-06 14:15:21 +00:00
|
|
|
|
nrGroundings *= std::pow (SetOrNode::nrPositives(),
|
2012-11-07 15:28:33 +00:00
|
|
|
|
c.nrPosCountedLogVars());
|
2012-11-06 14:15:21 +00:00
|
|
|
|
}
|
2012-11-07 15:28:33 +00:00
|
|
|
|
if (c.negCountedLogVars().empty() == false) {
|
2012-11-06 15:56:52 +00:00
|
|
|
|
//cout << " -> nr neg = " << SetOrNode::nrNegatives() << endl;
|
2012-11-06 14:15:21 +00:00
|
|
|
|
nrGroundings *= std::pow (SetOrNode::nrNegatives(),
|
2012-11-07 15:28:33 +00:00
|
|
|
|
c.nrNegCountedLogVars());
|
2012-11-06 14:15:21 +00:00
|
|
|
|
}
|
2012-11-06 15:56:52 +00:00
|
|
|
|
// cout << " -> nr groundings = " << nrGroundings << endl;
|
|
|
|
|
// cout << " -> lit weight = " << weight << endl;
|
|
|
|
|
// cout << " -> ret weight = " << std::pow (weight, nrGroundings) << endl;
|
2012-10-25 12:22:52 +01:00
|
|
|
|
return Globals::logDomain
|
|
|
|
|
? weight * nrGroundings
|
|
|
|
|
: std::pow (weight, nrGroundings);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double
|
|
|
|
|
SmoothNode::weight (void) const
|
|
|
|
|
{
|
|
|
|
|
Clauses cs = clauses();
|
|
|
|
|
double totalWeight = LogAware::multIdenty();
|
|
|
|
|
for (size_t i = 0; i < cs.size(); i++) {
|
2012-11-06 14:15:21 +00:00
|
|
|
|
double posWeight = lwcnf_.posWeight (cs[i].literals()[0].lid());
|
|
|
|
|
double negWeight = lwcnf_.negWeight (cs[i].literals()[0].lid());
|
|
|
|
|
LogVarSet lvs = cs[i].constr().logVarSet();
|
|
|
|
|
lvs -= cs[i].ipgLogVars();
|
2012-11-07 15:28:33 +00:00
|
|
|
|
lvs -= cs[i].posCountedLogVars();
|
|
|
|
|
lvs -= cs[i].negCountedLogVars();
|
2012-11-06 14:15:21 +00:00
|
|
|
|
unsigned nrGroundings = 1;
|
|
|
|
|
if (lvs.empty() == false) {
|
|
|
|
|
ConstraintTree ct = cs[i].constr();
|
|
|
|
|
ct.project (lvs);
|
|
|
|
|
nrGroundings = ct.size();
|
|
|
|
|
}
|
2012-11-06 15:56:52 +00:00
|
|
|
|
// cout << "calc smooth weight for " << cs[i] << endl;
|
2012-11-07 15:28:33 +00:00
|
|
|
|
if (cs[i].posCountedLogVars().empty() == false) {
|
2012-11-06 15:56:52 +00:00
|
|
|
|
// cout << " -> nr pos = " << SetOrNode::nrPositives() << endl;
|
2012-11-06 14:15:21 +00:00
|
|
|
|
nrGroundings *= std::pow (SetOrNode::nrPositives(),
|
2012-11-07 15:28:33 +00:00
|
|
|
|
cs[i].nrPosCountedLogVars());
|
2012-11-06 14:15:21 +00:00
|
|
|
|
}
|
2012-11-07 15:28:33 +00:00
|
|
|
|
if (cs[i].negCountedLogVars().empty() == false) {
|
2012-11-06 15:56:52 +00:00
|
|
|
|
// cout << " -> nr neg = " << SetOrNode::nrNegatives() << endl;
|
2012-11-06 14:15:21 +00:00
|
|
|
|
nrGroundings *= std::pow (SetOrNode::nrNegatives(),
|
2012-11-07 15:28:33 +00:00
|
|
|
|
cs[i].nrNegCountedLogVars());
|
2012-11-06 14:15:21 +00:00
|
|
|
|
}
|
2012-11-06 15:56:52 +00:00
|
|
|
|
// cout << " -> pos+neg = " << posWeight + negWeight << endl;
|
|
|
|
|
// cout << " -> nrgroun = " << nrGroundings << endl;
|
2012-10-25 12:22:52 +01:00
|
|
|
|
if (Globals::logDomain) {
|
2012-11-06 15:56:52 +00:00
|
|
|
|
totalWeight += (Util::logSum (posWeight, negWeight)
|
|
|
|
|
* std::log (nrGroundings));
|
2012-10-25 12:22:52 +01:00
|
|
|
|
} else {
|
|
|
|
|
totalWeight *= std::pow (posWeight + negWeight, nrGroundings);
|
|
|
|
|
}
|
2012-11-06 15:56:52 +00:00
|
|
|
|
// cout << " -> smooth weight = " << totalWeight << endl;
|
2012-10-25 12:22:52 +01:00
|
|
|
|
}
|
|
|
|
|
return totalWeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double
|
|
|
|
|
TrueNode::weight (void) const
|
|
|
|
|
{
|
|
|
|
|
return LogAware::multIdenty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-10-30 12:41:00 +00:00
|
|
|
|
double
|
|
|
|
|
CompilationFailedNode::weight (void) const
|
|
|
|
|
{
|
|
|
|
|
// we should not perform model counting
|
|
|
|
|
// in compilation failed nodes
|
2012-10-31 23:43:39 +00:00
|
|
|
|
// abort();
|
2012-10-30 12:41:00 +00:00
|
|
|
|
return 0.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-10-22 23:01:13 +01:00
|
|
|
|
LiftedCircuit::LiftedCircuit (const LiftedWCNF* lwcnf)
|
|
|
|
|
: lwcnf_(lwcnf)
|
|
|
|
|
{
|
|
|
|
|
root_ = 0;
|
2012-10-31 23:43:39 +00:00
|
|
|
|
Clauses clauses = lwcnf->clauses();
|
|
|
|
|
compile (&root_, clauses);
|
2012-10-24 21:22:49 +01:00
|
|
|
|
exportToGraphViz("circuit.dot");
|
2012-11-09 18:42:21 +00:00
|
|
|
|
smoothCircuit (root_);
|
2012-10-31 23:43:39 +00:00
|
|
|
|
exportToGraphViz("circuit.smooth.dot");
|
2012-11-06 14:15:21 +00:00
|
|
|
|
cout << "--------------------------------------------------" << endl;
|
|
|
|
|
cout << "--------------------------------------------------" << endl;
|
2012-10-25 12:22:52 +01:00
|
|
|
|
cout << "WEIGHTED MODEL COUNT = " << getWeightedModelCount() << endl;
|
2012-10-24 21:22:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-10-25 12:22:52 +01:00
|
|
|
|
double
|
|
|
|
|
LiftedCircuit::getWeightedModelCount (void) const
|
|
|
|
|
{
|
|
|
|
|
return root_->weight();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-10-22 23:01:13 +01:00
|
|
|
|
void
|
2012-10-24 21:22:49 +01:00
|
|
|
|
LiftedCircuit::exportToGraphViz (const char* fileName)
|
2012-10-22 23:01:13 +01:00
|
|
|
|
{
|
|
|
|
|
ofstream out (fileName);
|
|
|
|
|
if (!out.is_open()) {
|
|
|
|
|
cerr << "error: cannot open file to write at " ;
|
|
|
|
|
cerr << "BayesBallGraph::exportToDotFile()" << endl;
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
out << "digraph {" << endl;
|
|
|
|
|
out << "ranksep=1" << endl;
|
2012-10-24 21:22:49 +01:00
|
|
|
|
exportToGraphViz (root_, out);
|
2012-10-22 23:01:13 +01:00
|
|
|
|
out << "}" << endl;
|
|
|
|
|
out.close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
LiftedCircuit::compile (
|
|
|
|
|
CircuitNode** follow,
|
2012-10-27 00:13:11 +01:00
|
|
|
|
Clauses& clauses)
|
2012-10-22 23:01:13 +01:00
|
|
|
|
{
|
|
|
|
|
if (clauses.empty()) {
|
|
|
|
|
*follow = new TrueNode ();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (clauses.size() == 1 && clauses[0].isUnit()) {
|
2012-11-06 14:15:21 +00:00
|
|
|
|
*follow = new LeafNode (clauses[0], *lwcnf_);
|
2012-10-22 23:01:13 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tryUnitPropagation (follow, clauses)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-11-07 18:42:11 +00:00
|
|
|
|
|
2012-10-22 23:01:13 +01:00
|
|
|
|
if (tryIndependence (follow, clauses)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-11-07 18:42:11 +00:00
|
|
|
|
|
2012-10-24 21:22:49 +01:00
|
|
|
|
if (tryShannonDecomp (follow, clauses)) {
|
2012-10-22 23:01:13 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
2012-11-07 18:42:11 +00:00
|
|
|
|
|
2012-10-30 00:21:10 +00:00
|
|
|
|
if (tryInclusionExclusion (follow, clauses)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-11-07 18:42:11 +00:00
|
|
|
|
|
2012-11-06 23:35:14 +00:00
|
|
|
|
if (tryIndepPartialGrounding (follow, clauses)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-11-07 18:42:11 +00:00
|
|
|
|
|
2012-10-31 23:43:39 +00:00
|
|
|
|
if (tryAtomCounting (follow, clauses)) {
|
2012-10-27 00:13:11 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
2012-11-07 18:42:11 +00:00
|
|
|
|
|
2012-10-27 00:13:11 +01:00
|
|
|
|
if (tryGrounding (follow, clauses)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-11-07 18:42:11 +00:00
|
|
|
|
|
2012-10-27 00:13:11 +01:00
|
|
|
|
// assert (false);
|
2012-10-30 12:41:00 +00:00
|
|
|
|
*follow = new CompilationFailedNode (clauses);
|
2012-10-31 23:43:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-10-22 23:01:13 +01:00
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
LiftedCircuit::tryUnitPropagation (
|
|
|
|
|
CircuitNode** follow,
|
2012-10-27 00:13:11 +01:00
|
|
|
|
Clauses& clauses)
|
2012-10-22 23:01:13 +01:00
|
|
|
|
{
|
2012-11-01 22:34:28 +00:00
|
|
|
|
// cout << "ALL CLAUSES:" << endl;
|
|
|
|
|
// Clause::printClauses (clauses);
|
2012-10-22 23:01:13 +01:00
|
|
|
|
for (size_t i = 0; i < clauses.size(); i++) {
|
|
|
|
|
if (clauses[i].isUnit()) {
|
2012-11-01 22:34:28 +00:00
|
|
|
|
// cout << clauses[i] << " is unit!" << endl;
|
2012-10-22 23:01:13 +01:00
|
|
|
|
Clauses newClauses;
|
|
|
|
|
for (size_t j = 0; j < clauses.size(); j++) {
|
|
|
|
|
if (i != j) {
|
|
|
|
|
LiteralId lid = clauses[i].literals()[0].lid();
|
2012-10-31 23:43:39 +00:00
|
|
|
|
LogVarTypes types = clauses[i].logVarTypes (0);
|
2012-10-22 23:01:13 +01:00
|
|
|
|
if (clauses[i].literals()[0].isPositive()) {
|
2012-10-31 23:43:39 +00:00
|
|
|
|
if (clauses[j].containsPositiveLiteral (lid, types) == false) {
|
2012-10-22 23:01:13 +01:00
|
|
|
|
Clause newClause = clauses[j];
|
2012-10-31 23:43:39 +00:00
|
|
|
|
newClause.removeNegativeLiterals (lid, types);
|
2012-10-22 23:01:13 +01:00
|
|
|
|
newClauses.push_back (newClause);
|
|
|
|
|
}
|
2012-10-27 00:13:11 +01:00
|
|
|
|
} else if (clauses[i].literals()[0].isNegative()) {
|
2012-10-31 23:43:39 +00:00
|
|
|
|
if (clauses[j].containsNegativeLiteral (lid, types) == false) {
|
2012-10-22 23:01:13 +01:00
|
|
|
|
Clause newClause = clauses[j];
|
2012-10-31 23:43:39 +00:00
|
|
|
|
newClause.removePositiveLiterals (lid, types);
|
2012-10-22 23:01:13 +01:00
|
|
|
|
newClauses.push_back (newClause);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
stringstream explanation;
|
2012-10-30 14:31:52 +00:00
|
|
|
|
explanation << " UP on" << clauses[i].literals()[0];
|
2012-10-22 23:01:13 +01:00
|
|
|
|
AndNode* andNode = new AndNode (clauses, explanation.str());
|
2012-10-27 00:13:11 +01:00
|
|
|
|
Clauses leftClauses = {clauses[i]};
|
|
|
|
|
compile (andNode->leftBranch(), leftClauses);
|
2012-10-24 21:22:49 +01:00
|
|
|
|
compile (andNode->rightBranch(), newClauses);
|
2012-10-22 23:01:13 +01:00
|
|
|
|
(*follow) = andNode;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
LiftedCircuit::tryIndependence (
|
|
|
|
|
CircuitNode** follow,
|
2012-10-27 00:13:11 +01:00
|
|
|
|
Clauses& clauses)
|
2012-10-22 23:01:13 +01:00
|
|
|
|
{
|
|
|
|
|
if (clauses.size() == 1) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2012-11-07 18:42:11 +00:00
|
|
|
|
Clauses depClauses = { clauses[0] };
|
|
|
|
|
Clauses indepClauses (clauses.begin() + 1, clauses.end());
|
|
|
|
|
bool finish = false;
|
|
|
|
|
while (finish == false) {
|
|
|
|
|
finish = true;
|
|
|
|
|
for (size_t i = 0; i < indepClauses.size(); i++) {
|
2012-11-07 23:45:43 +00:00
|
|
|
|
if (independentClause (indepClauses[i], depClauses) == false) {
|
2012-11-07 18:42:11 +00:00
|
|
|
|
depClauses.push_back (indepClauses[i]);
|
|
|
|
|
indepClauses.erase (indepClauses.begin() + i);
|
|
|
|
|
finish = false;
|
2012-10-22 23:01:13 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-11-07 18:42:11 +00:00
|
|
|
|
}
|
|
|
|
|
if (indepClauses.empty() == false) {
|
|
|
|
|
AndNode* andNode = new AndNode (clauses, " Independence");
|
|
|
|
|
compile (andNode->leftBranch(), depClauses);
|
|
|
|
|
compile (andNode->rightBranch(), indepClauses);
|
|
|
|
|
(*follow) = andNode;
|
|
|
|
|
return true;
|
2012-10-22 23:01:13 +01:00
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
2012-10-24 21:22:49 +01:00
|
|
|
|
LiftedCircuit::tryShannonDecomp (
|
2012-10-22 23:01:13 +01:00
|
|
|
|
CircuitNode** follow,
|
2012-10-27 00:13:11 +01:00
|
|
|
|
Clauses& clauses)
|
2012-10-22 23:01:13 +01:00
|
|
|
|
{
|
|
|
|
|
for (size_t i = 0; i < clauses.size(); i++) {
|
|
|
|
|
const Literals& literals = clauses[i].literals();
|
|
|
|
|
for (size_t j = 0; j < literals.size(); j++) {
|
2012-10-27 00:13:11 +01:00
|
|
|
|
if (literals[j].isGround (clauses[i].constr(),clauses[i].ipgLogVars())) {
|
2012-10-22 23:01:13 +01:00
|
|
|
|
Literal posLit (literals[j], false);
|
|
|
|
|
Literal negLit (literals[j], true);
|
2012-10-27 00:13:11 +01:00
|
|
|
|
ConstraintTree ct1 = clauses[i].constr();
|
|
|
|
|
ConstraintTree ct2 = clauses[i].constr();
|
2012-10-22 23:01:13 +01:00
|
|
|
|
Clause c1 (ct1);
|
|
|
|
|
Clause c2 (ct2);
|
|
|
|
|
c1.addLiteral (posLit);
|
|
|
|
|
c2.addLiteral (negLit);
|
|
|
|
|
Clauses leftClauses = { c1 };
|
|
|
|
|
Clauses rightClauses = { c2 };
|
|
|
|
|
leftClauses.insert (leftClauses.end(), clauses.begin(), clauses.end());
|
|
|
|
|
rightClauses.insert (rightClauses.end(), clauses.begin(), clauses.end());
|
|
|
|
|
stringstream explanation;
|
|
|
|
|
explanation << " SD on " << literals[j];
|
|
|
|
|
OrNode* orNode = new OrNode (clauses, explanation.str());
|
2012-10-24 21:22:49 +01:00
|
|
|
|
compile (orNode->leftBranch(), leftClauses);
|
|
|
|
|
compile (orNode->rightBranch(), rightClauses);
|
2012-10-30 00:21:10 +00:00
|
|
|
|
(*follow) = orNode;
|
2012-10-22 23:01:13 +01:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-10-30 00:21:10 +00:00
|
|
|
|
bool
|
|
|
|
|
LiftedCircuit::tryInclusionExclusion (
|
|
|
|
|
CircuitNode** follow,
|
|
|
|
|
Clauses& clauses)
|
|
|
|
|
{
|
|
|
|
|
for (size_t i = 0; i < clauses.size(); i++) {
|
2012-11-07 23:45:43 +00:00
|
|
|
|
Literals depLits = { clauses[i].literals().front() };
|
|
|
|
|
Literals indepLits (clauses[i].literals().begin() + 1,
|
|
|
|
|
clauses[i].literals().end());
|
|
|
|
|
bool finish = false;
|
|
|
|
|
while (finish == false) {
|
|
|
|
|
finish = true;
|
|
|
|
|
for (size_t j = 0; j < indepLits.size(); j++) {
|
|
|
|
|
if (independentLiteral (indepLits[j], depLits) == false) {
|
|
|
|
|
depLits.push_back (indepLits[j]);
|
|
|
|
|
indepLits.erase (indepLits.begin() + j);
|
|
|
|
|
finish = false;
|
2012-10-30 00:21:10 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-11-07 23:45:43 +00:00
|
|
|
|
}
|
|
|
|
|
if (indepLits.empty() == false) {
|
|
|
|
|
// TODO this should be have to be count normalized too
|
|
|
|
|
LogVarSet lvs1;
|
|
|
|
|
for (size_t j = 0; j < depLits.size(); j++) {
|
|
|
|
|
lvs1 |= depLits[j].logVarSet();
|
|
|
|
|
}
|
|
|
|
|
LogVarSet lvs2;
|
|
|
|
|
for (size_t j = 0; j < indepLits.size(); j++) {
|
|
|
|
|
lvs2 |= indepLits[j].logVarSet();
|
|
|
|
|
}
|
|
|
|
|
Clause c1 (clauses[i].constr().projectedCopy (lvs1));
|
|
|
|
|
for (size_t j = 0; j < depLits.size(); j++) {
|
|
|
|
|
c1.addLiteral (depLits[j]);
|
|
|
|
|
}
|
|
|
|
|
Clause c2 (clauses[i].constr().projectedCopy (lvs2));
|
|
|
|
|
for (size_t j = 0; j < indepLits.size(); j++) {
|
|
|
|
|
c2.addLiteral (indepLits[j]);
|
2012-10-30 00:21:10 +00:00
|
|
|
|
}
|
2012-11-07 23:45:43 +00:00
|
|
|
|
Clauses plus1Clauses = clauses;
|
|
|
|
|
Clauses plus2Clauses = clauses;
|
|
|
|
|
Clauses minusClauses = clauses;
|
|
|
|
|
plus1Clauses.erase (plus1Clauses.begin() + i);
|
|
|
|
|
plus2Clauses.erase (plus2Clauses.begin() + i);
|
|
|
|
|
minusClauses.erase (minusClauses.begin() + i);
|
|
|
|
|
plus1Clauses.push_back (c1);
|
|
|
|
|
plus2Clauses.push_back (c2);
|
|
|
|
|
minusClauses.push_back (c1);
|
|
|
|
|
minusClauses.push_back (c2);
|
|
|
|
|
stringstream explanation;
|
|
|
|
|
explanation << " IncExc on clause nº " << i + 1;
|
|
|
|
|
IncExcNode* ieNode = new IncExcNode (clauses, explanation.str());
|
|
|
|
|
compile (ieNode->plus1Branch(), plus1Clauses);
|
|
|
|
|
compile (ieNode->plus2Branch(), plus2Clauses);
|
|
|
|
|
compile (ieNode->minusBranch(), minusClauses);
|
|
|
|
|
*follow = ieNode;
|
|
|
|
|
return true;
|
2012-10-30 00:21:10 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-10-27 00:13:11 +01:00
|
|
|
|
bool
|
|
|
|
|
LiftedCircuit::tryIndepPartialGrounding (
|
|
|
|
|
CircuitNode** follow,
|
|
|
|
|
Clauses& clauses)
|
|
|
|
|
{
|
|
|
|
|
// assumes that all literals have logical variables
|
2012-10-29 15:39:56 +00:00
|
|
|
|
// else, shannon decomp was possible
|
2012-11-06 23:35:14 +00:00
|
|
|
|
LogVars rootLogVars;
|
2012-10-29 20:49:21 +00:00
|
|
|
|
LogVarSet lvs = clauses[0].ipgCandidates();
|
|
|
|
|
for (size_t i = 0; i < lvs.size(); i++) {
|
2012-11-06 23:35:14 +00:00
|
|
|
|
rootLogVars.clear();
|
|
|
|
|
rootLogVars.push_back (lvs[i]);
|
|
|
|
|
ConstraintTree ct = clauses[0].constr().projectedCopy ({lvs[i]});
|
|
|
|
|
if (tryIndepPartialGroundingAux (clauses, ct, rootLogVars)) {
|
2012-10-29 20:49:21 +00:00
|
|
|
|
Clauses newClauses = clauses;
|
2012-11-06 23:35:14 +00:00
|
|
|
|
for (size_t j = 0; j < clauses.size(); j++) {
|
|
|
|
|
newClauses[j].addIpgLogVar (rootLogVars[j]);
|
2012-10-27 00:13:11 +01:00
|
|
|
|
}
|
2012-10-29 20:49:21 +00:00
|
|
|
|
SetAndNode* node = new SetAndNode (ct.size(), clauses);
|
|
|
|
|
*follow = node;
|
|
|
|
|
compile (node->follow(), newClauses);
|
|
|
|
|
return true;
|
2012-10-27 00:13:11 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2012-10-29 20:49:21 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
LiftedCircuit::tryIndepPartialGroundingAux (
|
|
|
|
|
Clauses& clauses,
|
|
|
|
|
ConstraintTree& ct,
|
2012-11-06 23:35:14 +00:00
|
|
|
|
LogVars& rootLogVars)
|
2012-10-29 20:49:21 +00:00
|
|
|
|
{
|
2012-11-06 23:35:14 +00:00
|
|
|
|
for (size_t i = 1; i < clauses.size(); i++) {
|
|
|
|
|
LogVarSet lvs = clauses[i].ipgCandidates();
|
|
|
|
|
for (size_t j = 0; j < lvs.size(); j++) {
|
|
|
|
|
ConstraintTree ct2 = clauses[i].constr().projectedCopy ({lvs[j]});
|
2012-10-29 20:49:21 +00:00
|
|
|
|
if (ct.tupleSet() == ct2.tupleSet()) {
|
2012-11-06 23:35:14 +00:00
|
|
|
|
rootLogVars.push_back (lvs[j]);
|
2012-10-29 20:49:21 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-11-06 23:35:14 +00:00
|
|
|
|
if (rootLogVars.size() != i + 1) {
|
2012-10-29 20:49:21 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2012-10-27 00:13:11 +01:00
|
|
|
|
}
|
2012-11-06 23:35:14 +00:00
|
|
|
|
// verifies if the IPG logical vars appear in the same positions
|
|
|
|
|
unordered_map<LiteralId, size_t> positions;
|
|
|
|
|
for (size_t i = 0; i < clauses.size(); i++) {
|
|
|
|
|
const Literals& literals = clauses[i].literals();
|
|
|
|
|
for (size_t j = 0; j < literals.size(); j++) {
|
|
|
|
|
size_t idx = literals[j].indexOfLogVar (rootLogVars[i]);
|
|
|
|
|
assert (idx != literals[j].nrLogVars());
|
|
|
|
|
unordered_map<LiteralId, size_t>::iterator it;
|
|
|
|
|
it = positions.find (literals[j].lid());
|
|
|
|
|
if (it != positions.end()) {
|
|
|
|
|
if (it->second != idx) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
positions[literals[j].lid()] = idx;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-10-27 00:13:11 +01:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-10-31 23:43:39 +00:00
|
|
|
|
bool
|
|
|
|
|
LiftedCircuit::tryAtomCounting (
|
|
|
|
|
CircuitNode** follow,
|
|
|
|
|
Clauses& clauses)
|
|
|
|
|
{
|
2012-11-06 23:56:52 +00:00
|
|
|
|
for (size_t i = 0; i < clauses.size(); i++) {
|
2012-11-07 15:28:33 +00:00
|
|
|
|
if (clauses[i].nrPosCountedLogVars() > 0
|
|
|
|
|
|| clauses[i].nrNegCountedLogVars() > 0) {
|
2012-11-06 23:56:52 +00:00
|
|
|
|
// only allow one atom counting node per branch
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-10-31 23:43:39 +00:00
|
|
|
|
for (size_t i = 0; i < clauses.size(); i++) {
|
|
|
|
|
Literals literals = clauses[i].literals();
|
|
|
|
|
for (size_t j = 0; j < literals.size(); j++) {
|
2012-11-06 23:39:18 +00:00
|
|
|
|
if (literals[j].nrLogVars() == 1
|
2012-11-06 15:56:52 +00:00
|
|
|
|
&& ! clauses[i].isIpgLogVar (literals[j].logVars().front())
|
|
|
|
|
&& ! clauses[i].isCountedLogVar (literals[j].logVars().front())) {
|
2012-11-01 22:34:28 +00:00
|
|
|
|
unsigned nrGroundings = clauses[i].constr().projectedCopy (
|
|
|
|
|
literals[j].logVars()).size();
|
|
|
|
|
SetOrNode* setOrNode = new SetOrNode (nrGroundings, clauses);
|
2012-10-31 23:43:39 +00:00
|
|
|
|
Clause c1 (clauses[i].constr().projectedCopy (literals[j].logVars()));
|
|
|
|
|
Clause c2 (clauses[i].constr().projectedCopy (literals[j].logVars()));
|
|
|
|
|
c1.addLiteral (literals[j]);
|
2012-11-07 15:28:33 +00:00
|
|
|
|
c2.addLiteralComplemented (literals[j]);
|
|
|
|
|
c1.addPosCountedLogVar (literals[j].logVars().front());
|
|
|
|
|
c2.addNegCountedLogVar (literals[j].logVars().front());
|
2012-10-31 23:43:39 +00:00
|
|
|
|
clauses.push_back (c1);
|
|
|
|
|
clauses.push_back (c2);
|
|
|
|
|
shatterCountedLogVars (clauses);
|
|
|
|
|
compile (setOrNode->follow(), clauses);
|
|
|
|
|
*follow = setOrNode;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-10-27 00:13:11 +01:00
|
|
|
|
bool
|
|
|
|
|
LiftedCircuit::tryGrounding (
|
2012-10-29 15:39:56 +00:00
|
|
|
|
CircuitNode**,
|
|
|
|
|
Clauses&)
|
2012-10-27 00:13:11 +01:00
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
/*
|
|
|
|
|
size_t bestClauseIdx = 0;
|
|
|
|
|
size_t bestLogVarIdx = 0;
|
|
|
|
|
unsigned minNrSymbols = Util::maxUnsigned();
|
|
|
|
|
for (size_t i = 0; i < clauses.size(); i++) {
|
|
|
|
|
LogVarSet lvs = clauses[i].constr().logVars();
|
|
|
|
|
ConstraintTree ct = clauses[i].constr();
|
|
|
|
|
for (unsigned j = 0; j < lvs.size(); j++) {
|
|
|
|
|
unsigned nrSymbols = ct.nrSymbols (lvs[j]);
|
|
|
|
|
if (nrSymbols < minNrSymbols) {
|
|
|
|
|
minNrSymbols = nrSymbols;
|
|
|
|
|
bestClauseIdx = i;
|
|
|
|
|
bestLogVarIdx = j;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
LogVar bestLogVar = clauses[bestClauseIdx].constr().logVars()[bestLogVarIdx];
|
|
|
|
|
ConstraintTrees cts = clauses[bestClauseIdx].constr().ground (bestLogVar);
|
|
|
|
|
return true;
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-11-01 13:56:12 +00:00
|
|
|
|
void
|
|
|
|
|
LiftedCircuit::shatterCountedLogVars (Clauses& clauses)
|
|
|
|
|
{
|
|
|
|
|
while (shatterCountedLogVarsAux (clauses)) ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
LiftedCircuit::shatterCountedLogVarsAux (Clauses& clauses)
|
|
|
|
|
{
|
|
|
|
|
for (size_t i = 0; i < clauses.size() - 1; i++) {
|
|
|
|
|
for (size_t j = i + 1; j < clauses.size(); j++) {
|
|
|
|
|
bool splitedSome = shatterCountedLogVarsAux (clauses, i, j);
|
|
|
|
|
if (splitedSome) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
LiftedCircuit::shatterCountedLogVarsAux (
|
|
|
|
|
Clauses& clauses,
|
|
|
|
|
size_t idx1,
|
|
|
|
|
size_t idx2)
|
|
|
|
|
{
|
|
|
|
|
Literals lits1 = clauses[idx1].literals();
|
|
|
|
|
Literals lits2 = clauses[idx2].literals();
|
|
|
|
|
for (size_t i = 0; i < lits1.size(); i++) {
|
|
|
|
|
for (size_t j = 0; j < lits2.size(); j++) {
|
|
|
|
|
if (lits1[i].lid() == lits2[j].lid()) {
|
|
|
|
|
LogVars lvs1 = lits1[i].logVars();
|
|
|
|
|
LogVars lvs2 = lits2[j].logVars();
|
|
|
|
|
for (size_t k = 0; k < lvs1.size(); k++) {
|
|
|
|
|
if (clauses[idx1].isCountedLogVar (lvs1[k])
|
|
|
|
|
&& clauses[idx2].isCountedLogVar (lvs2[k]) == false) {
|
|
|
|
|
clauses.push_back (clauses[idx2]);
|
2012-11-07 15:28:33 +00:00
|
|
|
|
clauses[idx2].addPosCountedLogVar (lvs2[k]);
|
|
|
|
|
clauses.back().addNegCountedLogVar (lvs2[k]);
|
2012-11-01 13:56:12 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (clauses[idx2].isCountedLogVar (lvs2[k])
|
|
|
|
|
&& clauses[idx1].isCountedLogVar (lvs1[k]) == false) {
|
|
|
|
|
clauses.push_back (clauses[idx1]);
|
2012-11-07 15:28:33 +00:00
|
|
|
|
clauses[idx1].addPosCountedLogVar (lvs1[k]);
|
|
|
|
|
clauses.back().addNegCountedLogVar (lvs1[k]);
|
2012-11-01 13:56:12 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-11-07 18:42:11 +00:00
|
|
|
|
bool
|
2012-11-07 23:45:43 +00:00
|
|
|
|
LiftedCircuit::independentClause (
|
2012-11-07 18:42:11 +00:00
|
|
|
|
Clause& clause,
|
|
|
|
|
Clauses& otherClauses) const
|
|
|
|
|
{
|
|
|
|
|
for (size_t i = 0; i < otherClauses.size(); i++) {
|
2012-11-07 21:21:42 +00:00
|
|
|
|
if (Clause::independentClauses (clause, otherClauses[i]) == false) {
|
2012-11-07 18:42:11 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-11-07 23:45:43 +00:00
|
|
|
|
bool
|
|
|
|
|
LiftedCircuit::independentLiteral (
|
|
|
|
|
const Literal& lit,
|
|
|
|
|
const Literals& otherLits) const
|
|
|
|
|
{
|
|
|
|
|
for (size_t i = 0; i < otherLits.size(); i++) {
|
|
|
|
|
if (lit.lid() == otherLits[i].lid()
|
|
|
|
|
|| (lit.logVarSet() & otherLits[i].logVarSet()).empty() == false) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-11-04 18:02:40 +00:00
|
|
|
|
LitLvTypesSet
|
2012-10-24 21:22:49 +01:00
|
|
|
|
LiftedCircuit::smoothCircuit (CircuitNode* node)
|
|
|
|
|
{
|
|
|
|
|
assert (node != 0);
|
2012-11-04 18:02:40 +00:00
|
|
|
|
LitLvTypesSet propagLits;
|
2012-10-24 21:22:49 +01:00
|
|
|
|
|
|
|
|
|
switch (getCircuitNodeType (node)) {
|
|
|
|
|
|
|
|
|
|
case CircuitNodeType::OR_NODE: {
|
|
|
|
|
OrNode* casted = dynamic_cast<OrNode*>(node);
|
2012-11-04 18:02:40 +00:00
|
|
|
|
LitLvTypesSet lids1 = smoothCircuit (*casted->leftBranch());
|
|
|
|
|
LitLvTypesSet lids2 = smoothCircuit (*casted->rightBranch());
|
|
|
|
|
LitLvTypesSet missingLeft = lids2 - lids1;
|
|
|
|
|
LitLvTypesSet missingRight = lids1 - lids2;
|
2012-10-30 15:48:19 +00:00
|
|
|
|
createSmoothNode (missingLeft, casted->leftBranch());
|
|
|
|
|
createSmoothNode (missingRight, casted->rightBranch());
|
2012-11-04 18:02:40 +00:00
|
|
|
|
propagLits |= lids1;
|
|
|
|
|
propagLits |= lids2;
|
2012-10-24 21:22:49 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case CircuitNodeType::AND_NODE: {
|
|
|
|
|
AndNode* casted = dynamic_cast<AndNode*>(node);
|
2012-11-04 18:02:40 +00:00
|
|
|
|
LitLvTypesSet lids1 = smoothCircuit (*casted->leftBranch());
|
|
|
|
|
LitLvTypesSet lids2 = smoothCircuit (*casted->rightBranch());
|
|
|
|
|
propagLits |= lids1;
|
|
|
|
|
propagLits |= lids2;
|
2012-10-24 21:22:49 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case CircuitNodeType::SET_OR_NODE: {
|
2012-11-04 18:02:40 +00:00
|
|
|
|
SetOrNode* casted = dynamic_cast<SetOrNode*>(node);
|
|
|
|
|
propagLits = smoothCircuit (*casted->follow());
|
|
|
|
|
TinySet<pair<LiteralId,unsigned>> litSet;
|
|
|
|
|
for (size_t i = 0; i < propagLits.size(); i++) {
|
|
|
|
|
litSet.insert (make_pair (propagLits[i].lid(),
|
|
|
|
|
propagLits[i].logVarTypes().size()));
|
|
|
|
|
}
|
|
|
|
|
LitLvTypesSet missingLids;
|
|
|
|
|
for (size_t i = 0; i < litSet.size(); i++) {
|
|
|
|
|
vector<LogVarTypes> allTypes = getAllPossibleTypes (litSet[i].second);
|
|
|
|
|
for (size_t j = 0; j < allTypes.size(); j++) {
|
|
|
|
|
bool typeFound = false;
|
|
|
|
|
for (size_t k = 0; k < propagLits.size(); k++) {
|
|
|
|
|
if (litSet[i].first == propagLits[k].lid()
|
|
|
|
|
&& containsTypes (allTypes[j], propagLits[k].logVarTypes())) {
|
|
|
|
|
typeFound = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (typeFound == false) {
|
2012-11-07 15:28:33 +00:00
|
|
|
|
missingLids.insert (LitLvTypes (litSet[i].first, allTypes[j]));
|
2012-11-04 18:02:40 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
createSmoothNode (missingLids, casted->follow());
|
2012-11-06 15:56:52 +00:00
|
|
|
|
for (size_t i = 0; i < propagLits.size(); i++) {
|
|
|
|
|
propagLits[i].setAllFullLogVars();
|
|
|
|
|
}
|
2012-10-29 15:39:56 +00:00
|
|
|
|
break;
|
2012-10-24 21:22:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case CircuitNodeType::SET_AND_NODE: {
|
2012-10-29 15:39:56 +00:00
|
|
|
|
SetAndNode* casted = dynamic_cast<SetAndNode*>(node);
|
2012-11-04 18:02:40 +00:00
|
|
|
|
propagLits = smoothCircuit (*casted->follow());
|
2012-10-29 15:39:56 +00:00
|
|
|
|
break;
|
2012-10-24 21:22:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case CircuitNodeType::INC_EXC_NODE: {
|
2012-10-30 15:48:19 +00:00
|
|
|
|
IncExcNode* casted = dynamic_cast<IncExcNode*>(node);
|
2012-11-04 18:02:40 +00:00
|
|
|
|
LitLvTypesSet lids1 = smoothCircuit (*casted->plus1Branch());
|
|
|
|
|
LitLvTypesSet lids2 = smoothCircuit (*casted->plus2Branch());
|
|
|
|
|
LitLvTypesSet missingPlus1 = lids2 - lids1;
|
|
|
|
|
LitLvTypesSet missingPlus2 = lids1 - lids2;
|
2012-10-30 15:48:19 +00:00
|
|
|
|
createSmoothNode (missingPlus1, casted->plus1Branch());
|
|
|
|
|
createSmoothNode (missingPlus2, casted->plus2Branch());
|
2012-11-04 18:02:40 +00:00
|
|
|
|
propagLits |= lids1;
|
|
|
|
|
propagLits |= lids2;
|
2012-10-29 15:39:56 +00:00
|
|
|
|
break;
|
2012-10-24 21:22:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case CircuitNodeType::LEAF_NODE: {
|
2012-11-07 15:28:33 +00:00
|
|
|
|
propagLits.insert (LitLvTypes (
|
2012-11-04 18:02:40 +00:00
|
|
|
|
node->clauses()[0].literals()[0].lid(),
|
|
|
|
|
node->clauses()[0].logVarTypes(0)));
|
2012-10-24 21:22:49 +01:00
|
|
|
|
}
|
2012-10-30 16:00:20 +00:00
|
|
|
|
|
2012-10-24 21:22:49 +01:00
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-04 18:02:40 +00:00
|
|
|
|
return propagLits;
|
2012-10-24 21:22:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-10-30 15:48:19 +00:00
|
|
|
|
void
|
|
|
|
|
LiftedCircuit::createSmoothNode (
|
2012-11-04 18:02:40 +00:00
|
|
|
|
const LitLvTypesSet& missingLits,
|
2012-10-30 15:48:19 +00:00
|
|
|
|
CircuitNode** prev)
|
|
|
|
|
{
|
2012-11-04 18:02:40 +00:00
|
|
|
|
if (missingLits.empty() == false) {
|
2012-10-30 15:48:19 +00:00
|
|
|
|
Clauses clauses;
|
2012-11-04 18:02:40 +00:00
|
|
|
|
for (size_t i = 0; i < missingLits.size(); i++) {
|
|
|
|
|
LiteralId lid = missingLits[i].lid();
|
|
|
|
|
const LogVarTypes& types = missingLits[i].logVarTypes();
|
2012-11-07 15:28:33 +00:00
|
|
|
|
Clause c = lwcnf_->createClause (lid);
|
2012-11-04 18:02:40 +00:00
|
|
|
|
for (size_t j = 0; j < types.size(); j++) {
|
|
|
|
|
LogVar X = c.literals().front().logVars()[j];
|
|
|
|
|
if (types[j] == LogVarType::POS_LV) {
|
2012-11-07 15:28:33 +00:00
|
|
|
|
c.addPosCountedLogVar (X);
|
2012-11-04 18:02:40 +00:00
|
|
|
|
} else if (types[j] == LogVarType::NEG_LV) {
|
2012-11-07 15:28:33 +00:00
|
|
|
|
c.addNegCountedLogVar (X);
|
2012-11-04 18:02:40 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2012-11-07 15:28:33 +00:00
|
|
|
|
c.addLiteralComplemented (c.literals()[0]);
|
2012-10-30 15:48:19 +00:00
|
|
|
|
clauses.push_back (c);
|
|
|
|
|
}
|
2012-11-06 14:15:21 +00:00
|
|
|
|
SmoothNode* smoothNode = new SmoothNode (clauses, *lwcnf_);
|
2012-10-30 15:48:19 +00:00
|
|
|
|
*prev = new AndNode ((*prev)->clauses(), smoothNode,
|
|
|
|
|
*prev, " Smoothing");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-11-07 12:37:22 +00:00
|
|
|
|
vector<LogVarTypes>
|
|
|
|
|
LiftedCircuit::getAllPossibleTypes (unsigned nrLogVars) const
|
|
|
|
|
{
|
|
|
|
|
if (nrLogVars == 0) {
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
if (nrLogVars == 1) {
|
|
|
|
|
return {{LogVarType::POS_LV},{LogVarType::NEG_LV}};
|
|
|
|
|
}
|
|
|
|
|
vector<LogVarTypes> res;
|
|
|
|
|
Indexer indexer (vector<unsigned> (nrLogVars, 2));
|
|
|
|
|
while (indexer.valid()) {
|
|
|
|
|
LogVarTypes types;
|
|
|
|
|
for (size_t i = 0; i < nrLogVars; i++) {
|
|
|
|
|
if (indexer[i] == 0) {
|
|
|
|
|
types.push_back (LogVarType::POS_LV);
|
|
|
|
|
} else {
|
|
|
|
|
types.push_back (LogVarType::NEG_LV);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
res.push_back (types);
|
|
|
|
|
++ indexer;
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
LiftedCircuit::containsTypes (
|
|
|
|
|
const LogVarTypes& typesA,
|
|
|
|
|
const LogVarTypes& typesB) const
|
|
|
|
|
{
|
|
|
|
|
for (size_t i = 0; i < typesA.size(); i++) {
|
|
|
|
|
if (typesA[i] == LogVarType::FULL_LV) {
|
|
|
|
|
|
|
|
|
|
} else if (typesA[i] == LogVarType::POS_LV
|
|
|
|
|
&& typesB[i] == LogVarType::POS_LV) {
|
|
|
|
|
|
|
|
|
|
} else if (typesA[i] == LogVarType::NEG_LV
|
|
|
|
|
&& typesB[i] == LogVarType::NEG_LV) {
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-10-24 21:22:49 +01:00
|
|
|
|
CircuitNodeType
|
|
|
|
|
LiftedCircuit::getCircuitNodeType (const CircuitNode* node) const
|
|
|
|
|
{
|
|
|
|
|
CircuitNodeType type;
|
|
|
|
|
if (dynamic_cast<const OrNode*>(node) != 0) {
|
|
|
|
|
type = CircuitNodeType::OR_NODE;
|
|
|
|
|
} else if (dynamic_cast<const AndNode*>(node) != 0) {
|
|
|
|
|
type = CircuitNodeType::AND_NODE;
|
2012-10-27 00:13:11 +01:00
|
|
|
|
} else if (dynamic_cast<const SetOrNode*>(node) != 0) {
|
|
|
|
|
type = CircuitNodeType::SET_OR_NODE;
|
|
|
|
|
} else if (dynamic_cast<const SetAndNode*>(node) != 0) {
|
|
|
|
|
type = CircuitNodeType::SET_AND_NODE;
|
2012-10-30 00:21:10 +00:00
|
|
|
|
} else if (dynamic_cast<const IncExcNode*>(node) != 0) {
|
|
|
|
|
type = CircuitNodeType::INC_EXC_NODE;
|
2012-10-24 21:22:49 +01:00
|
|
|
|
} else if (dynamic_cast<const LeafNode*>(node) != 0) {
|
|
|
|
|
type = CircuitNodeType::LEAF_NODE;
|
|
|
|
|
} else if (dynamic_cast<const SmoothNode*>(node) != 0) {
|
|
|
|
|
type = CircuitNodeType::SMOOTH_NODE;
|
|
|
|
|
} else if (dynamic_cast<const TrueNode*>(node) != 0) {
|
|
|
|
|
type = CircuitNodeType::TRUE_NODE;
|
2012-10-30 12:41:00 +00:00
|
|
|
|
} else if (dynamic_cast<const CompilationFailedNode*>(node) != 0) {
|
|
|
|
|
type = CircuitNodeType::COMPILATION_FAILED_NODE;
|
2012-10-24 21:22:49 +01:00
|
|
|
|
} else {
|
|
|
|
|
assert (false);
|
|
|
|
|
}
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-10-22 23:01:13 +01:00
|
|
|
|
void
|
2012-10-24 21:22:49 +01:00
|
|
|
|
LiftedCircuit::exportToGraphViz (CircuitNode* node, ofstream& os)
|
2012-10-22 23:01:13 +01:00
|
|
|
|
{
|
|
|
|
|
assert (node != 0);
|
2012-10-27 00:13:11 +01:00
|
|
|
|
|
2012-10-29 13:49:11 +00:00
|
|
|
|
static unsigned nrAuxNodes = 0;
|
|
|
|
|
stringstream ss;
|
|
|
|
|
ss << "n" << nrAuxNodes;
|
|
|
|
|
string auxNode = ss.str();
|
|
|
|
|
nrAuxNodes ++;
|
2012-11-07 23:45:43 +00:00
|
|
|
|
string opStyle = "shape=circle,width=0.7,margin=\"0.0,0.0\"," ;
|
2012-10-22 23:01:13 +01:00
|
|
|
|
|
2012-10-25 12:22:52 +01:00
|
|
|
|
switch (getCircuitNodeType (node)) {
|
|
|
|
|
|
|
|
|
|
case OR_NODE: {
|
|
|
|
|
OrNode* casted = dynamic_cast<OrNode*>(node);
|
2012-10-30 14:31:52 +00:00
|
|
|
|
printClauses (casted, os);
|
2012-10-29 15:39:56 +00:00
|
|
|
|
|
2012-11-07 23:45:43 +00:00
|
|
|
|
os << auxNode << " [" << opStyle << "label=\"∨\"]" << endl;
|
2012-10-29 13:49:11 +00:00
|
|
|
|
os << escapeNode (node) << " -> " << auxNode;
|
2012-10-29 15:39:56 +00:00
|
|
|
|
os << " [label=\"" << node->explanation() << "\"]" ;
|
|
|
|
|
os << endl;
|
|
|
|
|
|
2012-10-29 13:49:11 +00:00
|
|
|
|
os << auxNode << " -> " ;
|
2012-10-29 15:39:56 +00:00
|
|
|
|
os << escapeNode (*casted->leftBranch());
|
|
|
|
|
os << " [label=\" " << (*casted->leftBranch())->weight() << "\"]" ;
|
|
|
|
|
os << endl;
|
|
|
|
|
|
2012-10-29 13:49:11 +00:00
|
|
|
|
os << auxNode << " -> " ;
|
2012-10-29 15:39:56 +00:00
|
|
|
|
os << escapeNode (*casted->rightBranch());
|
|
|
|
|
os << " [label=\" " << (*casted->rightBranch())->weight() << "\"]" ;
|
|
|
|
|
os << endl;
|
|
|
|
|
|
2012-10-25 12:22:52 +01:00
|
|
|
|
exportToGraphViz (*casted->leftBranch(), os);
|
|
|
|
|
exportToGraphViz (*casted->rightBranch(), os);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-10-31 23:43:39 +00:00
|
|
|
|
|
2012-10-25 12:22:52 +01:00
|
|
|
|
case AND_NODE: {
|
|
|
|
|
AndNode* casted = dynamic_cast<AndNode*>(node);
|
2012-10-30 14:31:52 +00:00
|
|
|
|
printClauses (casted, os);
|
2012-10-31 23:43:39 +00:00
|
|
|
|
|
2012-11-07 23:45:43 +00:00
|
|
|
|
os << auxNode << " [" << opStyle << "label=\"∧\"]" << endl;
|
2012-10-29 13:49:11 +00:00
|
|
|
|
os << escapeNode (node) << " -> " << auxNode;
|
2012-10-29 15:39:56 +00:00
|
|
|
|
os << " [label=\"" << node->explanation() << "\"]" ;
|
|
|
|
|
os << endl;
|
|
|
|
|
|
2012-10-29 13:49:11 +00:00
|
|
|
|
os << auxNode << " -> " ;
|
2012-10-29 15:39:56 +00:00
|
|
|
|
os << escapeNode (*casted->leftBranch());
|
|
|
|
|
os << " [label=\" " << (*casted->leftBranch())->weight() << "\"]" ;
|
|
|
|
|
os << endl;
|
|
|
|
|
|
2012-10-29 13:49:11 +00:00
|
|
|
|
os << auxNode << " -> " ;
|
2012-10-25 12:22:52 +01:00
|
|
|
|
os << escapeNode (*casted->rightBranch()) << endl;
|
2012-10-29 15:39:56 +00:00
|
|
|
|
os << " [label=\" " << (*casted->rightBranch())->weight() << "\"]" ;
|
|
|
|
|
os << endl;
|
|
|
|
|
|
2012-10-25 12:22:52 +01:00
|
|
|
|
exportToGraphViz (*casted->leftBranch(), os);
|
|
|
|
|
exportToGraphViz (*casted->rightBranch(), os);
|
|
|
|
|
break;
|
2012-10-22 23:01:13 +01:00
|
|
|
|
}
|
2012-10-31 23:43:39 +00:00
|
|
|
|
|
2012-10-27 00:13:11 +01:00
|
|
|
|
case SET_OR_NODE: {
|
2012-10-31 23:43:39 +00:00
|
|
|
|
SetOrNode* casted = dynamic_cast<SetOrNode*>(node);
|
|
|
|
|
printClauses (casted, os);
|
|
|
|
|
|
2012-11-07 23:45:43 +00:00
|
|
|
|
os << auxNode << " [" << opStyle << "label=\"∨(X)\"]" << endl;
|
2012-10-31 23:43:39 +00:00
|
|
|
|
os << escapeNode (node) << " -> " << auxNode;
|
|
|
|
|
os << " [label=\"" << node->explanation() << "\"]" ;
|
|
|
|
|
os << endl;
|
|
|
|
|
|
|
|
|
|
os << auxNode << " -> " ;
|
|
|
|
|
os << escapeNode (*casted->follow());
|
|
|
|
|
os << " [label=\" " << (*casted->follow())->weight() << "\"]" ;
|
|
|
|
|
os << endl;
|
|
|
|
|
|
|
|
|
|
exportToGraphViz (*casted->follow(), os);
|
|
|
|
|
break;
|
2012-10-27 00:13:11 +01:00
|
|
|
|
}
|
2012-10-31 23:43:39 +00:00
|
|
|
|
|
2012-10-27 00:13:11 +01:00
|
|
|
|
case SET_AND_NODE: {
|
|
|
|
|
SetAndNode* casted = dynamic_cast<SetAndNode*>(node);
|
2012-10-30 14:31:52 +00:00
|
|
|
|
printClauses (casted, os);
|
2012-10-31 23:43:39 +00:00
|
|
|
|
|
2012-11-07 23:45:43 +00:00
|
|
|
|
os << auxNode << " [" << opStyle << "label=\"∧(X)\"]" << endl;
|
2012-10-29 13:49:11 +00:00
|
|
|
|
os << escapeNode (node) << " -> " << auxNode;
|
2012-10-29 15:39:56 +00:00
|
|
|
|
os << " [label=\"" << node->explanation() << "\"]" ;
|
|
|
|
|
os << endl;
|
2012-10-31 23:43:39 +00:00
|
|
|
|
|
2012-10-29 13:49:11 +00:00
|
|
|
|
os << auxNode << " -> " ;
|
2012-10-29 15:39:56 +00:00
|
|
|
|
os << escapeNode (*casted->follow());
|
|
|
|
|
os << " [label=\" " << (*casted->follow())->weight() << "\"]" ;
|
|
|
|
|
os << endl;
|
2012-10-31 23:43:39 +00:00
|
|
|
|
|
2012-10-27 00:13:11 +01:00
|
|
|
|
exportToGraphViz (*casted->follow(), os);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-10-31 23:43:39 +00:00
|
|
|
|
|
2012-10-30 00:21:10 +00:00
|
|
|
|
case INC_EXC_NODE: {
|
|
|
|
|
IncExcNode* casted = dynamic_cast<IncExcNode*>(node);
|
2012-10-30 14:31:52 +00:00
|
|
|
|
printClauses (casted, os);
|
2012-10-31 23:43:39 +00:00
|
|
|
|
|
2012-11-07 23:45:43 +00:00
|
|
|
|
os << auxNode << " [" << opStyle << "label=\"+ - +\"]" ;
|
|
|
|
|
os << endl;
|
2012-10-30 00:21:10 +00:00
|
|
|
|
os << escapeNode (node) << " -> " << auxNode;
|
|
|
|
|
os << " [label=\"" << node->explanation() << "\"]" ;
|
|
|
|
|
os << endl;
|
|
|
|
|
|
|
|
|
|
os << auxNode << " -> " ;
|
|
|
|
|
os << escapeNode (*casted->plus1Branch());
|
|
|
|
|
os << " [label=\" " << (*casted->plus1Branch())->weight() << "\"]" ;
|
|
|
|
|
os << endl;
|
2012-11-07 23:45:43 +00:00
|
|
|
|
|
|
|
|
|
os << auxNode << " -> " ;
|
|
|
|
|
os << escapeNode (*casted->minusBranch()) << endl;
|
|
|
|
|
os << " [label=\" " << (*casted->minusBranch())->weight() << "\"]" ;
|
|
|
|
|
os << endl;
|
2012-10-31 23:43:39 +00:00
|
|
|
|
|
2012-10-30 00:21:10 +00:00
|
|
|
|
os << auxNode << " -> " ;
|
|
|
|
|
os << escapeNode (*casted->plus2Branch());
|
|
|
|
|
os << " [label=\" " << (*casted->plus2Branch())->weight() << "\"]" ;
|
|
|
|
|
os << endl;
|
|
|
|
|
|
|
|
|
|
exportToGraphViz (*casted->plus1Branch(), os);
|
|
|
|
|
exportToGraphViz (*casted->plus2Branch(), os);
|
|
|
|
|
exportToGraphViz (*casted->minusBranch(), os);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-10-31 23:43:39 +00:00
|
|
|
|
|
2012-10-25 12:22:52 +01:00
|
|
|
|
case LEAF_NODE: {
|
2012-10-30 16:00:20 +00:00
|
|
|
|
printClauses (node, os, "style=filled,fillcolor=palegreen,");
|
2012-10-25 12:22:52 +01:00
|
|
|
|
break;
|
2012-10-24 21:22:49 +01:00
|
|
|
|
}
|
2012-10-31 23:43:39 +00:00
|
|
|
|
|
2012-10-25 12:22:52 +01:00
|
|
|
|
case SMOOTH_NODE: {
|
2012-10-30 16:00:20 +00:00
|
|
|
|
printClauses (node, os, "style=filled,fillcolor=lightblue,");
|
2012-10-25 12:22:52 +01:00
|
|
|
|
break;
|
2012-10-22 23:01:13 +01:00
|
|
|
|
}
|
2012-10-31 23:43:39 +00:00
|
|
|
|
|
2012-10-25 12:22:52 +01:00
|
|
|
|
case TRUE_NODE: {
|
|
|
|
|
os << escapeNode (node);
|
|
|
|
|
os << " [shape=box,label=\"⊤\"]" ;
|
|
|
|
|
os << endl;
|
|
|
|
|
break;
|
2012-10-24 21:22:49 +01:00
|
|
|
|
}
|
2012-10-31 23:43:39 +00:00
|
|
|
|
|
2012-10-30 12:41:00 +00:00
|
|
|
|
case COMPILATION_FAILED_NODE: {
|
2012-10-30 16:00:20 +00:00
|
|
|
|
printClauses (node, os, "style=filled,fillcolor=salmon,");
|
2012-10-25 12:22:52 +01:00
|
|
|
|
break;
|
2012-10-22 23:01:13 +01:00
|
|
|
|
}
|
2012-10-31 23:43:39 +00:00
|
|
|
|
|
2012-10-25 12:22:52 +01:00
|
|
|
|
default:
|
|
|
|
|
assert (false);
|
|
|
|
|
}
|
2012-10-22 23:01:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
2012-10-30 14:31:52 +00:00
|
|
|
|
|
|
|
|
|
|
2012-10-30 15:48:19 +00:00
|
|
|
|
string
|
|
|
|
|
LiftedCircuit::escapeNode (const CircuitNode* node) const
|
|
|
|
|
{
|
|
|
|
|
stringstream ss;
|
|
|
|
|
ss << "\"" << node << "\"" ;
|
|
|
|
|
return ss.str();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-10-30 14:31:52 +00:00
|
|
|
|
void
|
|
|
|
|
LiftedCircuit::printClauses (
|
|
|
|
|
const CircuitNode* node,
|
|
|
|
|
ofstream& os,
|
|
|
|
|
string extraOptions)
|
|
|
|
|
{
|
|
|
|
|
const Clauses& clauses = node->clauses();
|
|
|
|
|
if (node->clauses().empty() == false) {
|
|
|
|
|
os << escapeNode (node);
|
|
|
|
|
os << " [shape=box," << extraOptions << "label=\"" ;
|
|
|
|
|
for (size_t i = 0; i < clauses.size(); i++) {
|
|
|
|
|
if (i != 0) os << "\\n" ;
|
|
|
|
|
os << clauses[i];
|
|
|
|
|
}
|
|
|
|
|
os << "\"]" ;
|
|
|
|
|
os << endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|