package at.ac.tuwien.iter.services.impl.evo; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import matlabcontrol.MatlabInvocationException; import org.apache.tapestry5.ioc.services.TypeCoercer; import org.slf4j.Logger; import at.ac.tuwien.iter.data.Test; import at.ac.tuwien.iter.data.TestResult; import at.ac.tuwien.iter.services.LoadGenerator; import at.ac.tuwien.iter.services.MathEngineDao; import at.ac.tuwien.iter.services.TestSuiteEvolver; /** * * This class evolve the test suites by exploiting GPML models as describe in * the ESEC/FSE 2013 NIER-PAPER * * @author alessiogambi * */ public class GPMLBasedPlasticityEvolver implements TestSuiteEvolver { private Logger logger; private TypeCoercer typeCoercer; private LoadGenerator loadGenerator; private MathEngineDao mathEngineDao; private int nBestPredictions; private int limitCount; private int minDistance; private Map<Test, Integer> hitCount; private Collection<TestResult> testResults; public GPMLBasedPlasticityEvolver(Logger logger, TypeCoercer typeCoercer, LoadGenerator loadGenerator, MathEngineDao mathEngineDao, int nBestPredictions, int limitCount, int minDistance) { super(); this.logger = logger; this.typeCoercer = typeCoercer; this.loadGenerator = loadGenerator; this.mathEngineDao = mathEngineDao; this.nBestPredictions = nBestPredictions; this.limitCount = limitCount; this.minDistance = minDistance; // ? this.hitCount = new HashMap<Test, Integer>(); this.testResults = new ArrayList<TestResult>(); } public Collection<Test> evolveTestSuite(Collection<Test> testSuite, Collection<TestResult> testResults) { int newTests = 0; // Store only the new testResults for (TestResult testResult : testResults) { if (this.testResults.contains(testResult)) { logger.debug("TestResult " + testResult.getTestId() + " is not new"); } else { try { logger.debug("Storing " + testResult.getTestId()); mathEngineDao.addTestExecution(testResult); this.testResults.add( testResult ); newTests++; } catch (Throwable e) { logger.warn("Cannot add " + testResult.getTestId() + " to Matlab", e); } } } logger.info(String.format("Added %d new tests to the search !", newTests)); logger.info("Try to get the first " + nBestPredictions + " best expected improvements"); Collection<Test> newExperiments = new ArrayList<Test>(); try { // NOTE HERE We must make the search generic ! /* * IMPORTANT: Now that we use the discrete/integer problem we run * into a non-termination issue, this results in the call possibly * returning again the same tests. We need to deal with it: the * heuristic is to take a random test 'far-away' from the repeated * one and move on. If the same happens several time we are * confident that the 'real' optimum is actually the one returned. */ List<double[]> newParameters = mathEngineDao .getBestPlasticityTests(nBestPredictions); for (double[] _params : newParameters) { int i = (int) _params[0]; int j = (int) _params[1]; double maxEI = _params[2]; logger.info("Max(E[I]) = " + maxEI + " for Transition (" + i + "->" + j + ")"); double[] params = new double[_params.length - (2 + 1)]; System.arraycopy(_params, 3, params, 0, params.length); // Do the check ! Test newTest = loadGenerator.generateTest(typeCoercer.coerce( params, Number[].class)); if (testSuite.contains(newTest)) { // TODO How this reacts to our test repetitions? logger.info("IterImpl.evolveTestSuite() CHECK FAILED WE ALREADY COLLECTED THIS TEST !"); int hitcount = hitCount.get(newTest) + 1; if (hitcount < limitCount) { newTest = loadGenerator.generatePseudoRandomTest( minDistance, typeCoercer.coerce(params, Number[].class)); } else { logger.warn("IterImpl.evolveTestSuite() Max hit count reached. Do not add the test ! "); continue; } } newExperiments.add(newTest); } } catch (MatlabInvocationException e) { // TODO : Here we need to understand if the problem is due to the // impossibility of training the interpolator or other, // in one case we must add new data/random in other case not logger.error( "Iter.start() Something went wrong, try to add some more random experiment", e); // TODO This should be configurable as well, isn;t it ? // Generate random n tests ! for (int experiment = 0; experiment < nBestPredictions; experiment++) { newExperiments.add(loadGenerator.generateRandomCase()); } } catch (Exception e) { // e.printStackTrace(); logger.error(" Generic Error!!! Exit", e); } return newExperiments; } }