【问题标题】:Genetic Algorithm to Draw a Graph? Position assignment problem绘制图形的遗传算法?职位分配问题
【发布时间】:2011-10-03 14:13:26
【问题描述】:

我手头有一个分配问题,我想知道应用本地搜索技术来达到理想的解决方案有多合适(搜索空间非常大)。

我有一个有向图(流程图),我想在二维平面上以一种非常清晰、易于理解且易于人眼阅读的方式进行可视化。所以;我将为每个顶点分配 (x,y) 位置。我正在考虑使用模拟退火、遗传算法或您可以建议的任何此类方法来解决这个问题

输入: 图 G = (V,E)
输出: 一组作业,{(xi, yi) for each vi in V}。换句话说,每个顶点将被分配一个位置 (x, y),其中坐标都是整数并且 >= 0。

这些是我将用来判断解决方案的标准(我欢迎任何建议):

  • 相交边的数量应该最少,
  • 所有边沿一个方向流动(即从左到右),
  • 高角度分辨率(两条边形成的最小角度 事件在同一个顶点),
  • 小面积 - 最不重要。

此外;我有一个手工制作的初始配置(将位置分配给顶点)。它非常混乱,这就是我尝试自动化该过程的原因。

我的问题是,

  • 使用本地搜索技术有多明智?可能性有多大 它会产生预期的结果吗?

  • 我应该从什么开始?模拟退火,遗传算法 还是别的什么?

  • 我应该在开头随机播种还是使用初始 配置开始?

  • 或者,如果您已经知道类似的实现/伪代码/事物,请指点我。

任何帮助将不胜感激。谢谢。

编辑:它不需要很快 - 不是实时的。此外; |V|=~200,每个顶点平均有大约 1.5 个出边。该图没有断开的组件。它确实涉及循环。

【问题讨论】:

  • 主要任务是画图吗?已经有大量关于绘图的研究,您可能应该先阅读一下……如果这不是您的主要任务,那么只需使用一些现有的库来完成绘图部分。
  • 您是否找到了一种解决方案,如何在基因中存储坐标和边缘以创建不那么复杂的遗传算法?我的意思是您决定将其存储为具有 1,0 值的字符串,或者您找到了如何存储坐标和边的解决方案?

标签: algorithm graph genetic-algorithm


【解决方案1】:

我建议查看 http://www.graphviz.org/Theory.php,因为 graphviz 是领先的开源图形可视化工具之一。

根据分配的内容,也许完全使用 graphviz 进行可视化是有意义的。

【讨论】:

    【解决方案2】:

    This paper 很好地概述了各种方法。 Roberto Tomassia's book 也是不错的选择。

    【讨论】:

    • 感谢 MPG。这篇论文真的很好,但它并没有给我指出一个可靠的算法。这只是一个概述。此外;这本书的评论说它大多充满了理论,但没有实际的实现。
    【解决方案3】:

    http://oreilly.com/catalog/9780596529321 - 在这本书中,您可能会发现用于二维图形精细可视化的遗传算法实现。

    在类似的情况下,我更喜欢使用遗传算法。您也可以从随机初始化的人口开始 - 根据我在几次迭代后的经验,您会发现非常好的(但也不是最好的)解决方案。

    另外,使用 java 你可以并行这个算法(孤岛策略)——这是相当有效的改进。

    另外我想建议你差分进化算法。根据我的经验 - 它比遗传优化更快地找到解决方案。

    【讨论】:

    • 在那本书中我没有找到任何用于二维图形精细可视化的遗传算法实现
    【解决方案4】:
    function String generateGenetic()
    String genetic = "";
    for each vertex in your graph
        Generate random x and y;
        String xy = Transform x and y to a fixed-length bit string;
        genetic + = xy;
    endfor
    return genetic;
    

    编写一个函数 double evaluate(Stringgenetic),它会给你一个统计水平。 (可能基于相交的边数和边方向。

    你的程序:

    int population = 1000;
    int max_iterations = 1000;
    double satisfaction = 0;
    String[] genetics = new String[population]; //this is ur population;
    while((satisfaction<0.8)&&(count<max_iterations)){
        for (int i=0;i<population;i++){
            if(evaluate(genetics[i])>satisfaction)
                satisfaction = evaluate(genetics[i]);
            else
                manipulate(genetics[i]);
        }
    }
    

    函数操作可以翻转字符串的一些位或多个位或编码顶点的 x 和 y 的部分,或者可能生成完全新的遗传字符串或尝试解决其中的问题(指向边缘)。

    【讨论】:

    • 在很多问题中,从数字向量到位向量的转换是不必要的。但如果你想这样做,我建议使用格雷码
    【解决方案5】:

    要回答您的第一个问题,我必须说这取决于。这取决于许多不同的因素,例如:

    • 需要多快(是否需要实时完成?)
    • 有多少个顶点
    • 与顶点数相比有多少边(即它是密集图还是稀疏图?)

    如果需要实时完成,那么本地搜索技术将不是最好的,因为它们可能需要一段时间才能获得良好的结果。如果图形的大小很小,它们只会足够快。如果一开始就很小,你不应该一开始就使用本地搜索。

    正如您所描述的,已经有用于渲染图形的算法。问题是,在什么时候问题变得太大而无法有效?我不知道这个问题的答案,但我相信你可以做一些研究来找出答案。

    现在继续您关于实施本地搜索的问题。

    根据我的个人经验,模拟退火比遗传算法更容易实现。但是我认为这个问题很好地转化为两种设置。不过我会从 SA 开始。

    对于模拟退火,您将从随机配置开始。然后,您可以通过将一个或多个顶点移动一些随机距离来随机扰动配置。我相信你可以完成算法的细节。

    对于遗传算法方法,您还可以从随机种群开始(每个图的顶点都有随机坐标)。突变可以像我描述的 SA 算法中的扰动一样。重组可以简单地从父母那里获取随机顶点并在子图中使用它们。再次,我相信你可以填补空白。

    总结:仅当您的图表足够大以保证它并且您不需要超快速(比如少于几秒钟)完成时,才使用本地搜索。否则使用不同的算法。

    编辑:根据您的图形参数,我认为您可以使用最容易编码的算法。在 V=200 的情况下,即使是 O(V^3) 算法也足够了。我个人觉得模拟退火是最简单也是最好的路线。

    【讨论】:

    • 感谢 tkuzzy 的回答。我已经通过编辑原始帖子回答了您的问题。它不需要很快 - 不是实时的。此外; |V|=~200,每个顶点平均有大约 1.5 个出边。我将研究其他现有方法,看看它们需要多长时间......
    • 相应地编辑了我的答案。
    猜你喜欢
    • 2019-02-23
    • 2016-06-23
    • 2019-08-07
    • 1970-01-01
    • 2017-12-16
    • 2019-12-09
    • 2016-08-23
    • 2021-12-26
    相关资源
    最近更新 更多