1 | package de.uka.ipd.sdq.dsexplore.opt4j.optimizer; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.Collection; |
5 | import org.opt4j.common.random.Rand; |
6 | import org.opt4j.core.Individual; |
7 | import org.opt4j.core.IndividualBuilder; |
8 | import org.opt4j.core.problem.Genotype; |
9 | import org.opt4j.operator.copy.Copy; |
10 | import org.opt4j.operator.crossover.Crossover; |
11 | import org.opt4j.operator.mutate.Mutate; |
12 | import org.opt4j.optimizer.ea.Coupler; |
13 | import org.opt4j.optimizer.ea.CrossoverRate; |
14 | import org.opt4j.optimizer.ea.Mating; |
15 | import org.opt4j.optimizer.ea.Pair; |
16 | |
17 | import com.google.inject.Inject; |
18 | |
19 | import de.uka.ipd.sdq.dsexplore.opt4j.optimizer.heuristic.operators.QMLBoundDependentTacticOperatorsManager; |
20 | import de.uka.ipd.sdq.dsexplore.opt4j.optimizer.heuristic.operators.TacticOperatorsManager; |
21 | import de.uka.ipd.sdq.dsexplore.opt4j.representation.*; |
22 | import de.uka.ipd.sdq.dsexplore.opt4j.start.Opt4JStarter; |
23 | |
24 | /** |
25 | * |
26 | * @author martens, beyer, noorshams |
27 | * |
28 | */ |
29 | public class MatingWithHeuristics extends Mating { |
30 | |
31 | private TacticOperatorsManager heuristicManager; |
32 | |
33 | public TacticOperatorsManager getHeuristicManager() { |
34 | return this.heuristicManager; |
35 | } |
36 | |
37 | @Inject |
38 | public MatingWithHeuristics(Crossover<Genotype> crossover, Mutate<Genotype> mutate, Copy<Genotype> copy, |
39 | Coupler coupler, CrossoverRate crossoverRate, Rand random, |
40 | IndividualBuilder individualBuilder, |
41 | /*noorshams: inject this, I don't want to break the "injection chain"*/ |
42 | QMLBoundDependentTacticOperatorsManager qmlTacticManager) { |
43 | super(crossover, mutate, copy, coupler, crossoverRate, random, |
44 | individualBuilder); |
45 | if (Opt4JStarter.getDSEWorkflowConfig().isConsiderQMLBoundsWhenApplyingHeuristics()) { |
46 | heuristicManager = qmlTacticManager; |
47 | } else if (Opt4JStarter.getDSEWorkflowConfig().isUseHeuristics()){ |
48 | heuristicManager = new TacticOperatorsManager(copy, (DSEIndividualBuilder)individualBuilder); |
49 | } |
50 | } |
51 | |
52 | /* |
53 | * (non-Javadoc) |
54 | * |
55 | * @see org.opt4j.operator.mating.Mating#getOffspring(int, |
56 | * java.util.Collection) |
57 | */ |
58 | @Override |
59 | public Collection<Individual> getOffspring(int size, |
60 | Collection<Individual> parents) { |
61 | Collection<Individual> offspring = new ArrayList<Individual>(); |
62 | Collection<Pair<Individual>> couples = coupler.getCouples((int) Math |
63 | .ceil(((double) size / 2)), new ArrayList<Individual>(parents)); |
64 | |
65 | for (Pair<Individual> couple : couples) { |
66 | boolean crossover = random.nextDouble() <= crossoverRate.get(); |
67 | Individual parent1 = couple.getFirst(); |
68 | Individual parent2 = couple.getSecond(); |
69 | Pair<Individual> i = mate(parent1, parent2, crossover); |
70 | Individual i1 = i.getFirst(); |
71 | Individual i2 = i.getSecond(); |
72 | |
73 | offspring.add(i1); |
74 | if (offspring.size() < size) { |
75 | offspring.add(i2); |
76 | } |
77 | } |
78 | |
79 | return offspring; |
80 | } |
81 | |
82 | /** |
83 | * Performs the actual coupler process of two parents using |
84 | * heuristics |
85 | * |
86 | * @param parent1 |
87 | * parent one |
88 | * @param parent2 |
89 | * parent two |
90 | * @param doCrossover |
91 | * indicates whether the coupler shall take place |
92 | * @return the two offspring individuals |
93 | */ |
94 | private Pair<Individual> mate(Individual parent1, Individual parent2, |
95 | boolean doCrossover) { |
96 | |
97 | Genotype p1 = parent1.getGenotype(); |
98 | Genotype p2 = parent2.getGenotype(); |
99 | Genotype o1, o2; |
100 | |
101 | Individual i1 = null; |
102 | Individual i2 = null; |
103 | |
104 | // try to apply heuristics |
105 | // if not applicable: mutate |
106 | boolean useHeuristics = Opt4JStarter.getDSEWorkflowConfig().isUseHeuristics(); |
107 | double tacticsProbability = Opt4JStarter.getDSEWorkflowConfig().getTacticsProbability(); |
108 | |
109 | if (useHeuristics && Math.random() < tacticsProbability){ |
110 | i1 = heuristicManager.getCandidate((DSEIndividual)parent1); |
111 | i2 = heuristicManager.getCandidate((DSEIndividual)parent2); |
112 | } |
113 | |
114 | if (i1 == null && i2 == null){ |
115 | |
116 | if (doCrossover) { |
117 | Pair<Genotype> offspring = crossover.crossover(p1, p2); |
118 | o1 = offspring.getFirst(); |
119 | o2 = offspring.getSecond(); |
120 | // do mutate but don't use heuristics |
121 | mutate.mutate(o1); |
122 | mutate.mutate(o2); |
123 | |
124 | i1 = individualBuilder.build(o1); |
125 | i2 = individualBuilder.build(o2); |
126 | } // else go into mutation code below as i1 and i2 are null. |
127 | } |
128 | |
129 | if (i1 == null) { |
130 | o1 = copy.copy(p1); |
131 | mutate.mutate(o1); |
132 | i1 = individualBuilder.build(o1); |
133 | } |
134 | if (i2 == null) { |
135 | o2 = copy.copy(p2); |
136 | mutate.mutate(o2); |
137 | i2 = individualBuilder.build(o2); |
138 | } |
139 | |
140 | Pair<Individual> individuals = new Pair<Individual>(i1, i2); |
141 | return individuals; |
142 | } |
143 | |
144 | } |