Artificial intelligence 遗传算法的交叉函数

Artificial intelligence 遗传算法的交叉函数,artificial-intelligence,genetic-algorithm,evolutionary-algorithm,Artificial Intelligence,Genetic Algorithm,Evolutionary Algorithm,我正在用java编写一个时间表生成器,使用AI方法来满足硬约束并帮助找到最佳解决方案。到目前为止,我已经实现了迭代构造(最受约束的第一个启发式)和模拟退火,我正在实现一个遗传算法 关于该问题的一些信息,以及我如何陈述: 我有一套活动、房间、特色(活动要求和房间满足)、学生和吃角子老虎机 问题在于为每个活动分配一个时段和一个房间,这样学生就不需要在一个时段内参加两个活动,所有分配的房间都满足必要的要求 我有一个放坡函数,对于每一个集合,如果赋值对软约束冲突进行放坡,那么重点就是最小化它 我实现遗传

我正在用java编写一个时间表生成器,使用AI方法来满足硬约束并帮助找到最佳解决方案。到目前为止,我已经实现了迭代构造(最受约束的第一个启发式)和模拟退火,我正在实现一个遗传算法

关于该问题的一些信息,以及我如何陈述: 我有一套活动、房间、特色(活动要求和房间满足)、学生和吃角子老虎机 问题在于为每个活动分配一个时段和一个房间,这样学生就不需要在一个时段内参加两个活动,所有分配的房间都满足必要的要求

我有一个放坡函数,对于每一个集合,如果赋值对软约束冲突进行放坡,那么重点就是最小化它

我实现遗传算法的方式是从迭代构造生成的总体开始(可以不分配事件),然后执行正常步骤:评估、选择、交叉、变异和保持最佳状态。冲洗并重复

我的问题是,我的解决方案似乎改进太少。无论我做什么,人口倾向于一种随机适应,并被困在那里。请注意,这种适应度总是不同的,但是会出现一个下限

我怀疑问题出在我的交叉函数中,下面是它背后的逻辑:

随机选择两个作业进行交叉。让我们将它们称为赋值A和赋值B。对于所有B的事件,请执行以下步骤(选择B的事件顺序为随机):

在中获取相应的事件并比较赋值。可能会发生3种不同的情况

  • 如果其中只有一个未分配,并且可以复制 另一个关于孩子的作业,选择此作业
  • 如果两个都已分配,但其中只有一个不会创建任何
    分配给子级时发生冲突,选择该子级
  • 如果两个都已分配,但均未创建冲突,则 他们是随机挑选的
在任何其他情况下,事件都不会被分配

这会创建一个孩子,其中包含一些父母的作业,一些母亲的作业,所以在我看来这是一个有效的函数。此外,它没有打破任何硬约束

至于突变,我正在使用SA的邻接函数根据子项的数量给我另一个赋值,然后替换那个子项

再说一遍。在这种设置下,初始种群为100,遗传算法运行并始终趋向于稳定在某个随机(高)适应度值。有人能告诉我我可能做错了什么吗

谢谢


编辑:格式化并清除某些内容

我认为GA只有在解决方案的一部分(向量的一部分)作为解决方案的独立部分具有重要意义时才有意义,这样交叉函数才能在两个解决方案向量之间集成解决方案的有效部分。就像DNA序列的某个部分控制或影响个体的某个特定方面一样——例如,一个基因就是眼睛的颜色。然而,在这个问题中,解向量的不同部分相互影响,使得交叉几乎毫无意义。这导致(我猜)算法相当快地收敛于单个解,不同的交叉和突变对适应度只有负面影响


我不相信GA是解决这个问题的正确工具。

如果您能提供原始问题说明,我将能够为您提供更好的解决方案。这是我目前的回答

遗传算法不是满足硬约束的最佳工具。这是一个分配问题,可以用整数规划来解决,整数规划是线性规划的特例

线性规划允许用户最小化或最大化由目标函数(分级函数)建模的某些目标。目标函数由单个决策(或决策变量)和目标函数的值或贡献的总和定义。线性程序允许决策变量为十进制值,但整数程序强制决策变量为整数值

那么,你的决定是什么?您的决定是将学生分配到插槽。这些插槽具有活动所需和房间所满足的功能

在您的情况下,您希望最大限度地增加分配给某个时段的学生人数

你也有限制。在您的情况下,学生最多只能参加一次活动

下面的网站提供了一个关于如何为整数程序建模的好教程

对于特定于java的实现,请使用下面的链接

SolverFactory factory=new SolverFactoryLpSolve();//使用lp_求解
setParameter(Solver.VERBOSE,0);
factory.setParameter(Solver.TIMEOUT,100);//将超时设置为100秒
/**
*构建一个问题:
*最大化:143x+60 Y
*受制于:

*120x+210y我会从直接测量发生了什么开始。例如,有多少作业属于你的“任何其他情况”包罗万象,因此什么也不做

此外,虽然我们无法从给出的信息中真正判断,但您的任何移动似乎都无法进行“交换”,这可能是一个问题。如果日程安排受到严格限制,那么一旦发现可行的方案,就很可能无法将一个类从房间a移动到房间B,因为房间B将被使用。您需要考虑将类从A移动到B,并将类从B移动到A/P>的方法。 有时,您还可以通过允许违反约束来改进事情。与禁止交叉违反约束不同,您可以允许交叉违反约束,但根据违反约束的“不良程度”按比例惩罚适合度

最后,您的其他操作员也可能是问题所在。如果您选择和更换
SolverFactory factory = new SolverFactoryLpSolve(); // use lp_solve
factory.setParameter(Solver.VERBOSE, 0); 
factory.setParameter(Solver.TIMEOUT, 100); // set timeout to 100 seconds

/**
* Constructing a Problem: 
* Maximize: 143x+60y 
* Subject to: 
* 120x+210y <= 15000 
* 110x+30y <= 4000 
* x+y <= 75
* 
* With x,y being integers
* 
*/
Problem problem = new Problem();

Linear linear = new Linear();
linear.add(143, "x");
linear.add(60, "y");

problem.setObjective(linear, OptType.MAX);

linear = new Linear();
linear.add(120, "x");
linear.add(210, "y");

problem.add(linear, "<=", 15000);

linear = new Linear();
linear.add(110, "x");
linear.add(30, "y");

problem.add(linear, "<=", 4000);

linear = new Linear();
linear.add(1, "x");
linear.add(1, "y");

problem.add(linear, "<=", 75);

problem.setVarType("x", Integer.class);
problem.setVarType("y", Integer.class);

Solver solver = factory.get(); // you should use this solver only once for one problem
Result result = solver.solve(problem);

System.out.println(result);

/**
* Extend the problem with x <= 16 and solve it again
*/
problem.setVarUpperBound("x", 16);

solver = factory.get();
result = solver.solve(problem);

System.out.println(result);
// Results in the following output:

// Objective: 6266.0 {y=52, x=22}
// Objective: 5828.0 {y=59, x=16}