完整的GA算法的工程实现,包括与轮询(RR)算法效果对比:
完整项目代码地址(导入到eclipse中即可运行): GA-cloudsim.zip
遗传算法GA的核心代码实现:
最核心:
private static ArrayList<int[]> GA(ArrayList<int[]> pop,int gmax,double crossoverProb,double mutationRate)
{
HashMap<Integer,double[]> segmentForEach=calcSelectionProbs(pop);
ArrayList<int[]> children=new ArrayList<int[]>();
ArrayList<int[]> tempParents=new ArrayList<int[]>();
while(children.size()<pop.size())
{
//selection phase:select two parents each time.
for(int i=0;i<2;i++)
{
double prob = new Random().nextDouble();
for (int j = 0; j < pop.size(); j++)
{
if (isBetween(prob, segmentForEach.get(j)))
{
tempParents.add(pop.get(j));
break;
}
}
}
//cross-over phase.
int[] p1,p2,p1temp,p2temp;
p1= tempParents.get(tempParents.size() - 2).clone();
p1temp= tempParents.get(tempParents.size() - 2).clone();
p2 = tempParents.get(tempParents.size() -1).clone();
p2temp = tempParents.get(tempParents.size() -1).clone();
if(new Random().nextDouble()<crossoverProb)
{
int crossPosition = new Random().nextInt(cloudletList.size() - 1);
//cross-over operation
for (int i = crossPosition + 1; i < cloudletList.size(); i++)
{
int temp = p1temp[i];
p1temp[i] = p2temp[i];
p2temp[i] = temp;
}
}
//choose the children if they are better,else keep parents in next iteration.
children.add(getFitness(p1temp) < getFitness(p1) ? p1temp : p1);
children.add(getFitness(p2temp) < getFitness(p2) ? p2temp : p2);
// mutation phase.
if (new Random().nextDouble() < mutationRate)
{
// mutation operations bellow.
int maxIndex = children.size() - 1;
for (int i = maxIndex - 1; i <= maxIndex; i++)
{
operateMutation(children.get(i), mutationRate);
}
}
}
gmax--;
return gmax > 0 ? GA(children, gmax, crossoverProb, mutationRate): children;
}
完整核心代码:
1 private static int[] findBestSchedule(ArrayList<int[]> pop)
2 {
3 double bestFitness=1000000000;
4 int bestIndex=0;
5 for(int i=0;i<pop.size();i++)
6 {
7 int []schedule=pop.get(i);
8 double fitness=getFitness(schedule);
9 if(bestFitness>fitness)
10 {
11 bestFitness=fitness;
12 bestIndex=i;
13 }
14 }
15 return pop.get(bestIndex);
16 }
17
18 private static int[] getScheduleByGA(int popSize,int gmax,double crossoverProb,double mutationRate)
19 {
20 ArrayList<int[]> pop=initPopsRandomly(cloudletList.size(),vmList.size(),popSize);
21 pop=GA(pop,gmax,crossoverProb,mutationRate);
22 return findBestSchedule(pop);
23 }
24
25 private static ArrayList<int[]> initPopsRandomly(int taskNum,int vmNum,int popsize)
26 {
27 ArrayList<int[]> schedules=new ArrayList<int[]>();
28 for(int i=0;i<popsize;i++)
29 {
30 //data structure for saving a schedule:array,index of array are cloudlet id,content of array are vm id.
31 int[] schedule=new int[taskNum];
32 for(int j=0;j<taskNum;j++)
33 {
34 schedule[j]=new Random().nextInt(vmNum);
35 }
36 schedules.add(schedule);
37 }
38 return schedules;
39 }
40
41 private static double getFitness(int[] schedule)
42 {
43 double fitness=0;
44
45 HashMap<Integer,ArrayList<Integer>> vmTasks=new HashMap<Integer,ArrayList<Integer>>();
46 int size=cloudletList.size();
47
48 for(int i=0;i<size;i++)
49 {
50 if(!vmTasks.keySet().contains(schedule[i]))
51 {
52 ArrayList<Integer> taskList=new ArrayList<Integer>();
53 taskList.add(i);
54 vmTasks.put(schedule[i],taskList);
55 }
56 else
57 {
58 vmTasks.get(schedule[i]).add(i);
59 }
60 }
61
62 for(Entry<Integer, ArrayList<Integer>> vmtask:vmTasks.entrySet())
63 {
64 int length=0;
65 for(Integer taskid:vmtask.getValue())
66 {
67 length+=getCloudletById(taskid).getCloudletLength();
68 }
69
70 double runtime=length/getVmById(vmtask.getKey()).getMips();
71 if (fitness<runtime)
72 {
73 fitness=runtime;
74 }
75 }
76
77 return fitness;
78 }
79
80 private static ArrayList<int[]> GA(ArrayList<int[]> pop,int gmax,double crossoverProb,double mutationRate)
81 {
82 HashMap<Integer,double[]> segmentForEach=calcSelectionProbs(pop);
83 ArrayList<int[]> children=new ArrayList<int[]>();
84 ArrayList<int[]> tempParents=new ArrayList<int[]>();
85 while(children.size()<pop.size())
86 {
87 //selection phase:select two parents each time.
88 for(int i=0;i<2;i++)
89 {
90 double prob = new Random().nextDouble();
91 for (int j = 0; j < pop.size(); j++)
92 {
93 if (isBetween(prob, segmentForEach.get(j)))
94 {
95 tempParents.add(pop.get(j));
96 break;
97 }
98 }
99 }
100 //cross-over phase.
101 int[] p1,p2,p1temp,p2temp;
102 p1= tempParents.get(tempParents.size() - 2).clone();
103 p1temp= tempParents.get(tempParents.size() - 2).clone();
104 p2 = tempParents.get(tempParents.size() -1).clone();
105 p2temp = tempParents.get(tempParents.size() -1).clone();
106 if(new Random().nextDouble()<crossoverProb)
107 {
108 int crossPosition = new Random().nextInt(cloudletList.size() - 1);
109 //cross-over operation
110 for (int i = crossPosition + 1; i < cloudletList.size(); i++)
111 {
112 int temp = p1temp[i];
113 p1temp[i] = p2temp[i];
114 p2temp[i] = temp;
115 }
116 }
117 //choose the children if they are better,else keep parents in next iteration.
118 children.add(getFitness(p1temp) < getFitness(p1) ? p1temp : p1);
119 children.add(getFitness(p2temp) < getFitness(p2) ? p2temp : p2);
120 // mutation phase.
121 if (new Random().nextDouble() < mutationRate)
122 {
123 // mutation operations bellow.
124 int maxIndex = children.size() - 1;
125
126 for (int i = maxIndex - 1; i <= maxIndex; i++)
127 {
128 operateMutation(children.get(i), mutationRate);
129 }
130 }
131 }
132
133 gmax--;
134 return gmax > 0 ? GA(children, gmax, crossoverProb, mutationRate): children;
135 }
136
137 public static void operateMutation(int []child,double mutationRate)
138 {
139 if(new Random().nextDouble()<mutationRate)
140 {
141 int mutationIndex=new Random().nextInt(cloudletList.size());
142 int newVmId=new Random().nextInt(vmList.size());
143 while(child[mutationIndex]==newVmId)
144 {
145 newVmId=new Random().nextInt(vmList.size());
146 }
147
148 child[mutationIndex]=newVmId;
149 }
150 }
151
152 private static boolean isBetween(double prob,double[]segment)
153 {
154 if(segment[0]<=prob&&prob<=segment[1])
155 return true;
156 return false;
157 }
158
159 private static HashMap<Integer,double[]> calcSelectionProbs(ArrayList<int[]> parents)
160 {
161 int size=parents.size();
162 double totalFitness=0;
163 ArrayList<Double> fits=new ArrayList<Double>();
164 HashMap<Integer,Double> probs=new HashMap<Integer,Double>();
165
166 for(int i=0;i<size;i++)
167 {
168 double fitness=getFitness(parents.get(i));
169 fits.add(fitness);
170 totalFitness+=fitness;
171 }
172 for(int i=0;i<size;i++)
173 {
174 probs.put(i,fits.get(i)/totalFitness );
175 }
176
177 return getSegments(probs);
178 }
179
180 private static HashMap<Integer,double[]> getSegments(HashMap<Integer,Double> probs)
181 {
182 HashMap<Integer,double[]> probSegments=new HashMap<Integer,double[]>();
183 //probSegments保存每个个体的选择概率的起点、终点,以便选择作为交配元素。
184 int size=probs.size();
185 double start=0;
186 double end=0;
187 for(int i=0;i<size;i++)
188 {
189 end=start+probs.get(i);
190 double[]segment=new double[2];
191 segment[0]=start;
192 segment[1]=end;
193 probSegments.put(i, segment);
194 start=end;
195 }
196
197 return probSegments;
198 }
199