| 1 | package de.uka.ipd.sdq.dsexplore.helper; |
| 2 | |
| 3 | import java.io.BufferedReader; |
| 4 | import java.io.File; |
| 5 | import java.io.FileInputStream; |
| 6 | import java.io.FileNotFoundException; |
| 7 | import java.io.IOException; |
| 8 | import java.io.InputStreamReader; |
| 9 | import java.net.URL; |
| 10 | import java.util.ArrayList; |
| 11 | import java.util.Collections; |
| 12 | import java.util.Iterator; |
| 13 | import java.util.LinkedList; |
| 14 | import java.util.List; |
| 15 | |
| 16 | import org.apache.log4j.Logger; |
| 17 | import org.eclipse.core.runtime.CoreException; |
| 18 | import org.eclipse.core.runtime.FileLocator; |
| 19 | import org.eclipse.emf.ecore.EObject; |
| 20 | import org.eclipse.emf.ecore.resource.ResourceSet; |
| 21 | import org.eclipse.emf.ecore.util.EcoreUtil; |
| 22 | import org.opt4j.core.Criterion; |
| 23 | import org.opt4j.core.DoubleValue; |
| 24 | import org.opt4j.core.Value; |
| 25 | import org.opt4j.start.Opt4JTask; |
| 26 | |
| 27 | import de.uka.ipd.sdq.context.aggregatedUsageContext.ComputedAggregatedUsage; |
| 28 | import de.uka.ipd.sdq.dsexplore.analysis.AbstractPerformanceAnalysisResult; |
| 29 | import de.uka.ipd.sdq.dsexplore.analysis.IAnalysis; |
| 30 | import de.uka.ipd.sdq.dsexplore.analysis.IAnalysisResult; |
| 31 | import de.uka.ipd.sdq.dsexplore.analysis.PCMPhenotype; |
| 32 | import de.uka.ipd.sdq.dsexplore.exception.ExceptionHelper; |
| 33 | import de.uka.ipd.sdq.dsexplore.launch.DSEConstantsContainer; |
| 34 | import de.uka.ipd.sdq.dsexplore.opt4j.genotype.DesignDecisionGenotype; |
| 35 | import de.uka.ipd.sdq.dsexplore.opt4j.representation.DSEDecoder; |
| 36 | import de.uka.ipd.sdq.dsexplore.opt4j.representation.DSEEvaluator; |
| 37 | import de.uka.ipd.sdq.dsexplore.opt4j.representation.DSEIndividual; |
| 38 | import de.uka.ipd.sdq.dsexplore.opt4j.representation.DSEIndividualBuilder; |
| 39 | import de.uka.ipd.sdq.dsexplore.opt4j.representation.DSEObjectives; |
| 40 | import de.uka.ipd.sdq.dsexplore.opt4j.representation.DSEProblem; |
| 41 | import de.uka.ipd.sdq.dsexplore.opt4j.start.Opt4JStarter; |
| 42 | import de.uka.ipd.sdq.dsexplore.qml.handling.QMLConstantsContainer; |
| 43 | import de.uka.ipd.sdq.dsexplore.qml.reader.QMLDimensionReader; |
| 44 | import de.uka.ipd.sdq.pcm.core.entity.Entity; |
| 45 | import de.uka.ipd.sdq.pcm.designdecision.Candidate; |
| 46 | import de.uka.ipd.sdq.pcm.designdecision.Candidates; |
| 47 | import de.uka.ipd.sdq.pcm.designdecision.Choice; |
| 48 | import de.uka.ipd.sdq.pcm.designdecision.DegreeOfFreedomInstance; |
| 49 | import de.uka.ipd.sdq.pcm.resourceenvironment.LinkingResource; |
| 50 | import de.uka.ipd.sdq.pcm.resourceenvironment.ProcessingResourceSpecification; |
| 51 | import de.uka.ipd.sdq.pcm.resourceenvironment.ResourceContainer; |
| 52 | import de.uka.ipd.sdq.pcm.resourcetype.ResourceType; |
| 53 | import de.uka.ipd.sdq.pcm.resultdecorator.ResultDecoratorRepository; |
| 54 | import de.uka.ipd.sdq.pcm.resultdecorator.ResultdecoratorFactory; |
| 55 | import de.uka.ipd.sdq.pcm.resultdecorator.resourceenvironmentdecorator.ActiveResourceUtilisationResult; |
| 56 | import de.uka.ipd.sdq.pcm.resultdecorator.resourceenvironmentdecorator.LinkingResourceResults; |
| 57 | import de.uka.ipd.sdq.pcm.resultdecorator.resourceenvironmentdecorator.ProcessingResourceSpecificationResult; |
| 58 | import de.uka.ipd.sdq.pcm.resultdecorator.resourceenvironmentdecorator.ResourceenvironmentdecoratorFactory; |
| 59 | import de.uka.ipd.sdq.pcmsolver.models.PCMInstance; |
| 60 | import de.uka.ipd.sdq.statistics.estimation.ConfidenceInterval; |
| 61 | import de.uka.ipd.sdq.workflow.exceptions.UserCanceledException; |
| 62 | import de.uka.ipd.sdq.workflow.mdsd.blackboard.MDSDBlackboard; |
| 63 | |
| 64 | public class GenotypeReader { |
| 65 | |
| 66 | /**QUICKHACK need to inject objectives!!!**/ |
| 67 | private static Opt4JTask task = null; |
| 68 | public static void setTask(Opt4JTask t){ |
| 69 | task = t; |
| 70 | } |
| 71 | |
| 72 | private static final String SEPARATOR = ";"; |
| 73 | |
| 74 | /** Logger for log4j. */ |
| 75 | private static Logger logger = |
| 76 | Logger.getLogger("de.uka.ipd.sdq.dsexplore.helper.GenotypeReader"); |
| 77 | |
| 78 | /** |
| 79 | * Reads the genotypes from the specified files. |
| 80 | * If the file contains pretty printed genotypes and |
| 81 | * objectives are given, reads them and updates the DSEEvaluator cache |
| 82 | * by calling DSEEvaluator.addToPhenotypeCache(..). Requires confidence intervals |
| 83 | * to be available for all objectives with statistical evaluators. |
| 84 | * Reading in of objectives and confidence values is not supported for raw genotype files. |
| 85 | * Note that this method changes the internal objectives and deletes all objectives that are not |
| 86 | * found in the file. |
| 87 | * @param blackboard |
| 88 | */ |
| 89 | public static List<DesignDecisionGenotype> getGenotypes(String filename, MDSDBlackboard blackboard) |
| 90 | throws CoreException { |
| 91 | |
| 92 | if ("".equals(filename)){ |
| 93 | return Collections.emptyList(); |
| 94 | } |
| 95 | |
| 96 | if (filename.contains("csv")) { |
| 97 | try { |
| 98 | |
| 99 | List<DSEIndividual> individuals = readInPrettyPrintedIndividuals(getReaderFor(filename), blackboard); |
| 100 | List<DesignDecisionGenotype> results = new ArrayList<DesignDecisionGenotype>( |
| 101 | individuals.size()); |
| 102 | for (DSEIndividual individual : individuals) { |
| 103 | results.add(individual.getGenotype()); |
| 104 | } |
| 105 | |
| 106 | return results; |
| 107 | |
| 108 | } catch (Exception ex) { |
| 109 | throw ExceptionHelper.createNewCoreException( |
| 110 | "Could not evaluate predefined instances. See nested Exceptions for cause. " |
| 111 | + ex.getMessage(), ex); |
| 112 | } |
| 113 | } else if (filename.contains("designdecision")) { |
| 114 | return loadGenotypesFromEMF(filename); |
| 115 | |
| 116 | } else |
| 117 | throw ExceptionHelper |
| 118 | .createNewCoreException("Genotype file to read must must be of type csv or designdecision."); |
| 119 | } |
| 120 | |
| 121 | /** |
| 122 | * Load complete Individuals from the file (with objectives and utilisation info, if present). |
| 123 | * @param filename |
| 124 | * @param blackboard |
| 125 | * @return |
| 126 | * @throws CoreException |
| 127 | */ |
| 128 | public static List<DSEIndividual> getIndividuals(String filename, MDSDBlackboard blackboard) throws CoreException{ |
| 129 | |
| 130 | if (filename.contains("csv")) { |
| 131 | try { |
| 132 | |
| 133 | List<DSEIndividual> individuals = readInPrettyPrintedIndividuals(getReaderFor(filename), blackboard); |
| 134 | return individuals; |
| 135 | |
| 136 | } catch( Exception ex ) { |
| 137 | throw ExceptionHelper.createNewCoreException("Could not evaluate predefined instances. See nested Exceptions for cause. "+ex.getMessage(), ex); |
| 138 | } |
| 139 | } else if (filename.contains("designdecision")) { |
| 140 | List<DesignDecisionGenotype> genotypes = loadGenotypesFromEMF(filename); |
| 141 | List<DSEIndividual> individuals = new ArrayList<DSEIndividual>(genotypes.size()); |
| 142 | for (DesignDecisionGenotype designDecisionGenotype : genotypes) { |
| 143 | DSEIndividualBuilder builder = Opt4JStarter.getIndividualBuilder(); |
| 144 | DSEIndividual individual = builder.build(designDecisionGenotype); |
| 145 | individuals.add(individual); |
| 146 | } |
| 147 | return individuals; |
| 148 | |
| 149 | } else |
| 150 | throw ExceptionHelper |
| 151 | .createNewCoreException("Genotype file to read must must be of type csv or designdecision."); |
| 152 | } |
| 153 | |
| 154 | /** |
| 155 | * Note that this method changes the internal objectives and deletes all objectives that are not |
| 156 | * found in the file. |
| 157 | * @param filename |
| 158 | * @return |
| 159 | * @throws CoreException |
| 160 | */ |
| 161 | public static List<DSEObjectives> getObjectives (String filename) throws CoreException{ |
| 162 | |
| 163 | try { |
| 164 | |
| 165 | List<DSEObjectives> results = readInPrettyPrintedObjectives(getReaderFor(filename)); |
| 166 | |
| 167 | return results; |
| 168 | |
| 169 | } catch( Exception ex ) { |
| 170 | throw ExceptionHelper.createNewCoreException("Could not evaluate predefined instances. Leave field blank for evolutionary search or type \"random\" for a random search. "+ex.getMessage(), ex); |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | private static List<DesignDecisionGenotype> loadGenotypesFromEMF( |
| 175 | String filename) { |
| 176 | PCMInstance pcm = Opt4JStarter.getProblem().getInitialInstance(); |
| 177 | ResourceSet pcmResourceSet = pcm.getAllocation().eResource().getResourceSet(); |
| 178 | |
| 179 | EObject eCandidates = EMFHelper.loadFromXMIFile(filename, pcmResourceSet); |
| 180 | EcoreUtil.resolveAll(eCandidates); |
| 181 | FixDesignDecisionReferenceSwitch refSwitch = new FixDesignDecisionReferenceSwitch(Opt4JStarter.getProblem().getInitialInstance()); |
| 182 | refSwitch.doSwitch(eCandidates); |
| 183 | |
| 184 | if (!(eCandidates instanceof Candidates)){ |
| 185 | throw new RuntimeException("Cannot read candidate model file "+filename+". Please create a new one.", null); |
| 186 | } |
| 187 | Candidates candidates = (Candidates)eCandidates ; |
| 188 | EcoreUtil.resolveAll(candidates); |
| 189 | |
| 190 | List<DesignDecisionGenotype> genotypeList = new ArrayList<DesignDecisionGenotype>(candidates.getCandidate().size()); |
| 191 | for (Candidate candidate : candidates.getCandidate()) { |
| 192 | DesignDecisionGenotype genotype = new DesignDecisionGenotype(candidate, candidates.getProblem(), Opt4JStarter.getProblem().getGenotypeOfInitialPCMInstance()); |
| 193 | genotypeList.add(genotype); |
| 194 | } |
| 195 | |
| 196 | return genotypeList; |
| 197 | } |
| 198 | |
| 199 | //FIXME: copied from readInPrettyPrintedGenotypes. Refactor to use a proper serialisation!! |
| 200 | private static List<DSEObjectives> readInPrettyPrintedObjectives(BufferedReader in) throws CoreException, IOException { |
| 201 | List<DSEObjectives> results = new ArrayList<DSEObjectives>(); |
| 202 | |
| 203 | //order design decisions |
| 204 | String headline = in.readLine(); |
| 205 | if (headline == null){ |
| 206 | throw ExceptionHelper.createNewCoreException("Predefined instances file could not be read because it is empty. Specify a valid file or \"random\" or leave the field blank for an evolutionary search."); |
| 207 | } |
| 208 | String[] headlineArray = headline.split(SEPARATOR); |
| 209 | |
| 210 | List<CriterionAndEvaluator> objectiveList = Opt4JStarter.getDSEEvaluator().getCriterionAndEvaluatorList(); |
| 211 | |
| 212 | //Empty list if no objectives are specified. |
| 213 | List<List<CriterionAndEvaluator>> orderedObjectives = getOrderedObjectiveCollection(headlineArray, objectiveList); |
| 214 | |
| 215 | //count confidence intervals to determine boundaries of areas in file (objectives, confidences, genotype) |
| 216 | int numberOfConfidenceIntervals = countConfidenceIntervals(headlineArray); |
| 217 | |
| 218 | int startIndexOfConfidence = orderedObjectives.size(); |
| 219 | if( orderedObjectives.size() == 0){ |
| 220 | ExceptionHelper.createNewCoreException("Tried to read in Pareto front that has no objectives in it. Fix your file."); |
| 221 | } |
| 222 | |
| 223 | int expectedLineArrayLength = headlineArray.length; |
| 224 | |
| 225 | String line; |
| 226 | while ( null != (line = in.readLine()) ) { |
| 227 | String[] lineArray = line.split(SEPARATOR); |
| 228 | //Check minimum length, a last semicolon is ok that makes the line array one longer than the list. |
| 229 | if (lineArray.length < expectedLineArrayLength){ |
| 230 | throw ExceptionHelper.createNewCoreException("A line in the predefined instances file has not the right length"); |
| 231 | } |
| 232 | DSEObjectives objectives = readInObjectivesAndConfidence( |
| 233 | orderedObjectives, startIndexOfConfidence, |
| 234 | numberOfConfidenceIntervals, lineArray); |
| 235 | results.add(objectives); |
| 236 | } |
| 237 | in.close(); |
| 238 | |
| 239 | return results; |
| 240 | } |
| 241 | |
| 242 | private static BufferedReader getReaderFor(String path) throws FileNotFoundException { |
| 243 | // if this is a platform URL, first resolve it to an absolute path |
| 244 | if (path.startsWith("platform:")){ |
| 245 | try { |
| 246 | URL solvedURL = FileLocator.resolve(new URL(path)); |
| 247 | path = solvedURL.getPath(); |
| 248 | } catch (Exception e) { |
| 249 | e.printStackTrace(); |
| 250 | return null; |
| 251 | } |
| 252 | } |
| 253 | File file = new File(path); |
| 254 | |
| 255 | InputStreamReader ir = new InputStreamReader( |
| 256 | new FileInputStream( file ) ); |
| 257 | BufferedReader in = new BufferedReader(ir); |
| 258 | return in; |
| 259 | } |
| 260 | |
| 261 | /** |
| 262 | * Reads the genotypes from the specified files. |
| 263 | * If objectives are given, reads them and updates the DSEEvaluator cache |
| 264 | * by calling DSEEvaluator.addToPhenotypeCache(..). Requires confidence intervals |
| 265 | * to be available for all objectives with statistical evaluators. |
| 266 | * @param in Is used and modify and closed |
| 267 | * @param blackboard |
| 268 | * @return |
| 269 | * @throws CoreException |
| 270 | * @throws IOException |
| 271 | */ |
| 272 | private static List<DSEIndividual> readInPrettyPrintedIndividuals(BufferedReader in, MDSDBlackboard blackboard) throws CoreException, IOException { |
| 273 | List<DSEIndividual> results = new LinkedList<DSEIndividual>(); |
| 274 | |
| 275 | DSEProblem problem = Opt4JStarter.getProblem(); |
| 276 | List<DegreeOfFreedomInstance> decisionList = problem.getDesignDecisions(); |
| 277 | |
| 278 | //order design decisions |
| 279 | String headline = in.readLine(); |
| 280 | if (headline == null){ |
| 281 | throw ExceptionHelper.createNewCoreException("Predefined instances file could not be read because it is empty. Specify a valid file or \"random\" or leave the field blank for an evolutionary search."); |
| 282 | } |
| 283 | String[] headlineArray = headline.split(SEPARATOR); |
| 284 | |
| 285 | // the configured list of objectives |
| 286 | List<CriterionAndEvaluator> objectiveList = Opt4JStarter.getDSEEvaluator().getCriterionAndEvaluatorList(); |
| 287 | |
| 288 | // Empty list if no objectives are specified. |
| 289 | // The inner lists must not be empty. |
| 290 | // The inner lists contain all evaluators that are interested in one column of the result file. For example, |
| 291 | // if there is a response time objective and a response time constraint, these two are in one list. |
| 292 | List<List<CriterionAndEvaluator>> orderedObjectives = getOrderedObjectiveCollection(headlineArray, objectiveList); |
| 293 | |
| 294 | boolean hasObjectives = orderedObjectives.size() != 0; |
| 295 | |
| 296 | //determine missing objectives |
| 297 | List<CriterionAndEvaluator> missingObjectives = determineMissingObjectives(objectiveList, orderedObjectives); |
| 298 | |
| 299 | // special case: find one performance criterion to determine whether confidence intervals are required. |
| 300 | Criterion performance = null; |
| 301 | if (hasObjectives){ |
| 302 | for (List<CriterionAndEvaluator> objectiveAndEvaluatorList : orderedObjectives) { |
| 303 | |
| 304 | if (objectiveAndEvaluatorList.size()>0){ |
| 305 | CriterionAndEvaluator first = objectiveAndEvaluatorList.get(0); |
| 306 | //XXX: Read the dimension name from definition rather than the constants container |
| 307 | if (ResultsWriter.getDimensionName(first.getCriterion()).contains(new QMLDimensionReader().getDimension(QMLConstantsContainer.QUALITY_ATTRIBUTE_DIMENSION_RESPONSETIME_DEFINITION_PATH).getEntityName()) |
| 308 | || ResultsWriter.getDimensionName(first.getCriterion()).contains(new QMLDimensionReader().getDimension(QMLConstantsContainer.QUALITY_ATTRIBUTE_DIMENSION_THROUGHPUT_DEFINITION_PATH).getEntityName())){ |
| 309 | performance = first.getCriterion(); |
| 310 | break; |
| 311 | } |
| 312 | } |
| 313 | } |
| 314 | |
| 315 | } |
| 316 | |
| 317 | //count confidence intervals to determine boundaries of areas in file (objectives, confidences, genotype) |
| 318 | int numberOfConfidenceIntervals = countConfidenceIntervals(headlineArray); |
| 319 | |
| 320 | // determine number of objective columns. |
| 321 | |
| 322 | int startIndexOfConfidence = orderedObjectives.size(); |
| 323 | |
| 324 | //Its always three columns per objective that has confidence |
| 325 | int startIndexOfGenotype = orderedObjectives.size() + numberOfConfidenceIntervals*3; |
| 326 | |
| 327 | //order the design decision in the problem based on the found order. |
| 328 | List<DegreeOfFreedomInstance> orderedDesignDecisions = getOrderedDesignDecisions( |
| 329 | decisionList, headlineArray, startIndexOfGenotype, problem); |
| 330 | |
| 331 | int minExpectedLineArrayLength = startIndexOfGenotype + orderedDesignDecisions.size(); |
| 332 | |
| 333 | List<ResourcesWithUtilisationDescriptor> resourceDescriptorsWithUtilResults = getDescriptorsForResourcesWithUtilisation(headlineArray, minExpectedLineArrayLength, problem); |
| 334 | |
| 335 | String line; |
| 336 | while ( null != (line = in.readLine()) ) { |
| 337 | String[] lineArray = line.split(SEPARATOR); |
| 338 | //Check minimum length, a last semicolon is ok that makes the line array one longer than the list. |
| 339 | if (lineArray.length < minExpectedLineArrayLength){ |
| 340 | throw ExceptionHelper.createNewCoreException("A line in the predefined instances file has not the right length"); |
| 341 | } |
| 342 | DesignDecisionGenotype genotype = extractGenotypeAndAddToList(startIndexOfGenotype, |
| 343 | orderedDesignDecisions, lineArray); |
| 344 | |
| 345 | |
| 346 | DSEIndividualBuilder builder = Opt4JStarter.getIndividualBuilder(); |
| 347 | DSEIndividual individual = builder.build(genotype); |
| 348 | results.add(individual); |
| 349 | |
| 350 | if (hasObjectives){ |
| 351 | DSEObjectives objectives = readInObjectivesAndConfidence( |
| 352 | orderedObjectives, startIndexOfConfidence, |
| 353 | numberOfConfidenceIntervals, lineArray); |
| 354 | |
| 355 | //has utilisations? |
| 356 | if (resourceDescriptorsWithUtilResults.size() > 0 && performance != null){ |
| 357 | objectives.addResultDecoratorFor(performance, getResultDecorator(lineArray, minExpectedLineArrayLength, resourceDescriptorsWithUtilResults)); |
| 358 | |
| 359 | //if the processor list is non-empty, but no utilisations were found, warn because the read in values might be old versions |
| 360 | if (objectives.getResultDecoratorFor(performance).getUtilisationResults_ResultDecoratorRepository().size() == 0 && !objectives.getValueForCriterion(performance).equals(new DoubleValue(Double.POSITIVE_INFINITY))){ |
| 361 | logger.warn("Empty utilisation values for non-infinity objectives encountered when reading in individuals, check that this is ok."); |
| 362 | } |
| 363 | } |
| 364 | |
| 365 | //if (Opt4JStarter.getDSEWorkflowConfig().getUseAntipatternKnowledge()){ |
| 366 | if (Opt4JStarter.getDSEWorkflowConfig().isUseHeuristics()){ |
| 367 | |
| 368 | //PCMResourceSetPartition analysisPartition = (PCMResourceSetPartition)blackboard.getPartition(LoadPCMModelsIntoBlackboardJob.PCM_MODELS_PARTITION_ID); |
| 369 | //PCMInstance model = new PCMInstance(analysisPartition); |
| 370 | PCMInstance model = Opt4JStarter.getProblem().getInitialInstance(); |
| 371 | |
| 372 | //solve dependencies for performance |
| 373 | Opt4JStarter.getDSEDecoder().decode(genotype); |
| 374 | AbstractPerformanceAnalysisResult.solveDependencies(model); |
| 375 | |
| 376 | ComputedAggregatedUsage computedAggregatedUsage = model.getComputedAggregatedUsage(); |
| 377 | if (computedAggregatedUsage != null){ |
| 378 | objectives.addComputedAggregatedUsage(performance, computedAggregatedUsage); |
| 379 | } |
| 380 | } |
| 381 | |
| 382 | //add objective to phenotype cache with genotype string |
| 383 | Opt4JStarter.getDSEEvaluator().addToPhenotypeCache(DSEDecoder.getGenotypeString(genotype), objectives); |
| 384 | |
| 385 | //add objectives to individual |
| 386 | individual.setObjectives(objectives); |
| 387 | } |
| 388 | |
| 389 | } |
| 390 | in.close(); |
| 391 | |
| 392 | if (hasObjectives && missingObjectives.size() > 0){ |
| 393 | // evaluate the objectives that are not read in |
| 394 | evaluateMissingObjectives(results, missingObjectives); |
| 395 | } |
| 396 | |
| 397 | return results; |
| 398 | } |
| 399 | |
| 400 | /** |
| 401 | * Return those objectives in desiredObjectives that are not contained in orderedObjectives. |
| 402 | * @param desiredObjectives |
| 403 | * @param availableObjectives |
| 404 | * @return |
| 405 | */ |
| 406 | static public List<CriterionAndEvaluator> determineMissingObjectives(List<CriterionAndEvaluator> desiredObjectives, List<List<CriterionAndEvaluator>> availableObjectives) { |
| 407 | |
| 408 | List<CriterionAndEvaluator> flattenedAvailableObjectives = new ArrayList<CriterionAndEvaluator>(availableObjectives.size()*3); |
| 409 | for (List<CriterionAndEvaluator> list : availableObjectives) { |
| 410 | flattenedAvailableObjectives.addAll(list); |
| 411 | } |
| 412 | List<CriterionAndEvaluator> missingObjectives = new ArrayList<CriterionAndEvaluator>(); |
| 413 | // from the set of desired objectives... |
| 414 | missingObjectives.addAll(desiredObjectives); |
| 415 | // ... remove all objectives that are already included in the files |
| 416 | missingObjectives.removeAll(flattenedAvailableObjectives); |
| 417 | |
| 418 | // the resulting list are all desired objectives that are not in orderObjectives. |
| 419 | return missingObjectives; |
| 420 | |
| 421 | } |
| 422 | |
| 423 | /** |
| 424 | * Check all objectives of the indivuals and evaluate the missing ones |
| 425 | * @param results |
| 426 | * @param missingObjectives |
| 427 | * @throws |
| 428 | * @throws JobFailedException |
| 429 | * @throws UserCanceledException |
| 430 | * @throws CoreException |
| 431 | */ |
| 432 | private static void evaluateMissingObjectives(List<DSEIndividual> results, List<CriterionAndEvaluator> missingObjectives) throws CoreException { |
| 433 | |
| 434 | for (DSEIndividual individual : results) { |
| 435 | |
| 436 | DSEEvaluator dseEvaluator = task.getInstance(DSEEvaluator.class); |
| 437 | DSEDecoder decoder = task.getInstance(DSEDecoder.class); |
| 438 | |
| 439 | PCMPhenotype pheno = (PCMPhenotype) decoder.decode(individual.getGenotype()); |
| 440 | individual.setPhenotype(pheno); |
| 441 | |
| 442 | List<IAnalysis> alreadyEvaluatedMissingObjectives = new LinkedList<IAnalysis>(); |
| 443 | |
| 444 | for (CriterionAndEvaluator criterionAndEvaluator : missingObjectives) { |
| 445 | IAnalysis evaluator = criterionAndEvaluator.getEvaluator(); |
| 446 | |
| 447 | try { |
| 448 | if (!alreadyEvaluatedMissingObjectives.contains(evaluator)){ |
| 449 | evaluator.analyse(pheno, dseEvaluator.getMonitor()); |
| 450 | |
| 451 | alreadyEvaluatedMissingObjectives.add(evaluator); |
| 452 | |
| 453 | } |
| 454 | |
| 455 | dseEvaluator.retrieveCriterion(pheno, individual.getObjectives(), criterionAndEvaluator); |
| 456 | |
| 457 | } catch (Exception e){ |
| 458 | throw ExceptionHelper.createNewCoreException("Analysis of missing objectives when reading in genotypes failed. See nested cause.", e); |
| 459 | } |
| 460 | |
| 461 | } |
| 462 | |
| 463 | } |
| 464 | |
| 465 | } |
| 466 | |
| 467 | private static List<ResourcesWithUtilisationDescriptor> getDescriptorsForResourcesWithUtilisation( |
| 468 | String[] headlineArray, int minExpectedLineArrayLength, DSEProblem problem) { |
| 469 | |
| 470 | List<ResourcesWithUtilisationDescriptor> allPotentialResourcesWithUtil = getAllProcessors(problem); |
| 471 | List<ResourcesWithUtilisationDescriptor> orderedListOfUsedResourceDesccriptors = new ArrayList<ResourcesWithUtilisationDescriptor>(allPotentialResourcesWithUtil.size()); |
| 472 | for (int i = minExpectedLineArrayLength; i < headlineArray.length; i++) { |
| 473 | String entry = headlineArray[i]; |
| 474 | for (Iterator<ResourcesWithUtilisationDescriptor> iterator = allPotentialResourcesWithUtil.iterator(); iterator |
| 475 | .hasNext();) { |
| 476 | ResourcesWithUtilisationDescriptor processor = iterator |
| 477 | .next(); |
| 478 | if ( entry.contains(processor.getEntity().getEntityName()) |
| 479 | && entry.contains(processor.getResourceType().getEntityName())){ |
| 480 | orderedListOfUsedResourceDesccriptors.add(processor); |
| 481 | iterator.remove(); |
| 482 | break; |
| 483 | } |
| 484 | } |
| 485 | } |
| 486 | |
| 487 | |
| 488 | return orderedListOfUsedResourceDesccriptors; |
| 489 | } |
| 490 | |
| 491 | private static List<ResourcesWithUtilisationDescriptor> getAllProcessors( |
| 492 | DSEProblem problem) { |
| 493 | List<ResourceContainer> containers = problem.getInitialInstance().getResourceEnvironment().getResourceContainer_ResourceEnvironment(); |
| 494 | List<ResourcesWithUtilisationDescriptor> descriptorList = new LinkedList<ResourcesWithUtilisationDescriptor>(); |
| 495 | for (ResourceContainer resourceContainer : containers) { |
| 496 | List<ProcessingResourceSpecification> processorsOnContainer = resourceContainer.getActiveResourceSpecifications_ResourceContainer(); |
| 497 | for (ProcessingResourceSpecification processingResourceSpecification : processorsOnContainer) { |
| 498 | descriptorList.add(new ResourcesWithUtilisationDescriptor(resourceContainer, processingResourceSpecification.getActiveResourceType_ActiveResourceSpecification())); |
| 499 | } |
| 500 | |
| 501 | } |
| 502 | List<LinkingResource> links = problem.getInitialInstance().getResourceEnvironment().getLinkingResources__ResourceEnvironment(); |
| 503 | for (LinkingResource linkingResource : links) { |
| 504 | descriptorList.add(new ResourcesWithUtilisationDescriptor(linkingResource, linkingResource.getCommunicationLinkResourceSpecifications_LinkingResource().getCommunicationLinkResourceType_CommunicationLinkResourceSpecification())); |
| 505 | } |
| 506 | return descriptorList; |
| 507 | } |
| 508 | |
| 509 | private static ResultDecoratorRepository getResultDecorator(String[] lineArray, |
| 510 | int minExpectedLineArrayLength, List<ResourcesWithUtilisationDescriptor> processorsWithUtilResults) throws CoreException { |
| 511 | |
| 512 | ResultDecoratorRepository repo = ResultdecoratorFactory.eINSTANCE.createResultDecoratorRepository(); |
| 513 | |
| 514 | for (int i = 0; i < lineArray.length - minExpectedLineArrayLength && i < processorsWithUtilResults.size(); i++) { |
| 515 | String entry = lineArray[i+minExpectedLineArrayLength]; |
| 516 | if (entry.length() > 0){ |
| 517 | ResourcesWithUtilisationDescriptor processor = processorsWithUtilResults.get(i); |
| 518 | ActiveResourceUtilisationResult result = processor.createUtilisationResult(); |
| 519 | |
| 520 | result.setResourceUtilisation(Double.parseDouble(entry)); |
| 521 | //TODO: implement these if possible. |
| 522 | result.setDemandedTime(Double.NaN); |
| 523 | result.setAverageWaitTime(Double.NaN); |
| 524 | repo.getUtilisationResults_ResultDecoratorRepository().add(result); |
| 525 | } |
| 526 | |
| 527 | } |
| 528 | return repo; |
| 529 | |
| 530 | } |
| 531 | |
| 532 | private static int countConfidenceIntervals( |
| 533 | String[] headlineArray) throws CoreException { |
| 534 | //now count confidence intervals. |
| 535 | int numberOfConfidenceIntervals = 0; |
| 536 | for (int i = 0; i < headlineArray.length; i++) { |
| 537 | if (headlineArray[i].contains(DSEConstantsContainer.LOWER_BOUND_CONFIDENCE+"(")){ |
| 538 | //|| headlineArray[i].contains(DSEConstantsContainer.UPPER_BOUND_CONFIDENCE+"(") |
| 539 | //|| headlineArray[i].contains(DSEConstantsContainer.ALPHA) ){ |
| 540 | numberOfConfidenceIntervals++; |
| 541 | } |
| 542 | } |
| 543 | return numberOfConfidenceIntervals; |
| 544 | } |
| 545 | |
| 546 | private static DesignDecisionGenotype extractGenotypeAndAddToList( |
| 547 | int startIndexOfGenotype, |
| 548 | List<DegreeOfFreedomInstance> orderedDesignDecisions, String[] lineArray) throws CoreException { |
| 549 | |
| 550 | DesignDecisionGenotype genotype = new DesignDecisionGenotype(); |
| 551 | //read in genotype |
| 552 | int decisionIndex = 0; |
| 553 | for (int i = startIndexOfGenotype; i < lineArray.length && decisionIndex < orderedDesignDecisions.size(); i++) { |
| 554 | Choice gene = DSEDecoder.getChoiceFor(lineArray[i], orderedDesignDecisions.get(decisionIndex)); |
| 555 | genotype.add(gene); |
| 556 | decisionIndex++; |
| 557 | } |
| 558 | return genotype; |
| 559 | } |
| 560 | |
| 561 | private static DSEObjectives readInObjectivesAndConfidence( |
| 562 | List<List<CriterionAndEvaluator>> orderedObjectives, |
| 563 | int startIndexOfConfidence, int numberOfConfidenceIntervals, |
| 564 | String[] lineArray) throws CoreException { |
| 565 | //Read in objectives |
| 566 | DSEObjectives objectives = readInObjectives(lineArray, startIndexOfConfidence, orderedObjectives); |
| 567 | |
| 568 | //read in confidence |
| 569 | readInConfidenceIntervals(lineArray, startIndexOfConfidence, numberOfConfidenceIntervals, orderedObjectives, objectives); |
| 570 | return objectives; |
| 571 | } |
| 572 | |
| 573 | /** |
| 574 | * Orders the objectives based on the file and also adjusts the DSEProblem accordingly. |
| 575 | * @param decisionList |
| 576 | * @param headlineArray |
| 577 | * @param startIndexOfGenotype |
| 578 | * @param problem |
| 579 | * @return |
| 580 | */ |
| 581 | private static List<DegreeOfFreedomInstance> getOrderedDesignDecisions( |
| 582 | List<DegreeOfFreedomInstance> decisionList, String[] headlineArray, |
| 583 | int startIndexOfGenotype, DSEProblem problem) throws CoreException{ |
| 584 | List<DegreeOfFreedomInstance> orderedDesignDecisions = new ArrayList<DegreeOfFreedomInstance>(); |
| 585 | for (int i = startIndexOfGenotype; i < headlineArray.length; i++) { |
| 586 | String headlineEntry = headlineArray[i]; |
| 587 | for (DegreeOfFreedomInstance decision : decisionList) { |
| 588 | //We could use an iterator here and directly delete all design decision that have been matched from the list, to make the subsequent steps faster. |
| 589 | if (DegreeOfFreedomHelper.getDegreeDescription(decision).contains(headlineEntry)){ |
| 590 | orderedDesignDecisions.add(decision); |
| 591 | break; |
| 592 | } |
| 593 | } |
| 594 | } |
| 595 | |
| 596 | //Check that the last colums are only utilisation values. |
| 597 | int numberOfUtilColumns = 0; |
| 598 | for (int i = startIndexOfGenotype + orderedDesignDecisions.size(); i < headlineArray.length; i++){ |
| 599 | String headlineString = headlineArray[i]; |
| 600 | if (headlineString.contains("Util") || headlineString.contains("Candidate ID")){ |
| 601 | numberOfUtilColumns++; |
| 602 | } |
| 603 | } |
| 604 | |
| 605 | // If there were unrecognised headline entries (entries that are not before the genotype and that do |
| 606 | // not contain the Substring Util, throw an exception |
| 607 | if (headlineArray.length - startIndexOfGenotype - numberOfUtilColumns > orderedDesignDecisions.size()) |
| 608 | throw ExceptionHelper.createNewCoreException("Not all design decisions in the file were recognised. Check your file.\n" |
| 609 | + " Design decisions from index "+startIndexOfGenotype+" to index "+(headlineArray.length - numberOfUtilColumns -1) |
| 610 | + ", but expected "+orderedDesignDecisions.size()+ " decisions.\n These decisions are expected: "+orderedDesignDecisions.toString() |
| 611 | + "\n Make sure that you provided a designdecision file that matches the predefined candidates (i.e. there is a decision for each column in the predefined candidates files)."); |
| 612 | |
| 613 | //set the internal design decisions to the same order |
| 614 | problem.getDesignDecisions().clear(); |
| 615 | problem.getDesignDecisions().addAll(orderedDesignDecisions); |
| 616 | |
| 617 | return orderedDesignDecisions; |
| 618 | } |
| 619 | |
| 620 | /** |
| 621 | * Fills the confidence intervals of the passed objective and returns it. |
| 622 | * @param lineArray |
| 623 | * @param startIndexOfConfidence |
| 624 | * @param numberOfConfidenceIntervals |
| 625 | * @param orderedObjectives |
| 626 | * @param objectives |
| 627 | * @return |
| 628 | * @throws CoreException |
| 629 | */ |
| 630 | private static DSEObjectives readInConfidenceIntervals(String[] lineArray, |
| 631 | int startIndexOfConfidence, int numberOfConfidenceIntervals, |
| 632 | List<List<CriterionAndEvaluator>> orderedObjectives, DSEObjectives objectives) throws CoreException { |
| 633 | |
| 634 | //read in confidence |
| 635 | int index = startIndexOfConfidence; |
| 636 | for (List<CriterionAndEvaluator> objectiveAndEvaluatorList : orderedObjectives) { |
| 637 | if (objectiveAndEvaluatorList.size() > 0){ |
| 638 | |
| 639 | // only the first evaluator has to be handled because they all point to the same IAnalysis (e.g. SimuCom) |
| 640 | CriterionAndEvaluator objectiveAndEvaluator = objectiveAndEvaluatorList.get(0); |
| 641 | |
| 642 | if (objectiveAndEvaluator.getEvaluator().hasStatisticResults() && index < lineArray.length - 2){ |
| 643 | String lowerConfidenceString = lineArray[index]; |
| 644 | String upperConfidenceString = lineArray[index+1]; |
| 645 | String alphaConfidenceString = lineArray[index+2]; |
| 646 | |
| 647 | Criterion criterion = objectiveAndEvaluator.getCriterion(); |
| 648 | Value<?> value = objectives.getValueForCriterion(criterion); |
| 649 | |
| 650 | ConfidenceInterval ci = readInConfidenceInterval(lowerConfidenceString, upperConfidenceString, alphaConfidenceString, value); |
| 651 | index = index +3; |
| 652 | objectives.addConfidence(objectiveAndEvaluator.getCriterion(), ci); |
| 653 | } else { |
| 654 | |
| 655 | } |
| 656 | } |
| 657 | } |
| 658 | return objectives; |
| 659 | } |
| 660 | |
| 661 | /** |
| 662 | * Objective definition must be in the first columns of the file. |
| 663 | * |
| 664 | * @param headline |
| 665 | * @param objectiveList: A list of lists. The inner lists contains the {@link Criterion} for one headline entry. |
| 666 | * The list is in the same order as the headline, so the values in the lines can be associated with a {@link Criterion} by index. |
| 667 | * The inner lists are not empty. |
| 668 | * @return never null, but may be an empty list. |
| 669 | */ |
| 670 | private static List<List<CriterionAndEvaluator>> getOrderedObjectiveCollection(String[] headline, List<CriterionAndEvaluator> objectiveList) throws CoreException{ |
| 671 | |
| 672 | List<List<CriterionAndEvaluator>> orderedObjectives = new ArrayList<List<CriterionAndEvaluator>>(objectiveList.size()); |
| 673 | |
| 674 | for (int i = 0; i < headline.length; i++) { |
| 675 | String objectiveString = headline[i]; |
| 676 | List<CriterionAndEvaluator> o = matchObjective(objectiveList, objectiveString); |
| 677 | if (o.size() == 0){ |
| 678 | //The current entry is not an objective, so the objective columns are done |
| 679 | break; |
| 680 | } else { |
| 681 | orderedObjectives.add(o); |
| 682 | } |
| 683 | } |
| 684 | |
| 685 | if (objectiveList.size() < orderedObjectives.size()){ |
| 686 | // I cannot have more objectives than evaluators. |
| 687 | // throw Exception and notify user that there must be only one column per objective |
| 688 | throw ExceptionHelper.createNewCoreException("Error reading in objectives: There must be only one column for each objective."); |
| 689 | } |
| 690 | |
| 691 | return orderedObjectives; |
| 692 | } |
| 693 | |
| 694 | |
| 695 | private static ConfidenceInterval readInConfidenceInterval( |
| 696 | String lowerConfidenceString, String upperConfidenceString, |
| 697 | String alphaConfidenceString, |
| 698 | Value<?> value) throws CoreException { |
| 699 | |
| 700 | try { |
| 701 | double lowerBound = parseToDouble(lowerConfidenceString); |
| 702 | double upperBound = parseToDouble(upperConfidenceString); |
| 703 | double level = parseToDouble(alphaConfidenceString); |
| 704 | return new ConfidenceInterval(value.getDouble(), lowerBound, upperBound, level); |
| 705 | } catch (NumberFormatException e){ |
| 706 | throw ExceptionHelper.createNewCoreException("Could not read in confidence interval. Expected this to be a confidence interval: " |
| 707 | +lowerConfidenceString+SEPARATOR+upperConfidenceString+SEPARATOR+alphaConfidenceString, e); |
| 708 | } |
| 709 | |
| 710 | |
| 711 | } |
| 712 | |
| 713 | |
| 714 | |
| 715 | private static List<CriterionAndEvaluator> matchObjective( |
| 716 | List<CriterionAndEvaluator> objectiveList, String objectiveString) { |
| 717 | List<CriterionAndEvaluator> results = new ArrayList<CriterionAndEvaluator>(objectiveList.size()); |
| 718 | for (CriterionAndEvaluator objective : objectiveList) { |
| 719 | if (objectiveString.equals(ResultsWriter.getDimensionName(objective.getCriterion()))){ |
| 720 | results.add(objective); |
| 721 | } |
| 722 | } |
| 723 | return results; |
| 724 | } |
| 725 | |
| 726 | /** |
| 727 | * Reads in |
| 728 | * @param orderedObjectives |
| 729 | * @param endIndex |
| 730 | * @param |
| 731 | * @return |
| 732 | * @throws IOException |
| 733 | * @throws CoreException |
| 734 | */ |
| 735 | private static DSEObjectives readInObjectives(String[] objectiveLine, int endIndex, List<List<CriterionAndEvaluator>> orderedObjectives) throws CoreException { |
| 736 | |
| 737 | //objective line must have at least the length of the passed list |
| 738 | if (objectiveLine.length < orderedObjectives.size()){ |
| 739 | throw ExceptionHelper.createNewCoreException("Error when reading in result line: the line is shorter ("+objectiveLine+" entries) than the number of objectives I look for ("+orderedObjectives.size()+"entries)."); |
| 740 | } |
| 741 | |
| 742 | DSEObjectives obj; |
| 743 | if (task != null){ |
| 744 | obj = task.getInstance(DSEObjectives.class);//QUICKHACK |
| 745 | } else { |
| 746 | //TODO: LEGACY, but required in PredefinedInstanceEvaluator because that one does not initialise the Opt4J environment. |
| 747 | obj = new DSEObjectives(); |
| 748 | } |
| 749 | |
| 750 | int lineIndex = 0; |
| 751 | for (List<CriterionAndEvaluator> criterionList : orderedObjectives) { |
| 752 | try { |
| 753 | double d = parseToDouble(objectiveLine[lineIndex]); |
| 754 | for (CriterionAndEvaluator criterionAndEvaluator : criterionList) { |
| 755 | Criterion criterion = criterionAndEvaluator.getCriterion(); |
| 756 | obj.addValueForCriterion(criterion, d); |
| 757 | } |
| 758 | } catch (NumberFormatException e){ |
| 759 | throw ExceptionHelper.createNewCoreException("Could not parse objective value "+objectiveLine[lineIndex]+". Fix your input genome file."); |
| 760 | } |
| 761 | lineIndex++; |
| 762 | } |
| 763 | |
| 764 | return obj; |
| 765 | } |
| 766 | |
| 767 | private static double parseToDouble(String number) { |
| 768 | double d = Double.parseDouble(number); |
| 769 | if (Double.isInfinite(d)){ |
| 770 | logger.warn("Read in an infinite objective or confidence interval from predefined file, please check that this is correct and not result of an incomplete previous analysis step."); |
| 771 | } else if (Double.isNaN(d)){ |
| 772 | logger.warn("Read in an objective or confidence interval with NaN value from predefined file, please check that this is correct and not result of an incomplete previous analysis step."); |
| 773 | } |
| 774 | return d; |
| 775 | } |
| 776 | |
| 777 | } |
| 778 | |
| 779 | class ResourcesWithUtilisationDescriptor{ |
| 780 | |
| 781 | Entity resource; |
| 782 | |
| 783 | ResourceType resourceType; |
| 784 | |
| 785 | public ResourcesWithUtilisationDescriptor(Entity resource, ResourceType resourceType) { |
| 786 | super(); |
| 787 | this.resource = resource; |
| 788 | this.resourceType = resourceType; |
| 789 | } |
| 790 | |
| 791 | public ResourceType getResourceType() { |
| 792 | return this.resourceType; |
| 793 | } |
| 794 | |
| 795 | public Entity getEntity() { |
| 796 | return this.resource; |
| 797 | } |
| 798 | |
| 799 | public ActiveResourceUtilisationResult createUtilisationResult() throws CoreException{ |
| 800 | if (resource instanceof ResourceContainer){ |
| 801 | if (resourceType != null){ |
| 802 | ResourceContainer rc = (ResourceContainer)resource; |
| 803 | |
| 804 | for (ProcessingResourceSpecification procRes : rc.getActiveResourceSpecifications_ResourceContainer()) { |
| 805 | if (procRes.getActiveResourceType_ActiveResourceSpecification().getId().equals(resourceType.getId())){ |
| 806 | |
| 807 | ProcessingResourceSpecificationResult result = ResourceenvironmentdecoratorFactory.eINSTANCE.createProcessingResourceSpecificationResult(); |
| 808 | result.setProcessingResourceSpecification_ProcessingResourceSpecificationResult(procRes); |
| 809 | result.setEntityName("Util of "+resource.getEntityName() |
| 810 | +"_"+resourceType.getEntityName()); |
| 811 | return result; |
| 812 | } |
| 813 | } |
| 814 | throw ExceptionHelper.createNewCoreException("No processing resource of type "+this.resourceType+" found for ResourceContainer "+this.resource.getEntityName()); |
| 815 | |
| 816 | } else { |
| 817 | // TODO: as soon as we support aggregated results for the whole resource container, this has to be handled here |
| 818 | throw ExceptionHelper.createNewCoreException("Aggregated utilisation results for resource containers are not yet supported, define a resource type."); |
| 819 | } |
| 820 | } else if (resource instanceof LinkingResource){ |
| 821 | LinkingResourceResults result = ResourceenvironmentdecoratorFactory.eINSTANCE.createLinkingResourceResults(); |
| 822 | result.setEntityName("Util of "+resource.getEntityName()+"_"+resourceType.getEntityName()); |
| 823 | result.setLinkingResource_LinkingResourceResults((LinkingResource) resource); |
| 824 | return result; |
| 825 | } else { |
| 826 | throw ExceptionHelper.createNewCoreException("Unknown entity to create utilisation results for: "+this.resource.getClass().getName()); |
| 827 | } |
| 828 | } |
| 829 | |
| 830 | } |
| 831 | |