分布估计算法解决多元背包问题【java描述】
1.分布估计算法


2.PBIL算法
分布估计算法根据分布模型的不同可以分为不同的算法,PBIL是其中最简单的一种(通过不断更新分布函数)
PBIL算法如下:

其他算法可以参考https://www.jianshu.com/p/28862a258eb8
3.实现
MKPIstance.java
1 import java.util.Arrays; 2 3 public class MKPInstance { 4 int n;//knapsacks 5 int m;//objects 6 int x;//OPT if known 7 int[] weight; 8 int[] cap; 9 int[][] constr; 10 int maxprofit; 11 double[][] utils; 12 13 14 @Override 15 public String toString() { 16 return "MKPInstance{" + 17 "n=" + n + 18 ", m=" + m + 19 ", x=" + x + 20 ", weight=" + Arrays.toString(weight) + 21 ", cap=" + Arrays.toString(cap) + 22 ", constr=" + Arrays.toString(constr) + 23 ", maxprofit=" + maxprofit + 24 ", utils=" + Arrays.toString(utils) + 25 '}'; 26 } 27 }
MKPReader.java
1 import java.io.BufferedReader; 2 import java.io.FileReader; 3 import java.io.IOException; 4 5 public class MKPReader { 6 public static int count = 0; 7 public static int i = 0; 8 public static BufferedReader in; 9 public static int weightcount = 0; 10 public static int weightflag = 0; 11 public static MKPInstance convertgkMKPInstance(String inputfilename) throws IOException{ 12 //System.out.println("Reading input sequences from file "+inputfilename); 13 in = new BufferedReader(new FileReader(inputfilename)); 14 String line = in.readLine(); // first line of file contains number of knapsacks and objects 15 line = line.trim(); 16 String[] fields = line.split("\\s+"); 17 MKPInstance instance = new MKPInstance(); 18 instance.n = Integer.parseInt(fields[0]);//objects 横向 19 instance.m = Integer.parseInt(fields[1]);//knapsacks 纵向 20 instance.x = Integer.parseInt(fields[2]); 21 instance.weight = new int[instance.n]; 22 instance.cap = new int[instance.m]; 23 instance.constr = new int[instance.m][instance.n]; 24 weightflag=instance.m; 25 weightcount = 0; 26 do{ 27 line = in.readLine(); 28 line = line.trim(); 29 count=0; 30 processLine(count, line, instance); 31 }while(i!=instance.n); 32 line = in.readLine(); 33 line = line.trim(); 34 count=0; 35 processKnapsacks(count, line, instance); 36 in.close(); 37 count = 0; 38 i = 0; 39 return instance; 40 } 41 public static MKPInstance convertMKPInstance(String inputfilename) throws IOException{ 42 //System.out.println("Reading input sequences from file "+inputfilename); 43 in = new BufferedReader(new FileReader(inputfilename)); 44 String line = in.readLine(); // first line of file contains number of knapsacks and objects 45 line = line.trim(); 46 String[] fields = line.split("\\s+"); 47 MKPInstance instance = new MKPInstance(); 48 instance.n = Integer.parseInt(fields[0]);//objects 49 instance.m = Integer.parseInt(fields[1]);//knapsacks 50 instance.x = Integer.parseInt(fields[2]); 51 instance.weight = new int[instance.n]; 52 instance.cap = new int[instance.m]; 53 instance.constr = new int[instance.m][instance.n]; 54 line = in.readLine(); 55 line = line.trim(); 56 count=0; 57 processWeights(count, line, instance); 58 do{ 59 line = in.readLine(); 60 line = line.trim(); 61 count=0; 62 processConstraints(count, line, instance); 63 }while(i!=instance.m); 64 line = in.readLine(); 65 line = line.trim(); 66 count=0; 67 processKnapsacks(count, line, instance); 68 in.close(); 69 count = 0; 70 i = 0; 71 instance.maxprofit = 0; 72 for(int i = 0; i< instance.n;i++){ 73 if (instance.weight[i]>instance.maxprofit){ //find largest profit value 74 instance.maxprofit=instance.weight[i]; 75 } 76 } 77 return instance; 78 } 79 public static void processWeights(int count, String line, MKPInstance instance)throws IOException{ 80 String[] fields = line.split("\\s+"); 81 int counter = count; 82 for (int j = 0; j < fields.length; j++) { 83 int k = Integer.parseInt(fields[j]); 84 instance.weight[j+count]=k; 85 counter++; 86 } 87 if (counter != instance.n){ 88 line = in.readLine(); 89 line = line.trim(); 90 processWeights(counter, line, instance); 91 } 92 } 93 public static void processKnapsacks(int count, String line, MKPInstance instance)throws IOException{ 94 String[] fields = line.split("\\s+"); 95 int counter = count; 96 for (int j = 0; j < fields.length; j++) { 97 int k = Integer.parseInt(fields[j]); 98 instance.cap[j+count]=k; 99 counter++; 100 } 101 if (counter != instance.m){ 102 line = in.readLine(); 103 line = line.trim(); 104 processKnapsacks(counter, line, instance); 105 } 106 } 107 public static void processConstraints(int count, String line, MKPInstance instance)throws IOException{ 108 String[] fields = line.split("\\s+"); 109 int counter = count; 110 for (int j = 0; j < fields.length; j++) { 111 int k = Integer.parseInt(fields[j]); 112 instance.constr[i][j+count]=k; 113 counter++; 114 } 115 if (counter != instance.n){ 116 line = in.readLine(); 117 line = line.trim(); 118 processConstraints(counter, line, instance); 119 } 120 else{i++;} 121 } 122 public static void processLine(int count, String line, MKPInstance instance)throws IOException{ 123 String[] fields = line.split("\\s+"); 124 int counter = count; 125 for (int j = 0; j < fields.length; j++) { 126 int k = Integer.parseInt(fields[j]); 127 if(weightflag==instance.m){ 128 instance.weight[weightcount]=k; 129 weightcount++; 130 weightflag=0; 131 }else{ 132 instance.constr[counter][i]=k; 133 counter++; 134 weightflag++; 135 } 136 } 137 if (counter != instance.m){ 138 line = in.readLine(); 139 line = line.trim(); 140 processLine(counter, line, instance); 141 } 142 else{i++;} 143 } 144 }
Main.java
1 import java.io.IOException; 2 import java.nio.file.Paths; 3 import java.sql.Connection; 4 import java.util.*; 5 6 final class Config { 7 public static double INIT_P = 0.5; 8 public static int SAMPLE_N = 100; 9 public static int SAMPLE_M = 60; 10 public static double UPDATE_A = 0.5; 11 public static int LOOP_SIZE = 1000; 12 } 13 14 public class Main { 15 static MKPInstance instance = null; 16 static List<List<Integer>> group = null; 17 static Random random = new Random(); 18 static int index = 0; 19 static Scanner scanner = new Scanner(System.in); 20 static String file_path = null; 21 22 23 public static void main(String[] args) { 24 System.out.print("please input file path:"); 25 file_path = scanner.nextLine().trim(); 26 PBIL(); 27 } 28 29 /* 30 * PBIL init 31 * 32 * */ 33 static void init() { 34 35 try { 36 instance = MKPReader.convertMKPInstance(file_path); 37 System.out.println(instance.toString()); 38 } catch (IOException e) { 39 e.printStackTrace(); 40 } 41 group = new ArrayList<List<Integer>>(); 42 instance.utils = new double[Config.LOOP_SIZE][instance.n]; 43 44 for (int i = 0; i < instance.n; ++i) { 45 instance.utils[index][i] = Config.INIT_P; 46 } 47 ++index; 48 group.clear(); 49 group.addAll(sample(index - 1)); 50 Config.LOOP_SIZE = instance.n * instance.m * 100; 51 } 52 53 static String list2string(List<Integer> lt) { 54 StringBuilder sb = new StringBuilder(); 55 for (int t : lt) { 56 sb.append(t); 57 } 58 return sb.toString(); 59 } 60 61 static List<List<Integer>> sample(int index) { 62 List<List<Integer>> res = new ArrayList<List<Integer>>(); 63 64 Set<String> set = new HashSet<String>(); 65 for (int i = 0; i < Config.SAMPLE_N; ++i) { 66 List<Integer> lt = new LinkedList<Integer>(); 67 for (int j = 0; j < instance.n; ++j) { 68 if (random.nextDouble() < instance.utils[index][j]) { 69 lt.add(1); 70 } else { 71 lt.add(0); 72 } 73 } 74 String s = list2string(lt); 75 if (set.contains(s) || (!isValid(s))) { 76 --i; 77 } else { 78 res.add(lt); 79 set.add(s); 80 } 81 } 82 return res; 83 } 84 85 static boolean isValid(String s) { 86 int[] temp = new int[instance.m]; 87 88 for (int i = 0; i < s.length(); ++i) { 89 if (s.charAt(i) == '1') { 90 for (int j = 0; j < instance.m; ++j) { 91 temp[j] += instance.constr[j][i]; 92 } 93 } 94 } 95 for (int i = 0; i < instance.m; ++i) { 96 if (temp[i] > instance.cap[i]) { 97 return false; 98 } 99 } 100 return true; 101 } 102 103 104 static int fitnessOneS(List<Integer> lt) { 105 int fit = 0; 106 for (int i = 0; i < lt.size(); ++i) { 107 int p = lt.get(i); 108 if (p == 1) { 109 fit += instance.weight[i]; 110 } 111 } 112 return fit; 113 } 114 115 static int getWeight(List<Integer> s) { 116 int res = 0; 117 for (int i = 0; i < s.size(); ++i) { 118 int p = s.get(i); 119 if (p == 1) { 120 res += instance.weight[i]; 121 } 122 } 123 return res; 124 } 125 126 static List<Integer> fitnessAll(List<List<Integer>> lt) { 127 List<Integer> res = new ArrayList<Integer>(); 128 for (List<Integer> s : lt) { 129 res.add(fitnessOneS(s)); 130 } 131 return res; 132 } 133 134 135 static List<List<Integer>> choose(int size) { 136 class Pair { 137 List<Integer> s; 138 int fit; 139 140 public Pair(List<Integer> s, int fit) { 141 this.s = s; 142 this.fit = fit; 143 } 144 } 145 146 List<Pair> lt = new ArrayList<Pair>(); 147 List<Integer> fits = fitnessAll(group); 148 149 for (int i = 0; i < group.size(); ++i) { 150 lt.add(new Pair(group.get(i), fits.get(i))); 151 } 152 153 lt.sort(new Comparator<Pair>() { 154 @Override 155 public int compare(Pair o1, Pair o2) { 156 return o2.fit - o1.fit; 157 } 158 }); 159 160 161 List<List<Integer>> res = new ArrayList<List<Integer>>(); 162 for (int i = 0; i < size; ++i) { 163 res.add(lt.get(i).s); 164 } 165 return res; 166 } 167 168 169 static void update(List<List<Integer>> lt) { 170 double[] temp = new double[instance.n]; 171 for (int i = 0; i < lt.size(); ++i) { 172 List<Integer> s = lt.get(i); 173 for (int j = 0; j < s.size(); ++j) { 174 int p = s.get(j); 175 if (p == 1) { 176 temp[j] += 1.0; 177 } 178 } 179 } 180 for (int i = 0; i < temp.length; ++i) { 181 temp[i] /= lt.size(); 182 } 183 184 for (int i = 0; i < instance.n; ++i) { 185 instance.utils[index][i] = (1 - Config.UPDATE_A) * instance.utils[index - 1][i] + Config.UPDATE_A * temp[i]; 186 } 187 } 188 189 public static void PBIL() { 190 init();// 191 List<List<Integer>> lt = null; 192 for (int i = 0; i < Config.LOOP_SIZE; ++i) { 193 List<List<Integer>> better_sample = choose(Config.SAMPLE_M); 194 update(better_sample); 195 196 List<List<Integer>> new_sample = sample(index); 197 group.addAll(new_sample); 198 lt = choose(Config.SAMPLE_N); 199 group.clear(); 200 group.addAll(lt); 201 } 202 System.out.print("best:"); 203 System.out.print(lt.get(0)); 204 System.out.print(" weight:"); 205 System.out.println(getWeight(lt.get(0))); 206 207 } 208 }
4.结论
分布估计算法相比遗传算法更加宏观,通过更新种群的分布密度来逐步优化。
【点赞、关注、评论三连生活更美好】

浙公网安备 33010602011771号