分布估计算法解决多元背包问题【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.结论

分布估计算法相比遗传算法更加宏观,通过更新种群的分布密度来逐步优化。

 

posted @ 2019-09-10 21:17  mzl123  阅读(283)  评论(0)    收藏  举报