【发布时间】:2016-06-28 12:54:59
【问题描述】:
我有一个物品的 ArrayList(每个物品都有重量和利润):
ArrayList 项目列表: [{权重:3,收益:10},{权重:15,收益:50},{权重:7,收益:25},{权重:6,收益:15},{权重:4,收益:10} ]
然后我有一个随机的 bitStrings 表示在给定最大重量为 20(容量 = 20)的情况下要携带哪些物品。
假设获得的初始随机位是 [1,1,0,0,0],这意味着第 1 项和第 2 项得到:
总重量 = 3 + 15 = 18 [
然后我有一个随机位要翻转(如果该位是 1 -> 0,并且如果选择翻转的位是 0 -> 1)。假设翻转位的顺序是[3,2,1,4,0]。
首先,索引 3 处的位将被翻转并计算总重量,如下所示:
[1,1,0,0,0] --> [1,1,0,1,0]
因此,bit[3] 翻转后的新位串:[1,1,0,1,0]。
然后再次计算总重量:
新位串的总权重 = 3 + 15 + 6 = 24 [>容量]
所以总数超过了容量,我希望新的位串在翻转之前分配回前一个位串:
[1,1,0,1,0] --> 返回之前的状态:[1,1,0,0,0]。
返回状态后:[1,1,0,0,0]下一位会从刚才的顺序翻转[3,2,1,4,0]但是现在我必须按照从左到右的顺序翻转索引 2 处的位。这变成:
从 [1,1,0,0,0] --> 翻转位[2]:
[1,1,0,0,0] --> [1,1,1,0,0]
然后做同样的计算重量等。
如果总数仍然超过,它将返回到以前的状态,但如果它没有超过,它将新的解决方案添加到新的 ArrayList。
我已经对其进行了一些编码,但我的问题是要回到以前的状态,并将接受的位字符串添加到 ArrayList 改进。它仅存储最新更新的解决方案,并且正在替换其他已接受的解决方案,如我获得的输出所示。
这是我的代码: '
public class KnapsackHC {
public static void main (String[] args){
int n = 5, capacity = 20, pointer, toFlip;
//Item items = new Item();
ArrayList<Item> itemList = new ArrayList<Item>();
ArrayList<Integer> solution = new ArrayList<Integer>();
ArrayList<Integer> currentSolution = new ArrayList<Integer>();
ArrayList<Integer> flipOrder = new ArrayList<Integer>();
ArrayList<ArrayList<Integer>> improve = new ArrayList<ArrayList<Integer>>();
//ArrayList<Integer> temp = new ArrayList<Integer>();
itemList = getProblem();
solution = initialSolution(n);
currentSolution = solution;
flipOrder = randomFlipOrder(n);
System.out.println("List of Items: " + itemList);
System.out.println("Initial solution: " + solution);
System.out.println("Current solution: " + currentSolution);
System.out.println("Random order: " + flipOrder);
for (int i = 0; i < flipOrder.size(); i++){
int totalWeight = 0, totalProfit = 0;
pointer = flipOrder.get(i);
toFlip = solution.get(pointer);
for (int j = 0; j < solution.size(); j++){
if (solution.get(j) == 1){
totalWeight += itemList.get(j).getWeight();
totalProfit += itemList.get(j).getProfit();
}
}
System.out.println();
System.out.println("Updated Solution: " + currentSolution);
System.out.println("Total Weight Solution " + (i+1) + " : " + totalWeight + " | Total Profit Solution " + (i+1) + " : " + totalProfit);
if (totalWeight <= capacity){
System.out.println("----------NOT EXCEED-----------");
currentSolution = solution;
System.out.println("currentSolution BEFORE FLIP: " + currentSolution);
improve.add(currentSolution);
System.out.println("Improve: " + improve);
if (toFlip == 1){
solution.set(pointer, 0);
}
else if (toFlip == 0){
solution.set(pointer, 1);
}
System.out.println("solution AFTER FLIP from Random Order [" + flipOrder.get(i) + "] : " + solution);
currentSolution = solution;
//solution = new ArrayList<Integer>();
System.out.println("--------------------------------");
}
else{
System.out.println("----------EXCEED!!!!------------");
//currentSolution = solution;
System.out.println("currentSolution BEFORE FLIP {return back to previous state}: " + currentSolution);
if (toFlip == 1){
solution.set(pointer, 0);
}
else if (toFlip == 0){
solution.set(pointer, 1);
}
System.out.println("solution AFTER FLIP from Random Order [" + flipOrder.get(i) + "] : " + solution);
System.out.println("--------------------------------");
}
}
}
/*
public static ArrayList<Integer> calcFitness(ArrayList<Integer> currentSolution, ArrayList<Integer> solution, ArrayList<Item> itemList, int capacity){
System.out.println("\nAfter Flip: " + solution);
System.out.println("Current Solution: " + currentSolution);
int totalWeight = 0;
int totalProfit = 0;
for (int i = 0; i < solution.size(); i++){
if (solution.get(i) == 1){
totalWeight += itemList.get(i).getWeight();
totalProfit += itemList.get(i).getProfit();
}
}
System.out.println("Total Weight: " + totalWeight + " || Total Profit: " + totalProfit);
if (totalWeight <= capacity){
currentSolution = solution;
System.out.println("Solution change: " + currentSolution);
System.out.println();
return solution;
}
else{
System.out.println("Solution NO change: " + currentSolution);
System.out.println();
return currentSolution;
}
}*/
public static ArrayList<Item> getProblem(){
ArrayList<Item> itemsArr = new ArrayList<Item>();
try {
BufferedReader in = new BufferedReader( new FileReader("knapsack_problem_5.txt" ) );
int i = 0;
String str;
while ( (str = in.readLine() )!= null ) {
String[] item = str.split( "," );
//System.out.print("Weight #" + i + " : " + Integer.parseInt(item[0]));
//System.out.print("Profit #" + i + " : " + Integer.parseInt(item[1]));
int weight = Integer.parseInt(item[0]);
int profit = Integer.parseInt(item[1]);
itemsArr.add(i,new Item(weight,profit));
i++;
}
in.close();
} catch ( IOException ex ) {
System.err.println( "Error: Can't open the file for reading." );
}
return itemsArr;
}
//generate initial solution(bits) randomly
public static ArrayList<Integer> initialSolution(int length){
Random r = new Random();
ArrayList<Integer> solution = new ArrayList<Integer>(length);
// generate some random boolean values
boolean[] booleans = new boolean[length];
for (int i = 0; i < booleans.length; i++) {
booleans[i] = r.nextBoolean();
}
for (boolean b : booleans) {
if (b == true){
solution.add(1);
}
else{
solution.add(0);
}
}
return solution;
}
public static ArrayList<Integer> randomFlipOrder(int length){
ArrayList<Integer> order = new ArrayList<Integer>();
Random r = new Random();
for (int i = 0; i < length; i++){
order.add(i);
}
Collections.shuffle(order);
return order;
}
}
'
我的文本文件包含以下内容(重量、利润):
3,10
15,50
7,25
6,15
4,10
我得到的输出(将随机生成初始位串和翻转位的随机顺序):
项目列表:[{重量:3,利润:10},{重量:15,利润:50},{重量:7,利润:25},{重量:6,利润:15},{重量: 4, 利润: 10}]
初始解决方案:[1, 0, 0, 1, 0]
当前解决方案:[1, 0, 0, 1, 0]
随机顺序:[2, 4, 0, 1, 3]
更新的解决方案:[1, 0, 0, 1, 0]
总重量解决方案 1 : 9 |总利润解决方案 1 : 25
---------不超过------------
翻转前的当前解决方案:[1, 0, 0, 1, 0]
改进:[[1, 0, 0, 1, 0]]
随机顺序翻转后的解决方案 [2] : [1, 0, 1, 1, 0]
更新的解决方案:[1, 0, 1, 1, 0]
总重量解决方案 2 : 16 |总利润解决方案 2:50
---------不超过------------
翻转前的当前解决方案:[1, 0, 1, 1, 0]
改进:[[1, 0, 1, 1, 0], [1, 0, 1, 1, 0]] 它不存储以前接受的解决方案,而是用新的解决方案替换它强>
随机顺序翻转后的解决方案 [4] : [1, 0, 1, 1, 1]
更新的解决方案:[1, 0, 1, 1, 1]
总重量解决方案 3 : 20 |总利润解决方案 3 : 60
---------不超过------------
翻转前的当前解决方案:[1, 0, 1, 1, 1]
改进:[[1, 0, 1, 1, 1], [1, 0, 1, 1, 1], [1, 0, 1, 1, 1]]
从随机顺序 [0] 翻转后的解决方案:[0, 0, 1, 1, 1]
更新的解决方案:[0, 0, 1, 1, 1]
总重量解 4 : 17 |总利润解决方案 4:50
---------不超过------------
翻转前的当前解决方案:[0, 0, 1, 1, 1]
改进:[[0, 0, 1, 1, 1], [0, 0, 1, 1, 1], [0, 0, 1, 1, 1], [0, 0, 1, 1 , 1]]
从随机顺序 [1] 翻转后的解决方案:[0, 1, 1, 1, 1]
更新的解决方案:[0, 1, 1, 1, 1]
总重量解 5 : 32 |总利润解决方案 5:100
---------超过!!!!------------
currentSolution BEFORE FLIP {return back to previous state}: [0, 1, 1, 1, 1] ==> 这应该返回到 [0,0,1,1,1] 其中容量不超过
解决方案 AFTER FLIP from Random Order [3] : [0, 1, 1, 0, 1] ==> 这应该从 [0,0,1,1,1] 和 bcomes 中翻转 -> [0,0,1,0,1]
最后,一旦它变成 [0,0,1,0,1] 它应该再次显示总重量并显示但它不显示。
我不确定错误在哪里。请帮忙。谢谢。
【问题讨论】:
-
提示:这确实是很多的输入。为了你(也是为了我们),我建议减少整个问题的核心。换句话说:尝试找到一段示例代码来显示您的问题(换句话说:使用列表执行某些操作的代码),它没有权重、文件等的“开销”......以及旁注:这样的代码非常适合 TDD 和单元测试。做TDD;你会从小的、有效的代码开始;逐步增加。与将 100 行代码组合在一起相比,它的效果要好得多 ...然后发现:那里的某个错误
标签: java algorithm arraylist random bit