约束单目标优化

时间:2012-11-01 18:46:35

标签: optimization go

简介

我需要分割一个填充了某种类型的数组(让我们拿水桶),设置两个值(在这种情况下是重量和体积),同时保持重量总和之间的差异最小(首选)和总量小于1000(必需)之间的差异。这不需要是一个完整的遗传算法或类似的东西,但它应该比我现在拥有的更好......

当前实施

由于不知道如何更好地做到这一点,我开始将数组拆分为两个相同长度的数组(数组可以填充不均匀数量的项目),用一个具有两个值的项目替换可能的空白点是的。双方不需要有相同数量的物品,我只是不知道如何处理它。

分配后,我试图像这样优化它们:

func (main *Main) Optimize() {
    for {
        difference := main.Difference(WEIGHT)

        for i := 0; i < len(main.left); i++ {
            for j := 0; j < len(main.right); j++ {
                if main.DifferenceAfter(i, j, WEIGHT) < main.Difference(WEIGHT) {
                    main.left[i], main.right[j] = main.right[j], main.left[i]
                }
            }
        }

        if difference == main.Difference(WEIGHT) {
            break
        }
    }

    for main.Difference(CAPACITY) > 1000 {
        leftIndex := 0
        rightIndex := 0
        liters := 0
        weight := 100

        for i := 0; i < len(main.left); i++ {
            for j := 0; j < len(main.right); j++ {
                if main.DifferenceAfter(i, j, CAPACITY) < main.Difference(CAPACITY) {
                    newLiters := main.Difference(CAPACITY) - main.DifferenceAfter(i, j, CAPACITY)
                    newWeight := main.Difference(WEIGHT) - main.DifferenceAfter(i, j, WEIGHT)

                    if newLiters > liters && newWeight <= weight || newLiters == liters && newWeight < weight {
                        leftIndex = i
                        rightIndex = j
                        liters = newLiters
                        weight = newWeight
                    }
                }
            }
        }

        main.left[leftIndex], main.right[rightIndex] = main.right[rightIndex], main.left[leftIndex]
    }
}

功能:

main.Difference(const)计算双方之间的绝对差值,作为参数的常量决定了计算差值的值

main.DifferenceAfter(i,j,const)模拟两个桶之间的交换,我是左边的桶,j是右边的桶,然后计算得到的绝对差值,常量再次确定要检查的值

说明:

基本上,这是从优化权重开始的,这是第一个for-loop的作用。在每次迭代时,它会尝试可以切换的每个可能的桶组合,如果之后的差异小于当前差异(导致更好的分布),则会切换它们。如果重量不再变化,它会突然出现for循环。虽然不完美,但这种方法效果很好,我认为这是我可以接受的。

然后它应该根据音量来优化分布,所以总差异小于1000.在这里我试着更加小心,并在切换之前在运行中搜索最佳组合。因此,它搜索铲斗开关导致最大容量变化,并且还应该在此之间进行权衡,尽管我看到第一个铲斗组合尝试的缺陷将设置升和重量变量,从而产生下一个可能的组合减少了很多。

结论

我想我需要在这里加入更多的数学,但我老实说是在这里,不知道如何继续这里,所以我想得到你的帮助,基本上这可以帮助我在这里是欢迎。

2 个答案:

答案 0 :(得分:2)

如前所述,您的问题实际上是约束优化问题,并且会限制您的卷差异。

在数学上,这将最小化 将是:

min weights . x
    subject to  volumes . x < 1000.0
                for all i, x[i] = +1 or -1

其中a . b是矢量点积。解决此问题后,x = +1对应于您的第一个数组的所有索引,x = -1对应于您的第二个数组的所有索引。

不幸的是,0-1 integer programming已知为NP-hard。解决它的最简单方法是对空间进行详尽的强力探索,但需要测试所有2^n个可能的向量x(其中n是原始{{1}的长度}}和weights向量),它们很快就会失控。关于这个主题有很多文献,有更高效的算法,但它们通常高度特定于一组特定的问题和/或约束。你可以谷歌“线性整数编程”来看看在这个主题上做了什么。

我认为最简单的方法可能是执行基于启发式的强力搜索,在这种情况下,当你的搜索树超出你的音量约束时,你可以提早修剪它,并保持接近你的约束(作为一般规则,线性优化问题的解决方案位于可行空间的边缘。)

以下是一些您可能希望阅读此类优化的文章:

如果您不熟悉优化文章或数学,wikipedia articles提供了很好的介绍,但大多数关于此主题的文章都会快速显示您可以立即调整的一些(伪)代码。

如果你的volumes很大,我认为在某些时候你必须在你的解决方案的优化程度和计算速度之间做出权衡。您的解决方案可能不是最理想的,但它比穷举搜索快得多。可能会有更好的权衡,具体取决于问题的确切配置。

答案 1 :(得分:1)

在您的情况下,权重差异似乎是客观的,而体积差异只是一个约束,这意味着您正在寻找优化的解决方案< em>权重差异属性(尽可能小),并满足 属性<(em )属性的条件(总<1000)。在这种情况下,这是一个单一的客观约束优化问题。

然而,如果您对多目标优化感兴趣,也许您想看看Pareto Frontier的概念:http://en.wikipedia.org/wiki/Pareto_efficiency。保持多个优秀解决方案具有不同目标的优势,即不失去多样性,这是有益的。