1 | package de.uka.ipd.sdq.dsexplore.opt4j.representation; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.LinkedList; |
5 | import java.util.List; |
6 | |
7 | import org.apache.log4j.Logger; |
8 | import org.eclipse.core.runtime.CoreException; |
9 | import org.eclipse.emf.common.util.EList; |
10 | import org.eclipse.emf.ecore.EObject; |
11 | import org.eclipse.emf.ecore.util.EcoreUtil; |
12 | import org.opt4j.core.problem.Decoder; |
13 | |
14 | import com.google.inject.Inject; |
15 | |
16 | import de.uka.ipd.sdq.dsexplore.analysis.PCMPhenotype; |
17 | import de.uka.ipd.sdq.dsexplore.designdecisions.alternativecomponents.AlternativeComponent; |
18 | import de.uka.ipd.sdq.dsexplore.exception.ChoiceOutOfBoundsException; |
19 | import de.uka.ipd.sdq.dsexplore.exception.ExceptionHelper; |
20 | import de.uka.ipd.sdq.dsexplore.exception.InvalidChoiceForDegreeException; |
21 | import de.uka.ipd.sdq.dsexplore.helper.DegreeOfFreedomHelper; |
22 | import de.uka.ipd.sdq.dsexplore.helper.EMFHelper; |
23 | import de.uka.ipd.sdq.dsexplore.helper.ResultsWriter; |
24 | import de.uka.ipd.sdq.dsexplore.opt4j.genotype.DesignDecisionGenotype; |
25 | import de.uka.ipd.sdq.dsexplore.opt4j.start.Opt4JStarter; |
26 | import de.uka.ipd.sdq.pcm.allocation.AllocationContext; |
27 | import de.uka.ipd.sdq.pcm.core.composition.AssemblyContext; |
28 | import de.uka.ipd.sdq.pcm.core.entity.Entity; |
29 | import de.uka.ipd.sdq.pcm.cost.helper.CostUtil; |
30 | import de.uka.ipd.sdq.pcm.designdecision.AllocationDegree; |
31 | import de.uka.ipd.sdq.pcm.designdecision.AssembledComponentDegree; |
32 | import de.uka.ipd.sdq.pcm.designdecision.CapacityDegree; |
33 | import de.uka.ipd.sdq.pcm.designdecision.Choice; |
34 | import de.uka.ipd.sdq.pcm.designdecision.ContinousRangeChoice; |
35 | import de.uka.ipd.sdq.pcm.designdecision.ContinuousProcessingRateDegree; |
36 | import de.uka.ipd.sdq.pcm.designdecision.ContinuousRangeDegree; |
37 | import de.uka.ipd.sdq.pcm.designdecision.DegreeOfFreedomInstance; |
38 | import de.uka.ipd.sdq.pcm.designdecision.DiscreteProcessingRateDegree; |
39 | import de.uka.ipd.sdq.pcm.designdecision.DiscreteRangeChoice; |
40 | import de.uka.ipd.sdq.pcm.designdecision.DiscreteRangeDegree; |
41 | import de.uka.ipd.sdq.pcm.designdecision.ClassChoice; |
42 | import de.uka.ipd.sdq.pcm.designdecision.ClassDegree; |
43 | import de.uka.ipd.sdq.pcm.designdecision.ExchangeComponentRule; |
44 | import de.uka.ipd.sdq.pcm.designdecision.NumberOfCoresDegree; |
45 | import de.uka.ipd.sdq.pcm.designdecision.ProcessingRateDegree; |
46 | import de.uka.ipd.sdq.pcm.designdecision.ProcessingResourceDegree; |
47 | import de.uka.ipd.sdq.pcm.designdecision.RangeDegree; |
48 | import de.uka.ipd.sdq.pcm.designdecision.ResourceContainerReplicationDegree; |
49 | import de.uka.ipd.sdq.pcm.designdecision.ResourceContainerReplicationDegreeWithComponentChange; |
50 | import de.uka.ipd.sdq.pcm.designdecision.SchedulingPolicyChoice; |
51 | import de.uka.ipd.sdq.pcm.designdecision.SchedulingPolicyDegree; |
52 | import de.uka.ipd.sdq.pcm.designdecision.designdecisionFactory; |
53 | import de.uka.ipd.sdq.pcm.designdecision.impl.designdecisionFactoryImpl; |
54 | import de.uka.ipd.sdq.pcm.repository.PassiveResource; |
55 | import de.uka.ipd.sdq.pcm.repository.RepositoryComponent; |
56 | import de.uka.ipd.sdq.pcm.resourceenvironment.LinkingResource; |
57 | import de.uka.ipd.sdq.pcm.resourceenvironment.ProcessingResourceSpecification; |
58 | import de.uka.ipd.sdq.pcm.resourceenvironment.ResourceContainer; |
59 | import de.uka.ipd.sdq.pcm.resourceenvironment.SchedulingPolicy; |
60 | import de.uka.ipd.sdq.pcm.resourcetype.ProcessingResourceType; |
61 | import de.uka.ipd.sdq.pcmsolver.models.PCMInstance; |
62 | |
63 | /** |
64 | * The {@link DSEDecoder} is responsible for converting the genotypes into |
65 | * proper PCM instances that can then be analysed. |
66 | * |
67 | * @author Anne |
68 | * |
69 | */ |
70 | public class DSEDecoder implements Decoder<DesignDecisionGenotype, PCMPhenotype> { |
71 | |
72 | //private final DSEProblem problem; |
73 | |
74 | /** Logger for log4j. */ |
75 | private static Logger logger = |
76 | Logger.getLogger("de.uka.ipd.sdq.dsexplore"); |
77 | |
78 | /** Store first MTTF and rate values to adjust later MTTF with (see {@link #applyChangeProcessingRateDecision(ContinuousProcessingRateDegree, Choice)}).*/ |
79 | private double initialMTTF = Double.NaN; |
80 | /** @see #initialMTTF */ |
81 | private double initialRate = Double.NaN; |
82 | |
83 | @Inject |
84 | public DSEDecoder(){ |
85 | //XXX like this you can only set the problem once. Maybe don't save the reference. |
86 | //this.problem = Opt4JStarter.problem; |
87 | } |
88 | |
89 | @Override |
90 | public PCMPhenotype decode(DesignDecisionGenotype genotype) { |
91 | |
92 | //get PCM Instance |
93 | PCMInstance pcm = Opt4JStarter.getProblem().getInitialInstance(); |
94 | |
95 | int index = 0; |
96 | //adjust values as in genotype |
97 | for (Choice doubleGene : genotype) { |
98 | |
99 | applyChange(doubleGene.getDegreeOfFreedomInstance(), doubleGene); |
100 | |
101 | index++; |
102 | } |
103 | |
104 | String genotypeString = getGenotypeString(genotype); |
105 | |
106 | //encapsulate as phenotype |
107 | //return new PCMPhenotype(pcm.deepCopy(),genotypeStringBuilder.toString()); |
108 | return new PCMPhenotype(pcm,genotypeString, genotype.getNumericID()); |
109 | } |
110 | |
111 | /** |
112 | * Applies the given change to the initial pcm instance (as this is |
113 | * referenced by the design decisions. More precisely, this one calls |
114 | * calls specialized methods for dealing with different types of design |
115 | * decisions. |
116 | * |
117 | * @param designDecision |
118 | * @param pcm |
119 | * @param choice The new value the design decision should take. |
120 | */ |
121 | private void applyChange(DegreeOfFreedomInstance designDecision, Choice choice) { |
122 | |
123 | /** |
124 | * TODO Make the selection of the appropriate applyChange method more implicit. Maybe move the method to DesignDecision itself. |
125 | */ |
126 | if (ProcessingRateDegree.class.isInstance(designDecision)){ |
127 | this.applyChangeProcessingRateDecision((ProcessingRateDegree)designDecision, choice); |
128 | } else if (AssembledComponentDegree.class.isInstance(designDecision)){ |
129 | this.applyChangeAssembledComponentDecision((AssembledComponentDegree)designDecision, choice); |
130 | } else if (AllocationDegree.class.isInstance(designDecision)){ |
131 | this.applyChangeAllocationDecision((AllocationDegree)designDecision, choice); |
132 | } else if (SchedulingPolicyDegree.class.isInstance(designDecision)){ |
133 | this.applyChangeSchedulingDecision((SchedulingPolicyDegree)designDecision, choice); |
134 | } else if (CapacityDegree.class.isInstance(designDecision)){ |
135 | this.applyChangeCapacityDecision((CapacityDegree)designDecision, choice); |
136 | } else if (NumberOfCoresDegree.class.isInstance(designDecision)){ |
137 | this.applyChangeNumberOfCoresDecision((NumberOfCoresDegree)designDecision, choice); |
138 | } else if (ResourceContainerReplicationDegree.class.isInstance(designDecision)){ |
139 | this.applyChangeResourceContainerReplicationDegree((ResourceContainerReplicationDegree)designDecision, choice); |
140 | } else { |
141 | logger.warn("There was an unrecognised design decision "+designDecision.getClass()); |
142 | } |
143 | } |
144 | |
145 | private void applyChangeResourceContainerReplicationDegree( |
146 | ResourceContainerReplicationDegree designDecision, Choice choice) { |
147 | |
148 | if (!(choice instanceof DiscreteRangeChoice)){ |
149 | throwNewInvalidChoiceException(designDecision, choice); |
150 | } |
151 | DiscreteRangeChoice discreteChoice = (DiscreteRangeChoice)choice; |
152 | |
153 | int numberOfServers = discreteChoice.getChosenValue(); |
154 | |
155 | EObject changeableEntity = designDecision.getPrimaryChanged(); |
156 | if (!(changeableEntity instanceof ResourceContainer)){ |
157 | throwInvalidEntityException(designDecision, changeableEntity, ResourceContainer.class); |
158 | } |
159 | ResourceContainer server = (ResourceContainer)changeableEntity; |
160 | |
161 | if (numberOfServers < 1){ |
162 | throw new ChoiceOutOfBoundsException(discreteChoice); |
163 | } |
164 | |
165 | PCMInstance pcm = Opt4JStarter.getProblem().getInitialInstance(); |
166 | |
167 | // first reset the changes possibly made for earlier candidates |
168 | List<ResourceContainer> allServers = pcm.getResourceEnvironment().getResourceContainer_ResourceEnvironment(); |
169 | List<ResourceContainer> previousReplicasToRemove = new ArrayList<ResourceContainer>(); |
170 | for (ResourceContainer resourceContainer : allServers) { |
171 | if (resourceContainer.getId().contains(server.getId()) && resourceContainer.getEntityName().contains("Replica")){ |
172 | previousReplicasToRemove.add(resourceContainer); |
173 | } |
174 | } |
175 | allServers.removeAll(previousReplicasToRemove); |
176 | // also remove them from linking resources |
177 | List<LinkingResource> linkingResources = pcm.getResourceEnvironment().getLinkingResources__ResourceEnvironment(); |
178 | for (LinkingResource linkingResource : linkingResources) { |
179 | linkingResource.getConnectedResourceContainers_LinkingResource().removeAll(previousReplicasToRemove); |
180 | } |
181 | |
182 | List<AllocationContext> allocationContextsToRemove = new ArrayList<AllocationContext>(); |
183 | for (AllocationContext allocationContext : pcm.getAllocation().getAllocationContexts_Allocation()) { |
184 | if (previousReplicasToRemove.contains(allocationContext.getResourceContainer_AllocationContext())){ |
185 | allocationContextsToRemove.add(allocationContext); |
186 | } |
187 | } |
188 | pcm.getAllocation().getAllocationContexts_Allocation().removeAll(allocationContextsToRemove); |
189 | |
190 | // Apply the current value of the genome. |
191 | if (numberOfServers == 1){ |
192 | // no replication, keep original model with just one resource container. |
193 | // XXX: assumes that the original model has no replication. |
194 | } else { |
195 | // retrieve components deployed to this server |
196 | List<AllocationContext> allocationContexts = pcm.getAllocation().getAllocationContexts_Allocation(); |
197 | List<AllocationContext> allocationContextsOnServer = getAllocationContextsOnServer(allocationContexts, server); |
198 | |
199 | // the initial server is already there, so add numberOfServers - 1 new servers |
200 | for (int i = 1; i < numberOfServers; i++){ |
201 | // add a server, replicate all components on it. |
202 | |
203 | ResourceContainer serverCopy = (ResourceContainer) EcoreUtil.copy(server); |
204 | serverCopy.setId(serverCopy.getId()+i); |
205 | serverCopy.setEntityName(serverCopy.getEntityName()+"Replica"+i); |
206 | pcm.getResourceEnvironment().getResourceContainer_ResourceEnvironment().add(serverCopy); |
207 | |
208 | // connect the new server copy to all linking resources that the old one is connected to |
209 | for (LinkingResource linkingResource : linkingResources) { |
210 | if (linkingResource.getConnectedResourceContainers_LinkingResource().contains(server)){ |
211 | linkingResource.getConnectedResourceContainers_LinkingResource().add(serverCopy); |
212 | } |
213 | } |
214 | |
215 | for (AllocationContext allocationContext : allocationContextsOnServer) { |
216 | AllocationContext allocationContextCopy = (AllocationContext) EcoreUtil.copy(allocationContext); |
217 | allocationContextCopy.setId(allocationContextCopy.getId()+i); |
218 | allocationContextCopy.setEntityName(allocationContextCopy.getEntityName()+"Replica"+i); |
219 | |
220 | allocationContextCopy.setResourceContainer_AllocationContext(serverCopy); |
221 | |
222 | pcm.getAllocation().getAllocationContexts_Allocation().add(allocationContextCopy); |
223 | } |
224 | } |
225 | } |
226 | } |
227 | |
228 | private List<AllocationContext> getAllocationContextsOnServer( |
229 | List<AllocationContext> allocationContexts, ResourceContainer server) { |
230 | List<AllocationContext> allocationContextsOnThisServer = new LinkedList<AllocationContext>(); |
231 | for (AllocationContext allocationContext : allocationContexts) { |
232 | if (EMFHelper.checkIdentity(allocationContext.getResourceContainer_AllocationContext(), server)){ |
233 | allocationContextsOnThisServer.add(allocationContext); |
234 | } |
235 | } |
236 | return allocationContextsOnThisServer; |
237 | } |
238 | |
239 | private void applyChangeNumberOfCoresDecision( |
240 | NumberOfCoresDegree designDecision, Choice choice) { |
241 | if (!(choice instanceof DiscreteRangeChoice)){ |
242 | throwNewInvalidChoiceException(designDecision, choice); |
243 | } |
244 | |
245 | DiscreteRangeChoice discreteChoice = (DiscreteRangeChoice)choice; |
246 | |
247 | ProcessingResourceSpecification rightPrs = getProcessingRateSpecification(designDecision); |
248 | rightPrs.setNumberOfReplicas(discreteChoice.getChosenValue()); |
249 | |
250 | } |
251 | |
252 | private void applyChangeCapacityDecision(CapacityDegree designDecision, |
253 | Choice choice) { |
254 | if (!(choice instanceof DiscreteRangeChoice)){ |
255 | throwNewInvalidChoiceException(designDecision, choice); |
256 | } |
257 | |
258 | DiscreteRangeChoice discreteChoice = (DiscreteRangeChoice)choice; |
259 | |
260 | PassiveResource passiveResource = (PassiveResource)designDecision.getPrimaryChanged(); |
261 | passiveResource.getCapacity_PassiveResource().setSpecification(String.valueOf(discreteChoice.getChosenValue())); |
262 | |
263 | } |
264 | |
265 | private void applyChangeAllocationDecision( |
266 | AllocationDegree designDecision, Choice choice) { |
267 | |
268 | if (!(choice instanceof ClassChoice)){ |
269 | throwNewInvalidChoiceException(designDecision, choice); |
270 | } |
271 | ClassChoice enumChoice = (ClassChoice)choice; |
272 | |
273 | EObject entity = enumChoice.getChosenValue(); |
274 | if (!(entity instanceof ResourceContainer)){ |
275 | throwInvalidEntityException(designDecision,entity,ResourceContainer.class); |
276 | } |
277 | |
278 | ResourceContainer rc = (ResourceContainer)entity; |
279 | |
280 | ((AllocationContext)designDecision.getPrimaryChanged()).setResourceContainer_AllocationContext(rc); |
281 | |
282 | logger.debug("Handling a "+designDecision.getClass()+", setting resource container to "+rc.getEntityName()+ " for allocation context "+designDecision.getPrimaryChanged()); |
283 | |
284 | } |
285 | |
286 | private void applyChangeSchedulingDecision( |
287 | SchedulingPolicyDegree designDecision, Choice choice) { |
288 | if (!(choice instanceof SchedulingPolicyChoice)){ |
289 | throwNewInvalidChoiceException(designDecision, choice); |
290 | } |
291 | |
292 | SchedulingPolicyChoice schedChoice = (SchedulingPolicyChoice)choice; |
293 | SchedulingPolicy chosenPolicy = schedChoice.getChosenValue(); |
294 | |
295 | ProcessingResourceSpecification rightPrs = getProcessingRateSpecification(designDecision); |
296 | |
297 | rightPrs.setSchedulingPolicy(chosenPolicy); |
298 | |
299 | } |
300 | |
301 | /** |
302 | * @see applyChange(DesignDecision, PCMInstance, Double) |
303 | * @param designDecision |
304 | * @param pcm |
305 | * @param doubleGene |
306 | */ |
307 | private void applyChangeProcessingRateDecision (ProcessingRateDegree designDecision, Choice choice) { |
308 | //XXX The value is changed in the original model, not in a copy. |
309 | |
310 | if (!(choice instanceof ContinousRangeChoice || choice instanceof DiscreteRangeChoice)){ |
311 | throwNewInvalidChoiceException(designDecision,choice); |
312 | } |
313 | |
314 | double newRate = 0; |
315 | if (choice instanceof ContinousRangeChoice){ |
316 | ContinousRangeChoice doubleGene = (ContinousRangeChoice)choice; |
317 | newRate = doubleGene.getChosenValue(); |
318 | } else { |
319 | DiscreteRangeChoice doubleGene = (DiscreteRangeChoice)choice; |
320 | DiscreteProcessingRateDegree degree = (DiscreteProcessingRateDegree)designDecision; |
321 | newRate = degree.getFrom() + ((degree.getTo() - degree.getFrom()) / degree.getNumberOfSteps()) * doubleGene.getChosenValue(); |
322 | |
323 | } |
324 | |
325 | ProcessingResourceSpecification rightPrs = getProcessingRateSpecification(designDecision); |
326 | |
327 | // get initial models MTTF and rate to scale upcoming candidates MTTF with |
328 | if (Double.isNaN(this.initialRate)){ |
329 | //old spec for adjusting MTTF |
330 | String oldRateString = rightPrs.getProcessingRate_ProcessingResourceSpecification().getSpecification(); |
331 | this.initialRate = CostUtil.getInstance().getDoubleFromSpecification(oldRateString); |
332 | } |
333 | if (Double.isNaN(this.initialMTTF)){ |
334 | this.initialMTTF = rightPrs.getMTTF(); |
335 | } |
336 | |
337 | double mttf = this.initialMTTF * newRate / this.initialRate; |
338 | |
339 | //round to just four digits after decimal sign, to maybe have no errors by the above |
340 | //long l = (int)Math.round(mttf * 100000000); // truncates |
341 | //mttf = l / 100000000.0; |
342 | |
343 | rightPrs.getProcessingRate_ProcessingResourceSpecification().setSpecification(String.valueOf(newRate)); |
344 | rightPrs.setMTTF(mttf); |
345 | |
346 | logger.debug("Handling a "+designDecision.getClass()+", setting rate to "+newRate+" and MTTF to "+mttf+" (inital MTTF: "+this.initialMTTF+")"); |
347 | } |
348 | |
349 | private ProcessingResourceSpecification getProcessingRateSpecification( |
350 | ProcessingResourceDegree designDecision) { |
351 | ResourceContainer rc = ((ResourceContainer)designDecision.getPrimaryChanged()); |
352 | ProcessingResourceType prt = designDecision.getProcessingresourcetype(); |
353 | |
354 | ProcessingResourceSpecification rightPrs = null; |
355 | for (ProcessingResourceSpecification prs : rc.getActiveResourceSpecifications_ResourceContainer()) { |
356 | if (EMFHelper.checkIdentity(prs.getActiveResourceType_ActiveResourceSpecification(),prt)){ |
357 | rightPrs = prs; |
358 | break; |
359 | } |
360 | } |
361 | |
362 | if (rightPrs == null){ |
363 | throw new RuntimeException("Invalid degree of freedom "+designDecision.toString()+". The references ProcessingResourceType is not available in the given ResourceContainer."); |
364 | } |
365 | return rightPrs; |
366 | } |
367 | |
368 | private void throwNewInvalidChoiceException( |
369 | DegreeOfFreedomInstance designDecision, Choice choice) { |
370 | throw new InvalidChoiceForDegreeException(choice); |
371 | |
372 | } |
373 | |
374 | private void applyChangeAssembledComponentDecision ( AssembledComponentDegree designDecision, Choice choice) { |
375 | |
376 | if (!(choice instanceof ClassChoice)){ |
377 | throwNewInvalidChoiceException(designDecision, choice); |
378 | } |
379 | ClassChoice enumChoice = (ClassChoice)choice; |
380 | |
381 | //use the order of the enumeration of EquivalentComponents in the Domain |
382 | EObject entity = enumChoice.getChosenValue(); |
383 | if (!(entity instanceof RepositoryComponent)){ |
384 | throwInvalidEntityException(designDecision,entity,RepositoryComponent.class); |
385 | } |
386 | RepositoryComponent componentToBeAssembled = (RepositoryComponent)entity; |
387 | |
388 | AssemblyContext changedAssemblyContext = (AssemblyContext)designDecision.getPrimaryChanged(); |
389 | RepositoryComponent currentComponent = changedAssemblyContext.getEncapsulatedComponent__AssemblyContext(); |
390 | |
391 | //Do not replace component if it is already assembled. |
392 | if (!EMFHelper.checkIdentity(currentComponent, componentToBeAssembled)){ |
393 | AlternativeComponent.getInstance().applyChange(changedAssemblyContext, componentToBeAssembled); |
394 | } |
395 | |
396 | |
397 | logger.debug("Handling a "+designDecision.getClass()+", using component "+componentToBeAssembled.getEntityName()); |
398 | } |
399 | |
400 | @SuppressWarnings("unchecked") |
401 | private void throwInvalidEntityException( |
402 | DegreeOfFreedomInstance designDecision, EObject changeableEntity, |
403 | Class expectedClass) { |
404 | throw new RuntimeException("Entity "+changeableEntity+" of type "+changeableEntity.getClass().getName()+" is not an applicable value for degree of freedom "+designDecision.getClass().getName()+", required type is "+expectedClass.getName()); |
405 | |
406 | } |
407 | |
408 | public static String getGenotypeString(DesignDecisionGenotype genotype) { |
409 | StringBuilder genotypeStringBuilder = new StringBuilder(100); |
410 | for (Choice choice : genotype) { |
411 | genotypeStringBuilder.append(DSEDecoder.getDecisionString(choice)+";"); |
412 | } |
413 | return genotypeStringBuilder.toString(); |
414 | } |
415 | |
416 | public static String getDecisionString(Choice choice){ |
417 | DegreeOfFreedomInstance designDecision = choice.getDegreeOfFreedomInstance(); |
418 | |
419 | String result = ""; |
420 | /** |
421 | * TODO Make the selection of the appropriate applyChange method more implicit. Maybe move the method to DesignDecision itself. |
422 | */ |
423 | if (choice instanceof ContinousRangeChoice){ |
424 | result = ResultsWriter.formatDouble(((ContinousRangeChoice) choice).getChosenValue()); |
425 | } else if (choice instanceof ClassChoice){ |
426 | if (((ClassChoice) choice).getChosenValue() instanceof Entity){ |
427 | result = ((Entity)((ClassChoice)choice).getChosenValue()).getEntityName(); |
428 | } else { |
429 | result = ((ClassChoice)choice).getChosenValue().toString(); |
430 | } |
431 | } else if (choice instanceof DiscreteRangeChoice){ |
432 | result = String.valueOf(((DiscreteRangeChoice)choice).getChosenValue()); |
433 | } else if (choice instanceof SchedulingPolicyChoice){ |
434 | result = ((SchedulingPolicyChoice)choice).getChosenValue().getLiteral(); |
435 | } else { |
436 | logger.warn("There was an unrecognised design decision "+designDecision.getClass()); |
437 | } |
438 | return result; |
439 | } |
440 | |
441 | /** |
442 | * Calls getDoubleValueFor(String decisionString, DesignDecision designDecision) |
443 | * @param index |
444 | * @param decisionString |
445 | * @return |
446 | * @throws CoreException |
447 | */ |
448 | public static Choice getChoiceForIndex(int index, String decisionString) throws CoreException{ |
449 | |
450 | DegreeOfFreedomInstance designDecision = Opt4JStarter.getProblem().getDesignDecision(index); |
451 | |
452 | Choice value = getChoiceFor(decisionString, designDecision); |
453 | |
454 | return value; |
455 | |
456 | } |
457 | |
458 | public static Choice getChoiceFor(String decisionString, |
459 | DegreeOfFreedomInstance designDecision) throws CoreException { |
460 | Choice choice; |
461 | |
462 | designdecisionFactory factory = designdecisionFactoryImpl.init(); |
463 | |
464 | if (designDecision instanceof ContinuousRangeDegree){ |
465 | ContinuousRangeDegree contDegree = (ContinuousRangeDegree) designDecision; |
466 | double d = Double.parseDouble(decisionString); |
467 | if (!validRange(d, contDegree, contDegree.getFrom(), contDegree.getTo())){ |
468 | throw ExceptionHelper.createNewCoreException("Error: Value "+d+" is not a valid value for degree "+designDecision+" "+DegreeOfFreedomHelper.getDegreeDescription(designDecision)); |
469 | } |
470 | ContinousRangeChoice contChoice = factory.createContinousRangeChoice(); |
471 | contChoice.setChosenValue(d); |
472 | choice = contChoice; |
473 | } else if (designDecision instanceof DiscreteRangeDegree){ |
474 | DiscreteRangeDegree discDegree = (DiscreteRangeDegree) designDecision; |
475 | int i = Integer.parseInt(decisionString); |
476 | if (!validRange(i, discDegree, discDegree.getFrom(), discDegree.getTo())){ |
477 | throw ExceptionHelper.createNewCoreException("Error: Value "+i+"\" is not a valid value for degree "+designDecision+" "+DegreeOfFreedomHelper.getDegreeDescription(designDecision)); |
478 | } |
479 | DiscreteRangeChoice discChoice = factory.createDiscreteRangeChoice(); |
480 | discChoice.setChosenValue(i); |
481 | choice = discChoice; |
482 | } else if (designDecision instanceof ClassDegree){ |
483 | |
484 | ClassChoice enumChoice = factory.createClassChoice(); |
485 | Entity entity = getEntityFor((ClassDegree)designDecision, decisionString); |
486 | if (entity == null){ |
487 | throw ExceptionHelper.createNewCoreException("Error: Decision string \""+decisionString+"\" is not a valid value for degree "+designDecision+" "+DegreeOfFreedomHelper.getDegreeDescription(designDecision)); |
488 | } |
489 | enumChoice.setChosenValue(entity); |
490 | choice = enumChoice; |
491 | } else if (designDecision instanceof SchedulingPolicyDegree){ |
492 | |
493 | SchedulingPolicyChoice schedChoice = factory.createSchedulingPolicyChoice(); |
494 | |
495 | SchedulingPolicy chosenPolicy = SchedulingPolicy.get(decisionString); |
496 | |
497 | if (chosenPolicy == null){ |
498 | throw ExceptionHelper.createNewCoreException("Error: Decision string \""+decisionString+"\" is not a valid value for degree "+designDecision+" "+DegreeOfFreedomHelper.getDegreeDescription(designDecision)); |
499 | } |
500 | schedChoice.setChosenValue(chosenPolicy); |
501 | choice = schedChoice; |
502 | } else { |
503 | logger.warn("There was an unrecognised design decision "+designDecision.getClass()); |
504 | return null; |
505 | } |
506 | choice.setDegreeOfFreedomInstance(designDecision); |
507 | return choice; |
508 | } |
509 | |
510 | private static boolean validRange(double value, RangeDegree designDecision, double from, |
511 | double to) { |
512 | return (value >= from && value <= to); |
513 | } |
514 | |
515 | private static Entity getEntityFor(ClassDegree designDecision, |
516 | String decisionString) { |
517 | List<Entity> entities = new ArrayList<Entity>(); |
518 | for (EObject entity : designDecision.getClassDesignOptions()) { |
519 | if (entity instanceof Entity){ |
520 | entities.add((Entity) entity); |
521 | } |
522 | } |
523 | return getEntityByName(entities, decisionString); |
524 | } |
525 | |
526 | private static Entity getEntityByName(List<Entity> entities, |
527 | String decisionString) { |
528 | for (Entity entity : entities) { |
529 | if (entity.getEntityName().equals(decisionString)){ |
530 | return entity; |
531 | } |
532 | } |
533 | return null; |
534 | } |
535 | |
536 | /** |
537 | * Edits the passed genotype by inserting the passed choice at the index |
538 | * for the passed {@link DegreeOfFreedomInstance}. |
539 | * @param genotype |
540 | * @param degree |
541 | * @param choice |
542 | */ |
543 | public static void applyChangeToGenotype(DesignDecisionGenotype genotype, DegreeOfFreedomInstance degree, Choice choice){ |
544 | int index = Opt4JStarter.getProblem().getDesignDecisions().indexOf(degree); |
545 | genotype.set(index, choice); |
546 | } |
547 | |
548 | } |