仓库配货问题:
有A、B、C、D…等n各仓库,实际拥有的货物数量为,现在有总量为T的货物,需要按照一定的比例从各个仓库获取,然而有些仓库的实际数量可能不够、而有些仓库的实际数量可能有多余。部分仓库不够的差额需要从其余有多余货物的仓库中取足其差额。
则问题转化为以下优化函数:
上述目标函数描述了问题的目标,不过两个目标函数看着实在头大,好在实际求解过程中并不需要直接计算这两个目标函数来得到最终结果,这里列出这两个目标函数只是方便把问题描述清楚。实际计算时,只需要模仿人分配的流程,先找出哪些差额不够的,计算差额,并重新将差额分配给其余货物满足当前需求数量的,在分配差额后,会出现部分原本实际数量够分配的仓库由于不足其他仓库的差额后数量不够分配的情况,因此需要进行又一次的迭代。
过程比较简单清晰,直接上代码看看:
package AssignOptmize;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Administrator on 2015/10/23.
*/
public class AssignOptimize {
private int ITER = 2;
private double TOTAL = 0;
private int SIZE = 0;
/*理想情况下每组分配的比例*/
List<Double> factor;
/*理想情况下每组需要分配的数量*/
List<Double> require;
/*每组还剩多少可以分配的数量*/
List<Double> realNumber;
/*每组实际分配的数量*/
List<Double> optNumber = new ArrayList<Double>();
/*每组实际拥有的数量*/
List<Double> haveNumber = new ArrayList<Double>();
AssignOptimize(List<Double> factor,List<Double> realNumber,int total){
this.factor = factor;
this.realNumber = realNumber;
this.SIZE = factor.size();
require = new ArrayList<Double>();
for(int index=0; index<SIZE; index++){
double need = Math.rint(total*factor.get(index)<1?1:total*factor.get(index));
require.add(need);
optNumber.add(0.0);
haveNumber.add(realNumber.get(index));
}
}
/**
* 进行目标求解
* @param factor 分配比例
* @param require 各组的需求数量
* @param realNumber 各组的实际数量
* @return 各组优化后需要获取的数量
*/
public void optimize(){
int iterate = 0;
while(iterate<(require.size()+ITER)){
updateTotal();
updateFactor();
AssignTask();
iterate++;
double taskCount = 0;
System.out.println("第"+iterate+"分配开始");
for(int index=0; index<require.size(); index++){
taskCount += optNumber.get(index);
System.out.println("需要数目:"+require.get(index)+" 已经分配:"+optNumber.get(index));
}
updateTotal();
System.out.println("还需要"+TOTAL);
System.out.println("已经分配的总数目"+taskCount);
System.out.println();
}
}
/**
* 还需要这么多数量
* @param require 各组的需求数量
* @param exist 各组的已经分配的数量
*/
private void updateTotal(){
if(require.size() != optNumber.size()){
TOTAL = 0;
return;
}
TOTAL = 0;
for(int index=0; index<require.size(); index++){
double re = require.get(index);
double exs = optNumber.get(index);
TOTAL += re-exs;
}
}
/**根据实例情况重新计算各组应该分配的比例**/
private void updateFactor(){
double fac1 = 0;
double assign = 0;
for(int index=0; index<require.size(); index++){
if(realNumber.get(index)>0){
fac1 += factor.get(index);
}
else{
assign += factor.get(index);
}
}
/*重新计算各个组的比例*/
for(int index=0; index<require.size(); index++){
if(realNumber.get(index)>0){
double norFac = factor.get(index);
norFac = norFac + assign*norFac/fac1;
factor.set(index, norFac);
}
else{
factor.set(index, 0.0);
}
}
}
/**
* 对差额进行重新分配
*/
private void AssignTask(){
for(int index=0; index<require.size(); index++){
if(realNumber.get(index)>0){
double add = Math.rint(TOTAL*factor.get(index));
double have = Math.rint((realNumber.get(index)-optNumber.get(index)));
if(add>have){
optNumber.set(index, optNumber.get(index)+have);
realNumber.set(index, 0.0);
}
else{
optNumber.set(index, optNumber.get(index)+add);
realNumber.set(index, realNumber.get(index)-add);
}
}
}
}
/*
* test
*/
public static void main(String[] args) throws Exception {
List<Double> factor = new ArrayList<Double>();
List<Double> realNumber = new ArrayList<Double>();
int total = 35;
factor.add(0.1);
realNumber.add(0.0);
factor.add(0.2);
realNumber.add(30.0);
factor.add(0.3);
realNumber.add(0.0);
factor.add(0.05);
realNumber.add(40.0);
factor.add(0.35);
realNumber.add(1.0);
AssignOptimize optmize = new AssignOptimize(factor,realNumber,total);
optmize.optimize();
}
}
每一次迭代设计三个过程
1、更新剩下的需求总量
2、更新分配比例
3、计算各个仓库的分配数目
当存在N各仓库时,最多迭代N次即可收敛得到最优解。