package splar.plugins.reasoners.bdd.javabdd;
import splar.core.constraints.CNFClause;
import splar.core.constraints.CNFFormula;
import splar.core.constraints.CNFLiteral;
import splar.core.constraints.PropositionalFormula;
import splar.core.fm.FeatureGroup;
import splar.core.fm.FeatureModel;
import splar.core.fm.FeatureTreeNode;
import splar.core.fm.SolitaireFeature;
import splar.core.fm.clustering.FeatureModelClustersManager;
import splar.core.fm.clustering.NodeCluster;
import splar.core.heuristics.VariableOrderingHeuristic;
import net.sf.javabdd.BDD;
import net.sf.javabdd.BDDFactory;
import net.sf.javabdd.BDDFactory.ReorderMethod;
public class FMReasoningWithBDD extends FTReasoningWithBDD {
public FMReasoningWithBDD(FeatureModel featureModel, VariableOrderingHeuristic voHeuristic, int nodeNum, int cacheSize, long maxBuildingtime, String orderingFormulasStrategy) {
this(featureModel, voHeuristic, nodeNum, cacheSize, maxBuildingtime, BDDFactory.REORDER_NONE, orderingFormulasStrategy);
}
public FMReasoningWithBDD(FeatureModel featureModel, VariableOrderingHeuristic voHeuristic, int nodeNum, int cacheSize, long maxBuildingtime, ReorderMethod reorderMethod, String orderingFormulasStrategy) {
super(featureModel, voHeuristic, nodeNum, cacheSize, maxBuildingtime, reorderMethod, orderingFormulasStrategy);
}
protected BDD createBDDStructure(long startTime, String orderingFormulasStrategy) throws BDDExceededBuildingTimeException {
BDD bdd = null;
if ( orderingFormulasStrategy.compareToIgnoreCase("pre-order-cluster") == 0 ) {
// System.out.println("Using strategy: " + orderingFormulasStrategy);
FeatureModelClustersManager clustersManager = new FeatureModelClustersManager(featureModel);
clustersManager.createClusters();
bdd = preOrderClusterFormulaOrdering(clustersManager,featureModel.getRoot(), startTime);
}
else {
// System.out.println(">>>>> Generating BDD for Feature Tree...");
long start = System.nanoTime();
bdd = super.createBDDStructure(startTime, orderingFormulasStrategy);
long end = System.nanoTime();
// System.out.println(">>>>> Done Generating BDD for Feature Tree: " + ((end-start)/1E6) + " ms");
// System.out.println(">>>>> Generating BDD for Extra Constraints......");
start = System.nanoTime();
for( PropositionalFormula pf : featureModel.getConstraints() ) {
String formula = pf.getFormula();
if ( formula != null ) {
if ( formula.trim().length() > 0 ) {
long maxParsingTime = (startTime+maxBuildingTime) - (System.currentTimeMillis());
PF2BDDParser parser = new PF2BDDParser(bddFactory, varName2IndexMap, maxParsingTime);
try {
BDD tempBDD = parser.parse(formula);
if ( tempBDD != null ) {
bdd.andWith(tempBDD);
}
}
catch (Exception e) {
// TODO: handle exception
}
}
}
}
end = System.nanoTime();
// System.out.println(">>>>> Done Generating BDD for Extra Constraints: " + ((end-start)/1E6) + " ms");
}
return bdd;
}
protected BDD preOrderClusterFormulaOrdering(FeatureModelClustersManager clustersManager, FeatureTreeNode curNode, long startTime) throws BDDExceededBuildingTimeException {
BDD bdd = bddFactory.one();
BDD parentNodeBDD = bddFactory.ithVar(varName2IndexMap.get(curNode.getID()));
int count = curNode.getChildCount();
if ( count > 0 ) {
BDD childBDD = null;
for( int i = 0 ; i < count ; i++ ) {
FeatureTreeNode childNode = ((FeatureTreeNode)curNode.getChildAt(i));
// It's a solitaire feature
if ( childNode instanceof SolitaireFeature ) {
SolitaireFeature solitaireNode = (SolitaireFeature)childNode;
childBDD = bddFactory.ithVar(varName2IndexMap.get(childNode.getID()));
// if node is optional relation is "child implies parent"
if ( solitaireNode.isOptional() ) {
bdd.andWith(childBDD.imp(parentNodeBDD.id()));
}
// if node is mandatory relation is "child iff parent"
else {
bdd.andWith(childBDD.biimp(parentNodeBDD.id()));
}
// recursive call
BDD subtreeBDD = preOrderClusterFormulaOrdering(clustersManager, childNode, startTime);
bdd.andWith(subtreeBDD);
}
// It's a feature group
else if ( childNode instanceof FeatureGroup ) {
FeatureGroup fGroup = (FeatureGroup)childNode;
BDD fgBDD = createFeatureGroupBDDStructure(parentNodeBDD.id(),fGroup, null, bddFactory, startTime);
bdd.andWith(fgBDD);
// recursive call
for( int j = 0 ; j < fGroup.getChildCount() ; j++ ) {
FeatureTreeNode groupedNode = (FeatureTreeNode)fGroup.getChildAt(j);
// recursive call
BDD subtreeBDD = preOrderClusterFormulaOrdering(clustersManager, groupedNode, startTime);
bdd.andWith(subtreeBDD);
}
}
else {
System.out.println("Error: Other type of node!");
}
}
}
// generate BDD for cluster EC constraints
for( NodeCluster cluster : clustersManager.sortClusterAscendingOrder(curNode) ) {
if ( cluster.getECClauses() != null ) {
long start = System.nanoTime();
System.out.println(">>>>> Generating BDD for Extra Constraint relations..." + curNode.getID());
for( CNFClause clause : cluster.getECClauses() ) {
BDD clauseBDD = bddFactory.zero();
for( CNFLiteral literal : clause.getLiterals() ) {
if ( literal.isPositive() ) {
clauseBDD.orWith(bddFactory.ithVar(varName2IndexMap.get(literal.getVariable().getID())));
}
else {
clauseBDD.orWith(bddFactory.nithVar(varName2IndexMap.get(literal.getVariable().getID())));
}
}
bdd.andWith(clauseBDD);
}
long end = System.nanoTime();
System.out.println(">>>>> Done Generating BDD for Extra Constraint relations..." + curNode.getID() + " (" + ((end-start)/1E6) + "ms)");
}
}
return bdd;
}
protected CNFFormula toCNF() {
return featureModel.FM2CNF();
}
}