package statechart.evolve; import java.io.File; import java.io.FileOutputStream; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.xmi.XMLResource; import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; import statechart.Model; import statechart.Node; import statechart.StatechartPackage; import statechart.evolve.Mutate.Action; public class Runner { //////These are parameters that can be changed by the user. Ideally they should go in a resource file!////// // each action {ADD, EXPAND, REMOVE} has probability 1/probabilities to happen for every node; the rest goes to do NOTHING private static int probabilities = 100; private static int maxNumGenerations = 10; private static int maxNumIncrPopulation = 6; /////////////////////////////////////////////////////////////////////////////////////////////////////// public static void main(String[] args) { for (int gen=0; gen<maxNumGenerations; gen++) { int maxPop = (int)Math.min(Math.pow(2,gen), Math.pow(2,maxNumIncrPopulation)); for (int pop=1; pop<=maxPop; pop++) { String input = (gen < 10 ? "0" : "") + gen + "_" + (pop < 10 ? "0" : "") + pop + ".sct"; String output1 = (gen+1 < 10 ? "0" : "") + (gen+1) + "_" + (pop < 10 ? "0" : "") + pop + ".sct"; generateNewModel(input, output1); if(gen < maxNumIncrPopulation) { int new_pop= (int)(Math.pow(2,gen)+pop); String output2 = "0" + (gen+1) + "_" + (new_pop < 10 ? "0" : "") + new_pop + ".sct"; generateNewModel(input, output2); } } int numModels = gen < maxNumIncrPopulation ? 2*maxPop : maxPop; System.out.println("Finished generation " + (gen+1 < 10 ? "0" : "") + (gen+1) + ": " + (numModels < 10 ? "0" : "") + numModels + " models produced (filenames: " + (gen+1 < 10 ? "0" : "") + (gen+1) + "_xx.sct)"); } } // gets an input model and outputs an output model of the next generation (after mutation) public static void generateNewModel(String inputName, String outputName) { // Create a new generation model instance Model outputModel = getResourceModel(inputName); //print the model to the console (just debugging) //printModel(r); // mutation code: boolean output_equals_input = true; boolean isMutable = true; // run until at least one change is made to the outputModel while(output_equals_input) { // find the root of the tree Node root = findRoot(outputModel); // the for loop below can break sometimes as the tree is changing dynamically // adding a children somewhere at random could break the iterator try { // for each children of the root for (Node child : root.getChildren()) { // mutate only if the node is BASIC, OR, CONDITION if(child.getType().equalsIgnoreCase("BASIC") || child.getType().equalsIgnoreCase("OR") || child.getType().equalsIgnoreCase("CONDITION")) { Action action = Mutate.selectAction(child, probabilities); switch (action) { case ADD: Mutate.addNode(outputModel, child); Mutate.performRelabelling(outputModel); isMutable = checkModelSuitability(outputModel); if(isMutable==true) output_equals_input = false; else outputModel = getResourceModel(inputName); break; case EXPAND: Mutate.expandNode(outputModel, child); Mutate.performRelabelling(outputModel); isMutable = checkModelSuitability(outputModel); if(isMutable==true) output_equals_input = false; else outputModel = getResourceModel(inputName); break; case REMOVE: List<Node> toBeDeleted = new LinkedList<Node>(); // collect all the nodes to be deleted (removing all transitions at the same time) Mutate.collectNodes(outputModel, child, toBeDeleted); // remove collected nodes Mutate.removeNodes(outputModel, toBeDeleted); Mutate.performRelabelling(outputModel); isMutable = checkModelSuitability(outputModel); if(isMutable==true) output_equals_input = false; else outputModel = getResourceModel(inputName); break; case NOTHING: break; } } }// end for } catch (Exception e) { break; // exit for loop; the model is already mutated and this for is problematic } } // save the output model ResourceSet resourceSet = getResourceSet(); Resource newResource = resourceSet.createResource(URI.createURI("http://statechart/1.0")); newResource.getContents().add(outputModel); try { FileOutputStream out = new FileOutputStream(new File(outputName)); newResource.save(out, getOptions()); } catch (Exception e) { System.out.println("Problem saving the output .xml file!\n"); e.printStackTrace(); } finally { //print outputModel to the console (just debugging) //printModel(newResource); } }// end generateNewModel // returns the root of a tree (model) public static Node findRoot(Model tree) { Node root = null; for (Node iterator : tree.getNodes()) { if(iterator.getLabel().equalsIgnoreCase("0")) { root = iterator; break; } } return root; } // define Options for XML resources public static Map<String, Object> getOptions() { // Options for XML Map<String, Object> options = new HashMap<String, Object>(); options.put(XMLResource.OPTION_ENCODING, "UTF-8"); options.put(XMLResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE); options.put(XMLResource.OPTION_SCHEMA_LOCATION_IMPLEMENTATION, Boolean.TRUE); return options; } // print a model to the console public static void printModel(Resource resource) { Map<String, Object> options = getOptions(); try { resource.save(System.out, options); System.out.println("\n"); } catch (Exception e) { System.out.println("Problem printing input model!\n"); } } // we may end up with a model that cannot be further mutated and we don't want that // so if a model like this appears at some generation, we don't accept it and go back // to the previous model and mutate again // (this method returns the number of nodes that can be further mutated for this model) public static boolean checkModelSuitability(Model model) { Node output_root = findRoot(model); int count_mutable_nodes = 0; // for each children of the root for (Node children : output_root.getChildren()) { if(children.getType().equalsIgnoreCase("BASIC") || children.getType().equalsIgnoreCase("OR") || children.getType().equalsIgnoreCase("CONDITION")) { count_mutable_nodes += 1; } } if (count_mutable_nodes<1) return false; else return true; } // returns input model from resource file public static ResourceSet getResourceSet() { ResourceSet resourceSet = new ResourceSetImpl(); // Register the appropriate resource factory to handle all file extensions resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(Resource.Factory.Registry.DEFAULT_EXTENSION, new XMIResourceFactoryImpl()); // Register the package to ensure it is available during loading. resourceSet.getPackageRegistry().put(StatechartPackage.eNS_URI, StatechartPackage.eINSTANCE); return resourceSet; } // returns input model from resource file public static Model getResourceModel(String inputFile) { ResourceSet rSet = getResourceSet(); Resource r = rSet.getResource(URI.createFileURI(inputFile), true); Model inputModel = (Model) r.getContents().get(0); return inputModel; } }// end Runner