package Sequenic.T2ext.CoverageEngine.ga; import java.util.LinkedList; import java.util.List; import java.util.Random; import org.uncommons.watchmaker.framework.EvolutionaryOperator; import Sequenic.T2.Engines.BaseEngine; import Sequenic.T2.Engines.BaseEngineToolPlug; import Sequenic.T2.Obj.Cloner; import Sequenic.T2.Seq.CALL_METHOD; import Sequenic.T2.Seq.CONST; import Sequenic.T2.Seq.MkValStep; import Sequenic.T2.Seq.ReportersPool; import Sequenic.T2.Seq.Trace; import Sequenic.T2.Seq.TraceStep; /** * This is an EvolutionaryOperator that can mutate traces. * * @author Christiaan Hees */ public class TraceMutation implements EvolutionaryOperator { private Random rng; private String[] t2Args; public TraceMutation(String[] t2Args) { this.t2Args = t2Args; } /** * Removes, adds and modifies steps from the selected traces. * @see EvolutionaryOperator#apply(List, Random) */ @Override public List apply(List selectedCandidates, Random rng) { this.rng = rng; List result = new LinkedList(); for(S trace : selectedCandidates) { // Clone the trace: try { trace = Cloner.clone(trace); } catch (Exception e) { System.out.println("Failed to clone trace "+trace); e.printStackTrace(); System.exit(1); } // Mutate it: removeStep(trace); insertStep(trace); changeParams(trace); // TODO crossover? result.add(trace); } return result; } /** * Possibly removes a single step in a random position from the trace. * The object creation step is never removed. */ private void removeStep(Trace t) { // TODO tweak probability if(t.trace.size() <= 0 || rng.nextFloat() > 0.2) { return; } //System.out.println("DEBUG: removing a step from the trace"); t.trace.remove(rng.nextInt(t.trace.size())); // FIXME recalculate REFs } /** * Possibly adds a single random step in a random position to the trace. */ private void insertStep(Trace t) { // TODO tweak probability if(rng.nextFloat() > 0.8) { return; } BaseEngine engine = prepareEngine(); int newStepPos = 0; if(t.trace.size() > 0) newStepPos = rng.nextInt(t.trace.size()); // Remove the steps past the insertion point and save them for later: LinkedList postSteps = new LinkedList(); for(int i=newStepPos; i 0.04) { return; } BaseEngine engine = prepareEngine(); TraceStep s = t.trace.get(rng.nextInt(t.trace.size())); if(s instanceof CALL_METHOD) { for(MkValStep param : ((CALL_METHOD)s).params) { if(param instanceof CONST) { // For now only change the CONST of a CALL_METHOD: //System.out.print("DEBUG changing "+param+" to "); param = engine.META_mkObject(((CONST)param).val.getClass(), 0, false); //System.out.println(param); } } } } /** * Configures a BaseEngine using the original arguments passed to T2. */ private BaseEngine prepareEngine() { BaseEngineToolPlug toolPlug = new BaseEngineToolPlug(); try { toolPlug.configure(t2Args); } catch (Exception e) { e.printStackTrace(); } return toolPlug.getBaseEngine(); // TODO configure the engine to allow more steps and things like that? } }