蚂蚁群算法表现异常

8
我开发了一种aco算法。我认为它没有正常工作...很难解释,但我会试着说明。
问题在于信息素水平在浮动。我认为,在最佳路径上的信息素水平必须越来越高,但在我的程序中并非如此。
“最优路径”是通过查找起始顶点和目标顶点之间边缘上的最大信息素水平来构建的路径。
例如:
1 5 3
4 5 10
0 0 0

最优路径将是1 -> 2 -> 3

权重矩阵:

 0 3 10
 0 0 3
 0 0 0

最佳路径为:1 -> 2 -> 3 (长度:6) 另一条路径(不是最优):1 -> 3 (长度:10)

10只蚂蚁后的信息素水平:

0 5 1 
0 0 3
0 0 0

最佳路径:1 -> 2 -> 3


20只蚂蚁之后的信息素水平(增加了10只):

0 1 5 
0 0 1
0 0 0

最优路径:1 -> 3


30只蚂蚁后信息素水平:
0 4 1 
0 0 3
0 0 0

最优路径:1 -> 2 -> 3


30只蚂蚁后的信息素水平:
0 4 6 
0 0 2
0 0 0

最佳路径:1 -> 3

这只是一个例子,但它代表了我的程序中蚂蚁素矩阵的样子。


我程序的伪代码:
init alpha, beta and other coef's

while antCount do
{
    current = start
    // + init visited array for current ant, some others variables

    while vertexAvailable(current) do
    {
        find probabilities to go to 1
            or another vertex

        generate random number, choose next
            vertex depending on it,
            defining nextVertex

        current = nextVertex

        if current == stop then
        {
            get path length

            update pheromones on path of current
                ant depending on path length
        }
    }

    evaporation of pheromones

    antCount = antCount - 1
}

所以,为什么我的程序中信息素水平会浮动?为什么最佳路径没有最高的信息素水平?我知道这个算法有概率因素,但它必须显示正确的结果。
我在我的程序里做了什么?这里你可以找到我的程序完整的主循环源代码。
1) 主循环是一个循环,一直运行直到当前迭代中没有可用的蚂蚁为止。
1.1) 在这个循环中,我有另一个循环(内部循环),它将一直执行,直到当前蚂蚁有要前往的顶点(这些顶点不能被当前蚂蚁访问过)。
在内部循环中,我做了以下操作:
1.1.1) 计算下面方程式的分母

main formula

这个公式将计算选择ij路径(i是当前节点,j是下一个节点)的概率。

代码:

var denom = 0;

for(col in graph[currentVertex])
{
    // этот цикл формирует знаменатель формулы

    var weight = graph[currentVertex][col];

    if(weight != 0 && visited[col] != true)
    {
        var tau = pheromone[currentVertex][col];

        denom = denom + getAttractiveness(tau, weight);
    }
}

1.1.2) 计算上述公式的分子并获取当前可用顶点选择概率

此外,我将所有概率添加到一个区间中,以帮助我决定选择哪个顶点。

代码:

for(col in graph[currentVertex])
{
    var weight = graph[currentVertex][col];

    if(weight != 0 && visited[col] != true)
    {
        var tau = pheromone[currentVertex][col];

        var nom = getAttractiveness(tau, weight);

        var probability = nom/denom;

        intervals[col] = probability+intervals.last;

        intervals.last = probability+intervals.last;
    }
}

1.1.3) 根据代码的前一部分定义的intervals数组,从0到1创建随机数并选择顶点 代码:
var rand = Math.random();
var nextVertex = 0;

for(vertex in intervals)
{
    if (rand < intervals[vertex])
    {
        nextVertex = parseInt(vertex,10);
        break;
    }
}

1.1.4) 一些指令、设置助手(路径助手、已访问助手)等

1.1.5) 下一步,我正在检查找到的顶点是否为目标顶点

如果是(这意味着蚂蚁发现了目标顶点),我会执行以下操作:

1.1.5.1) 获取当前蚂蚁路径长度

代码:

var length = 0;

while(source = pathCopy.pop())
{
    console.log("dest: " + dest + " source: " + source);
    length = length + graph[source][dest];

    dest = source;
}

1.1.5.2) 更新此路径上的信息素水平

代码:

var deltaTau = 5/length;
var dest = path.pop();
var source;

while(source = path.pop())
{
    var oldPheromone = pheromone[source][dest];

    // обновление феромона формула 3
    var newPheromone = oldPheromone+deltaTau;

    // console.log('pheromone levels: old =
    //      '+oldPheromone+' new = ' + newPheromone);

    pheromone[source][dest] = newPheromone;

    dest = source;
}

1.2) 在主循环结束时,我会对信息素水平进行蒸发处理:

代码:

for(row in pheromone)
{
    for(col in pheromone[row])
    {
        var oldPheromone = pheromone[row][col];

        // обновление феромона формула 3
        var newPheromone = (1-ktau)*oldPheromone;

        pheromone[row][col] = newPheromone;
    }
}

8
你显然知道自己在做什么,但是在这个问题中,你直接跳进了详细问题的中心,我怀疑很少有人会花时间了解你在做什么。你可能会发现这里的提示 很有用,尤其是“示例代码和数据”部分。我敢打赌,如果你将问题简化为最小可重现的示例,你就能够自己解决它... - AakashM
1
@AakashM 谢谢你的回答!我已经多次阅读了有关如何撰写好问题的文章。我明白你所说的,这就是为什么我在问是否有人知道可能导致我的问题的因素。我明白,没有人会花费超过5分钟来回答我的问题 :) 但对我来说也一样:我正在浪费时间审查这段代码,而它看起来像是工作正常的。至于示例数据...这取决于情况。我不确定代码的哪个部分出错了,所以请给出aco的所有代码(我尝试删除了初始化等)。 - Sharikov Vladislav
@AakashM 首先,我希望大家注意到,这是信息素矩阵的截屏。 - Sharikov Vladislav
@KhaledAKhunaifer 等等,我不是在问这个 :) 我是在问为什么最佳矩阵的信息素没有最大化 :) - Sharikov Vladislav
1
这听起来可能是一个非常有趣的问题,只要我能够理解它。我的理解是,您有一个蚂蚁群体优化器(针对某个问题,我不确定是什么;看起来像是小图上的最短路径,但我可能错了),它没有按照您的预期工作,您已经向我们倾倒了一堆代码片段,并且您怀疑错误可能在其中之一。很抱歉,除非您能将代码转换为更接近MCVE的东西,否则我认为您在这里不会得到太多有用的帮助。 - Ilmari Karonen
显示剩余16条评论
1个回答

4
在选择路径时,您的代码总是选择低于随机阈值的第一个相邻顶点。我不确定这样如何表示蚂蚁朝着具有更多信息素的顶点前进。在信息素浓度相对较低(低于0.5)的区域中,这种方法会在一定程度上起作用。然而,在信息素浓度高(接近或高于1)的区域中,因为您的随机()数字介于0和1之间,您将回到始终选择第一个可用顶点的情况。这可能就是您无法收敛的原因。

谢谢你的回答。我理解得对吗,我们只是建立了蚂蚁群模型,而不是真正的蚂蚁群? :) 我正在做这个:如果蚂蚁找到目标顶点,就会在路径上更新信息素,该路径是蚂蚁到达此路径的路径(您可以在这里看到),如果蚂蚁没有找到目标顶点,则不会增加蚂蚁路径上的信息素水平。每次蚂蚁尝试寻找目标顶点后,信息素都会蒸发。通过这种方式,我实现了这样一个事实,即如果使用这条路径找到食物,信息素水平会增加。我理解得对吗? - Sharikov Vladislav
信息素会在每只蚂蚁尝试寻找顶点后蒸发。代码在这里。你是指这个吗? - Sharikov Vladislav
我没有看到信息素在路径上是如何增加的。我会随之更新我的答案。我认为你需要更好地解释一下下一个顶点选择的工作方式以及概率是如何计算的。 - zeFrenchy
如果我这样解释:“接下来我要做什么——链接到代码的git?”那就可以了吗?还是我应该在这里复制它? - Sharikov Vladislav
@Sharikov...现在有点忙,等我有时间再回来。 - zeFrenchy
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接