小白求助,关于Java编写遗传算法求解成本最小化问题

Anastasia1015 2018-05-07 05:12:05
做仓储管理系统的毕设中需要添加个遗传算法,遇到了难题。
程序出现除零错误,但是订货量minstock与安全库存点safestock不应该赋初值,而是由getminStock方法与getsafeStock方法转换得到,然后代入适应度函数求解。不知道是不是因为方法不对,导致传值为空。

package gatest;
public class GA {
private int ChrNum = 50; //染色体数量
private String[] ipop = new String[ChrNum]; //一个种群中染色体总数
private int generation = 0; //染色体代号
public static final int GENE = 10; //基因数
private double bestfitness = Double.MAX_VALUE; //函数最优解
private int bestgenerations; //所有子代与父代中最好的染色体
private String beststr; //最优解的染色体的二进制码
public static int safestock;//安全库存
public static int minstock; //订货量
// 初始化一条染色体(用二进制字符串表示)
private String initChr() {
String res = "";
for (int i = 0; i < GENE; i++) {
if (Math.random() > 0.5) {
res += "0";
} else {
res += "1";
}
}
return res;
}
// 初始化一个种群(50条染色体)
private String[] initPop() {
String[] ipop = new String[ChrNum];
for (int i = 0; i < ChrNum; i++) {
ipop[i] = initChr();
}
return ipop;
}
//将染色体转换成x,y变量的值
//将string类型的染色体前5位作为安全库存、并解码为int型
public int getsafeStock(String res){
safestock = Integer.parseInt(res.substring(0, 5), 2);
for(int i=0;i<GENE;i++){
safestock<<=1;
safestock +=1;

}
return safestock;
}
//将string类型的染色体后5位作为订货量、并解码为int型
public int getminStock(String res){
minstock = Integer.parseInt(res.substring(5, 10), 2);
for(int i=0;i<GENE;i++){
minstock<<=1;
minstock +=1;
}
return minstock;
}
//适应度函数
private double fitnessvalue(String str) {

double fitness=0;
if(safestock>=GaConstants.daysales*GaConstants.leadtime){
fitness=buy(safestock, getminStock(str))+kucunduo(safestock, minstock);
}
else{
fitness=buy(safestock, minstock)+kucunshao(safestock, minstock)+quehuo(safestock, minstock);
}
return fitness ;
}
public double buy(int safestock, int minstock){
double buyCount;
buyCount=(GaConstants.fixdordercost+(GaConstants.price*minstock))*Math.ceil(GaConstants.cyclesales/minstock);
return buyCount;
}
public double kucunduo(int safestock, int minstock){
double kucunCount1;
kucunCount1=(Math.ceil(minstock/2)+safestock-(GaConstants.daysales*GaConstants.leadtime))*GaConstants.cycleday*GaConstants.cunchu;
return kucunCount1;
}
public double quehuo(int safestock, int minstock){
double quehuoCount;
double stockout=GaConstants.daysales*GaConstants.leadtime-safestock;
double losscustomerprob=stockout*(0.012)+GaConstants.losscustomerprob;
quehuoCount=(stockout)*((1-losscustomerprob)*GaConstants.delayoss+losscustomerprob*GaConstants.losscustomer);
return quehuoCount;
}
public double kucunshao(int safestock, int minstock){
double kucunCount2;
kucunCount2=(Math.ceil(minstock/2)-((GaConstants.daysales*GaConstants.leadtime)-safestock)*GaConstants.cycleday*GaConstants.cunchu)/GaConstants.daysales;
return kucunCount2;
}
/* 轮盘选择: 计算群体上每个个体的适应度值; 按由个体适应度值所决定的某个规则选择将进入下一代的个体;*/
private void select() {
double evals[] = new double[ChrNum]; // 所有染色体适应值
double p[] = new double[ChrNum]; // 各染色体选择概率
double q[] = new double[ChrNum]; // 累计概率
double F = 0; // 累计适应值总和
for (int i = 0; i < ChrNum; i++) {
evals[i] = fitnessvalue(ipop[i]);
if (evals[i] < bestfitness){ // 记录下种群中的最小值,即最优解
bestfitness = evals[i];
bestgenerations = generation;
beststr = ipop[i];
}
F = F + evals[i]; // 所有染色体适应值总和
}
for (int i = 0; i < ChrNum; i++) {
p[i] = (F-(ChrNum-1)*evals[i]) / F;
if (i == 0)
q[i] = p[i];
else {
q[i] = q[i - 1] + p[i];
}
}
String[] ipopnew = new String[ChrNum];
for (int i = 0; i < ChrNum; i++) {
double r = Math.random();
for (int j = 0; j < ChrNum; j++) {
if (r < q[j]) {
ipopnew[i] = ipop[j];
}
}
}
ipop=ipopnew;
}
//交叉操作 交叉率为80%,平均为80%的染色体进行交叉
private void cross() {
String temp1, temp2;
for (int i = 0; i < ChrNum; i++) {
if (Math.random() < 0.80) {
int pos = (int)(Math.random()*GENE)+1; //pos位点前后二进制串交叉
temp1 = ipop[i].substring(0, pos) + ipop[(i + 1) % ChrNum].substring(pos);
temp2 = ipop[(i + 1) % ChrNum].substring(0, pos) + ipop[i].substring(pos);
ipop[i] = temp1;
ipop[(i + 1) / ChrNum] = temp2;
}
}
}
//基因突变操作 1%基因变异
private void mutation() {
for (int i = 0; i < 4; i++) {
int chromosomeNum = (int) (Math.random() * ChrNum );// 染色体号:在数组中,对应的数字少一位,所以不用+1
int mutationNum = (int) (Math.random() * GENE ); // 基因号
String temp;
String a; //记录变异位点变异后的编码
if (ipop[chromosomeNum].charAt(mutationNum) == '0') { //当变异位点为0时
a = "1";
} else {
a = "0";
}
//当变异位点在首、中段和尾时的突变情况
if (mutationNum == 0) {
temp = a + ipop[chromosomeNum].substring(mutationNum);
} else {
if (mutationNum != GENE-1) {
temp = ipop[chromosomeNum].substring(0, mutationNum ) + a
+ ipop[chromosomeNum].substring(mutationNum);
} else {
temp = ipop[chromosomeNum].substring(0, mutationNum) + a;
}
}
//记录下变异后的染色体
ipop[chromosomeNum] = temp;
}
}
public static void main(String args[]) {
GA Tryer = new GA();
Tryer.ipop = Tryer.initPop(); //产生初始种群
String str = "";
//迭代次数
for (int i = 0; i < 100000; i++) {
Tryer.select();
Tryer.cross();
Tryer.mutation();
Tryer.generation = i;
}
double safestock = Tryer.fitnessvalue(Tryer.beststr);
str = "最小值" + Tryer.bestfitness + '\n' + "第"
+ Tryer.bestgenerations + "个染色体:<" + Tryer.beststr + ">" + '\n'
+ "safestock=" + safestock + '\n' + "minstock=" + minstock;
System.out.println(str);
}
}

以下是一些数据的定义。

package gatest;
public class GaConstants {
public static final int biarystrsize=26;//二进制字符串长度
public static final int daysales=20;//预期每日销量
public static final int cycleday=30;//30天一个周期
public static final int cyclesales=cycleday*daysales;//周期销量
public static final int leadtime=3;//订货提前期
public static final int fixdordercost=100;//固定订货费
public static final int price=70;//单价
public static final int delayoss=0;//延迟损失费
public static final int losscustomer=100;//丢失客户损失费
public static final double losscustomerprob=0.2;//丢失客户概率
public static final double mutationrate=0.6;//
public static final int cunchu=1;//存储费
}

选择交叉变异部分的程序我没有进行修改,是网页上的资源。经过算法的选择交叉变异,迭代500次后返回最优解的染色体,然后解码为最优的safestock与minstock。
不太会将遗传算法编成Java程序,大佬们能帮我看看问题出在哪里吗?要是能帮我修改一下代码就更好了的说。
...全文
859 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

33,007

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧