package splar.apps.experiments; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import net.sf.javabdd.BDDFactory; import net.sf.javabdd.BDDFactory.ReorderMethod; import splar.core.constraints.CNFFormula; import splar.core.fm.FeatureModel; import splar.core.fm.FeatureModelException; import splar.core.fm.FeatureModelStatistics; import splar.core.fm.XMLFeatureModel; import splar.core.heuristics.FORCEVariableOrderingHeuristic; import splar.core.heuristics.FTPreOrderSortedECTraversalHeuristic; import splar.core.heuristics.FTPreOrderTraversalHeuristic; import splar.core.heuristics.VariableOrderingHeuristic; import splar.core.heuristics.VariableOrderingHeuristicsManager; import splar.plugins.reasoners.bdd.javabdd.FMReasoningWithBDD; import splar.plugins.reasoners.bdd.javabdd.ReasoningWithBDD; public class ScalabilityExperiments { public static void main(String args[]) { ScalabilityExperiments exp = new ScalabilityExperiments(); String parms[] = args; if ( parms.length < 1 ) { parms= new String[1]; parms[0] = "memory-overflow"; } exp.init(parms); } String resultsOutputPath = "c:\\users\\marcilio\\eclipse\\4watreason\\experiments\\thesis\\analysis\\"; String resultsOutputFileName = "scalability_results.txt"; String restoreFilePath = "c:\\users\\marcilio\\eclipse\\4watreason\\experiments\\thesis\\scalability\\"; String restoreFileName = "_restore.txt"; String collectionPath = "c:\\users\\marcilio\\eclipse\\4watreason\\experiments\\thesis\\scalability\\files\\"; CollectionData collections[] = createCollections(); String heuristics[] = {"Pre-CL-MinSpan"};//, "Pre-CL-Size", "Pre"}; boolean simplifyModels = true; int modelStartIndex = 4; long bddTimeout = 60 * 60000; int bddNodeNum = 5000000; int bddCacheSize = 1000000; double bddNodeTableIncreaseFactor = 0.20; double bddMinimumGCFactor = 0.20; ReorderMethod reorderMethod = BDDFactory.REORDER_NONE; int collectionCurIndex = 0; int heuristicCurIndex = 0; int modelCurIndex = modelStartIndex; private CollectionData[] createCollections() { CollectionData[] collections = new CollectionData[1]; // collections[0] = new CollectionData("FM-1000-SAT-20", 10); // collections[1] = new CollectionData("FM-1500-SAT-20", 10); // collections[0] = new CollectionData("FM-2000-SAT-20", 10); collections[0] = new CollectionData("FM-2500-SAT-20", 4); // collections[4] = new CollectionData("FM-3000-SAT-20", 10); // collections[5] = new CollectionData("FM-3500-SAT-20", 10); // collections[6] = new CollectionData("FM-4000-SAT-20", 10); return collections; } public void init(String args[]) { if ( restoreState(args[0]) ) { logLastFailure(collectionCurIndex); modelCurIndex++; // skip the failing model } initializeHeuristics(null); for( int collectionIndex = collectionCurIndex ; collectionIndex < collections.length ; collectionIndex++ ) { for( int heuristicIndex = heuristicCurIndex ; heuristicIndex < heuristics.length ; heuristicIndex++ ) { for( int modelIndex = modelCurIndex ; modelIndex <= collections[collectionIndex].size ; modelIndex++ ) { String modelName = getModelToProcess(collectionIndex, modelIndex); String heurName = heuristics[heuristicIndex]; System.out.println("-------------------------------------------------------" ); System.out.println("Processing: [" + modelName + ", " + heurName + "]" ); saveState(collectionIndex, heuristicIndex, modelIndex); TestData data = new TestData(); data.heuristic = heurName; data.modelName = modelName; // if ( Math.abs(new Random().nextInt())% 5 == 0 ) { // System.exit(-1); // } FeatureModel fm = new XMLFeatureModel(collectionPath+modelName+".xml", XMLFeatureModel.SET_ID_AUTOMATICALLY); try { fm.loadModel(); } catch (FeatureModelException e) { e.printStackTrace(); } FeatureModelStatistics stats = new FeatureModelStatistics(fm); stats.update(); data.fmSize = stats.countFeatures(); data.fmMan = stats.countMandatory(); data.fmOpt = stats.countOptional(); data.fmGrp1 = stats.countGrouped11(); data.fmGrpn = stats.countGrouped1n(); data.ecClauses = stats.countExtraConstraintCNFClauses(); data.ECR = ((stats.countConstraintVars()*1.0)/data.fmSize); data.simplified = 0; if ( simplifyModels ) { fm.shrink(); stats.update(); data.simplified = 1; } data.fmSizeSimp = stats.countFeatures(); data.ECRSimp = ((1.0*stats.countConstraintVars())/data.fmSizeSimp); VariableOrderingHeuristic heurObject = VariableOrderingHeuristicsManager.createHeuristicsManager().getHeuristic(heurName); heurObject.setParameter("feature_model", fm); heurObject.setParameter("start_node", "output"); CNFFormula cnf = fm.FM2CNF(); System.out.println(">> Running heuristic..."); heurObject.run(cnf); data.heurTime = heurObject.getRunningTime(); System.out.println(">> done! (" + data.heurTime +"ms)"); ReasoningWithBDD reasoning = new FMReasoningWithBDD(fm, heurObject, bddNodeNum, bddCacheSize, bddTimeout, reorderMethod, "pre-order"); try { System.out.println(">> Building BDD..."); reasoning.init(); data.timeout = 0; System.out.println(">> done! (" + reasoning.getBDD().nodeCount() + " BDD nodes - " + reasoning.getBDDBuildingTime() +"ms)"); } catch (Exception e) { System.out.println(">>> Timeout: > " +bddTimeout); data.timeout = 1; System.out.println(">> done! (timed out!)"); } data.bddTime = reasoning.getBDDBuildingTime(); data.bddSize = reasoning.getBDD().nodeCount(); data.sifting = 0; data.span = cnf.calculateClauseSpan(VariableOrderingHeuristic.variableOrderingAsHashMap(heurObject.getVariableOrdering())); long tempTime = System.nanoTime(); reasoning.getBDD().satCount(); data.timeToCountBDDSolutions = ((System.nanoTime()-tempTime)/1000000.0); logData(data, collectionIndex); } saveState(collectionIndex, heuristicIndex, collections[collectionIndex].size+1); modelCurIndex = modelStartIndex; if ( heuristicIndex < heuristics.length-1 ) { startNewHeuristicInLog(collectionIndex); } } heuristicCurIndex = 0; } } private void initializeHeuristics(FeatureModel featureModel) { new FTPreOrderTraversalHeuristic("Pre", featureModel); // new Fujita88DFSCircuitTraversalHeuristic("Fuj-88", null, "output"); new FTPreOrderSortedECTraversalHeuristic("Pre-CL-MinSpan", featureModel, FTPreOrderSortedECTraversalHeuristic.FORCE_SORT); new FTPreOrderSortedECTraversalHeuristic("Pre-CL-Size", featureModel, FTPreOrderSortedECTraversalHeuristic.SIZE_SORT); new FORCEVariableOrderingHeuristic("FORCE", null, 1); // new FORCEVariableOrderingHeuristic("Pre-CLS-FORCE", null, 1); // new FORCEVariableOrderingHeuristic("Pre-CLM-FORCE", null, 1); } private String getModelToProcess(int collectionIndex, int modelIndex) { return collections[collectionIndex].name + "-" + modelIndex; } private String getOutputFileName(int collectionIndex) { return collections[collectionIndex].name + "-" + resultsOutputFileName; } private void startNewHeuristicInLog(int collectionIndex) { try { System.out.println("SPACES --------------"); java.io.File file = new File(resultsOutputPath + getOutputFileName(collectionIndex)); FileWriter writer = new FileWriter(file,true); writer.write("--\r\n--\r\n"); writer.close(); } catch( IOException e2) { e2.printStackTrace(); } } private void logLastFailure(int collectionIndex) { try { java.io.File file = new File(resultsOutputPath + getOutputFileName(collectionIndex)); // System.out.println(">> Logging failure data in " + file.getName() + "..."); FileWriter writer = new FileWriter(file,true); String line = ""; line += heuristics[heuristicCurIndex]; line += ","; line += getModelToProcess(collectionCurIndex, modelCurIndex); line += ","; line += "Memory Overflow"; writer.write(line+"\r\n"); writer.close(); } catch( IOException e2) { e2.printStackTrace(); } } private void logData(TestData data, int collectionIndex) { try { java.io.File file = new File(resultsOutputPath + getOutputFileName(collectionIndex)); System.out.println(">> Logging data in " + file.getName() + "..."); FileWriter writer = new FileWriter(file,true); String line = ""; line += data.heuristic; line += ","; line += data.modelName; line += ","; line += data.heurTime; line += ","; line += data.bddTime; line += ","; line += (data.bddTime+data.heurTime); line += ","; line += data.timeout; line += ","; line += data.fmSize; line += ","; line += data.fmSizeSimp; line += ","; line += data.simplified; line += ","; line += data.fmMan; line += ","; line += data.fmOpt; line += ","; line += data.fmGrp1; line += ","; line += data.fmGrpn; line += ","; line += data.ecClauses; line += ","; line += data.ECR; line += ","; line += data.ECRSimp; line += ","; line += data.bddTablePeek; line += ","; line += data.bddSizePeek; line += ","; line += data.sifting; line += ","; line += data.bddSize; line += ","; line += (data.bddSize/data.fmSize); line += ","; line += data.span; line += ","; line += data.timeToCountBDDSolutions; writer.write(line+"\r\n"); writer.close(); } catch( IOException e2) { e2.printStackTrace(); } } // returns true if the program crashed in a previous run // or false if the program was manually stopped or never interrupted private boolean restoreState(String typeOfInterruption) { java.io.File file = new File(restoreFilePath + restoreFileName); try { if ( file.exists() ) { // System.out.println(">> Restoring system's state " + file.getName() + "..."); DataInputStream stream = new DataInputStream(new FileInputStream(file)); collectionCurIndex = stream.readInt(); heuristicCurIndex = stream.readInt(); modelCurIndex = stream.readInt(); System.out.println(">> Indexes restored: [collection=" + collectionCurIndex+", heuristic=" + heuristicCurIndex + ", model=" + modelCurIndex + "]"); stream.close(); if ( typeOfInterruption.compareToIgnoreCase("manual-stop") == 0 ) { System.out.println("Type of interruption: Manual"); return false; } if ( modelCurIndex > collections[collectionCurIndex].size ) { return false; } return true; } } catch( FileNotFoundException e1) { } catch( IOException e2) { e2.printStackTrace(); } return false; } private void saveState(int collectionIndex, int heuristicIndex, int modelIndex) { java.io.File file = new File(restoreFilePath + restoreFileName); try { // System.out.println(">> Saving system's state " + file.getName() + "..."); DataOutputStream stream = new DataOutputStream(new FileOutputStream(file)); stream.writeInt(collectionIndex); stream.writeInt(heuristicIndex); stream.writeInt(modelIndex); // System.out.println(">> Indexes saved: [collection=" + // collectionIndex+", heuristic=" + // heuristicIndex + // ", model=" + modelIndex + // "]"); stream.close(); } catch( IOException e2) { e2.printStackTrace(); } } } class CollectionData { public CollectionData(String name, int size) { this.name = name; this.size = size; } public String name; public int size; } class TestData { public String heuristic; public String modelName; public double heurTime; public long bddTime; public long bddSize; public int timeout; public int simplified; public int fmSize; public int fmSizeSimp; public int fmMan; public int fmOpt; public int fmGrp1; public int fmGrpn; public int ecClauses; public double ECR; public double ECRSimp; public long bddTablePeek; public long bddSizePeek; public long sifting; public int span; public double timeToCountBDDSolutions; }