package splar.core.fm; import java.util.Iterator; import splar.core.constraints.CNFClause; import splar.core.constraints.CNFFormula; import splar.core.constraints.PropositionalFormula; public class FeatureModelStatistics { private FeatureModel fm; int root=0; int opt = 0; int man = 0; int grp11 = 0; int grp1n = 0; int fgrp11 = 0; int fgrp1n = 0; public FeatureModelStatistics(FeatureModel fm) { this.fm = fm; } public FeatureModel getFeatureModel() { return fm; } public void reset() { root=0; opt = 0; man = 0; grp11 = 0; grp1n = 0; fgrp11 = 0; fgrp1n = 0; } public void update() { reset(); for( Iterator<FeatureTreeNode> it = fm.nodesIterator(); it.hasNext() ; ) { FeatureTreeNode node = it.next(); if ( node instanceof RootNode ) { root++; } else if ( node instanceof SolitaireFeature ) { if ( ((SolitaireFeature)node).isOptional() ) { opt++; } else { man++; } } else if ( node instanceof GroupedFeature ) { FeatureGroup fg = (FeatureGroup)(node.getParent()); int min = fg.getMin(); int max = fg.getMax(); if ( min == max && min == 1) { grp11++; } else if ( min == 1 && (max == -1 || max == fg.getChildCount())){ grp1n++; } } else if ( node instanceof FeatureGroup ) { FeatureGroup fg = (FeatureGroup)node; int min = fg.getMin(); int max = fg.getMax(); if ( min == max && min == 1) { fgrp11++; } else if ( min == 1 && (max == -1 || max == fg.getChildCount())){ fgrp1n++; } } } } public int countNodes() { return fm.countNodes(); } public int countFeatures() { return root+opt+man+grp11+grp1n; } public int depth() { return fm.depth(); } public int countMandatory() { return this.man; } public int countOptional() { return this.opt; } public int countGrouped() { return this.grp11 + this.grp1n; } public int countGrouped11() { return this.grp11; } public int countGrouped1n() { return this.grp1n; } public int countGroups11() { return this.fgrp11; } public int countGroups1N() { return this.fgrp1n; } public int countConstraints() { return fm.countConstraints(); } public int countConstraintVars() { return fm.countConstraintsVariables(); } public double getAverageDepth() { return fm.getAverageDepth(); } public double getDepthStandardDeviation() { return fm.getDepthStandardDeviation(); } public double getDepthDeviationCoeficient() { return fm.getDepthDeviationCoeficient(); } public int countFeatureModelCNFClauses() { return fm.FM2CNF().countClauses(); } public int countFeatureTreeCNFClauses() { return fm.FT2CNF().countClauses(); } public int countExtraConstraintCNFClauses() { return fm.EC2CNF().countClauses(); } public int[] count23NClauses() { int clauseSizeCounter[] = new int[3]; java.util.Arrays.fill(clauseSizeCounter, 0); for( CNFClause clause : fm.FM2CNF().getClauses() ) { int numVars = clause.countVariables(); if ( numVars == 2) { clauseSizeCounter[0]++; } else if ( numVars == 3) { clauseSizeCounter[1]++; } else { clauseSizeCounter[2]++; } } return clauseSizeCounter; } public double getECClauseDensity() { CNFFormula cnf = fm.EC2CNF(); return (cnf == null) ? 0 : cnf.getClauseDensity(); } public double getECRepresentativeness() { return fm.countConstraintsVariables()/(1.0*fm.countFeatures()); } // decisions = number of times a feature has been assigned a truth value public long countDecisions() { return fm.getInstantiatedNodes().size(); } public int countInstantiatedNodes() { return fm.getInstantiatedNodes().size(); } public int countUninstantiatedNodes() { return fm.countNodes()-fm.getInstantiatedNodes().size(); } public String toString() { StringBuffer str = new StringBuffer(100); str.append("*************************************************************"); str.append("\r\nFEATURE TREE STATISTICS"); str.append("\r\n"); str.append(" Model name.: " + fm.getName()); str.append("\r\n"); str.append(" tree depth.: "); str.append(fm.depth()); str.append("\r\n"); // str.append("depth (average): " + fm.getAverageDepth()); // str.append(fm.depth()); // str.append("\r\n"); // str.append("depth (standard deviation): " + getDepthStandardDeviation() + " (" + (getDepthDeviationCoeficient()*100) +"%) - (gives a notion of the tree balancing)"); // str.append("\r\n"); str.append(" #root......: "); str.append(root); str.append("\r\n"); str.append(" #opt.......: "); str.append(opt); str.append("\r\n"); str.append(" #man.......: "); str.append(man); str.append("\r\n"); str.append(" #grouped...: "); str.append(grp11+grp1n); str.append("\r\n"); str.append(" #grouped [1,1]: "); str.append(grp11); str.append("\r\n"); str.append(" #grouped [1,n]: "); str.append(grp1n); str.append("\r\n"); str.append(" #fgrp [1,1]: "); str.append(fgrp11); str.append(" (exclusive-OR)\r\n"); str.append(" #fgrp [1,N]: "); str.append(fgrp1n); str.append(" (inclusive-OR)\r\n"); str.append(" #total features: "); str.append(countFeatures()); str.append("\r\n"); str.append(" #total nodes: "); str.append((root+opt+man+grp11+grp1n+fgrp11+fgrp1n)); String formula = ""; int countConstraints = 0; for( Iterator<PropositionalFormula> it = fm.getConstraints().iterator() ; it.hasNext() ; ) { PropositionalFormula pf = it.next(); formula += "(" + pf.getFormula() + ")"; if ( it.hasNext() ) { formula += " AND "; } countConstraints++; } try { // PropositionalFormula pf = new PropositionalFormula("", formula); // str.append("\n#constraints........: " + countConstraints); // str.append("\n#vars in constraints: " + pf.getVariables().size()); // int numCNFClauses = countFeatureModelCNFClauses(); // str.append("\n#CNF clauses........: " + numCNFClauses + " (Feature Tree + Extra Constraints)"); // int clausesSize[] = count23NClauses(); // str.append("\n 2-variable clauses........: " + clausesSize[0]); // str.append("\n 3-variable clauses........: " + clausesSize[1]); // str.append("\n > 3-variable clauses......: " + clausesSize[2]); // str.append("\n hardness if 2+p-SAT.......: " + clausesSize[2]/(1f*numCNFClauses) + "(<0.4: polynomial behavior, >=0.4: hard)"); // str.append("\nCNF CLAUSES: Feature Tree "); // str.append(cnfGenerator.getStats(fm.FT2CNF().getClauses())); // str.append("\nCNF CLAUSES: Cross-Tree Constraints "); // str.append(cnfGenerator.getStats(fm.EC2CNF().getClauses())); // str.append("\nCNF CLAUSES: Entire Feature Model"); // str.append(cnfGenerator.getStats(fm.FM2CNF().getClauses())); } catch( Exception e) { e.printStackTrace(); } return str.toString(); } public void dump() { System.out.println(toString()); } }