完整的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