我有一个优化问题,我想知道是否有一个聪明的方法来解决它。 (这可能已经被广泛研究过,我只是不知道要查找它的名称。)
我在G
生成器上有一个(编辑:免费)有限生成的阿贝尔群,n
。我还有一组P
元素G
,每个元素都标有严格正数的成本。 G
的所有生成器都显示在P
中,因此始终可以将G
的任何元素表示为P
或其反转元素的乘积。任何此类产品的成本是出现在其中的P
元素的成本之和,并考虑它们出现的频率。表示G
的标识元素的nullary产品的成本为零。
鉴于该小组的一个元素,我想找一种方法来查找按P
元素表示的最低成本产品。
将此转换为没有负二轮车的最短路径问题是直截了当的(在无限图上,但对于任何给定的元素,您只需要在标识元素附近的有限部分)。将它转换为整数线性规划问题也很简单。
可能是其中一种翻译是要走的路?或者此问题的其他结构是否导致更容易的方法呢?在我的实际问题5 <= n <= 10
和我感兴趣的元素中,从来没有任何大于+/- 20的生成器的多重性。
我在Haskell工作,因此功能方法优先于有状态方法,但有状态方法也可以。
答案 0 :(得分:1)
This is pseudocode. It isn't finished and probably won't even compile.
minCost :: element -> [generator] -> number -> Maybe [generator]
minCost _ [] _ = Nothing
minCost x _ c | (elemCost x) + c > cutoff = Nothing
minCost e _ _ = Just [] -- The factorization of the identity is the nullary product.
minCost x gs _ | elem x gs = Just [x]
minCost x gs _ | elem x ps = Nothing -- in P but not in gs.
minCost x gs c =
argmin
pathCost
[maybeCons g (minCost (x-g) [h| h <- gs, h <= g, h /= -g] (c+(elemCost g))) | g<-gs]
maybeCons :: a -> Maybe [a] -> Maybe [a]
maybeCons _ Nothing = Nothing
maybeCons x (Just xs) = Just (x:xs)
elemCost :: element -> number
pathCost :: [element] -> number
pathCost = sum . map elemCost
argmin :: (a -> n) -> [Maybe a] -> Maybe a
-- Return the item with the lowest cost, or Nothing if there isn't one.
这里有一点点的处理,但我希望逻辑应该清楚。我们必须对 P 施加任意总排序,而argmin
必须处理Nothing
的结果,表示无法从 x 生成 x P 的子集。为了便于阅读,我的伪代码没有完全正确的语法。
不包括 h &gt;来自允许的生成器的 g 是安全的,因为minCost (x-h)
分支可以找到包含 h 的任何解决方案,直到排列(和 G 是Abelian,因此任何排列的解决方案都是等效的)。排除 - g 是安全的,因为 g +( - g + a )= a ,但成本要高得多,所以没有这样的解决方案可能是最佳的。
算法需要一种修剪分支的方法,例如,当 P = {1,-1,i,-i}时,测试(2 + i){1,-1,-i },(2 + 2i){1,-1,-i},ad infinitum。这可能需要在成本超过截止时修剪搜索。使用该修复程序,它会终止,因为每次递归都会减小gs
的大小或步骤数,直到 x 减少到生成器,直到达到其中一个基本情况或成本累积到上面门槛。 (这可以通过调整到目前为止在任何并行分支上计算的最低成本来改进。)它不能重复计算,因为我们已经排除了路径中所有先前步骤的反转。
假设 e 自身生成自己,即使 P 中的要求不正确,也不需要正确性:算法永远不会在其自身的反转中添加元素,所以这可以只有在我们明确询问如何生成身份时才会出现。这是一个有效的查询:统一的复杂根源?
进一步思考,感谢建议将身份表示为无效产品。否则,我们会失败,因为我们从不检查发电机是否反转!它也有合适的类型!
有一种情况是返回类型[[generator]]
而不是Maybe [generator]
并返回所有最佳作品,将Nothing
表示为[]
。 maybeCons
的定义仅为map ((:)g)
。然而,如果存在许多同样廉价的路径,这可能会出现指数性的爆炸。
在元组中返回成本和分解,都会让我们更快地修剪任何后来的并行分支。或者我们可以使用pathCost
。
你们小组的特殊格子结构可能会提出更多修剪方法,尽管我并没有想到其他任何一般。例如,对于加法下的复数整数,我们可以很容易地从实数和虚数系数中检测出两个(最多)生成器必须是什么。在许多组中,我们可以很容易地检测到某些东西不是某个特定生成器的产品,而它是 G 的子集。这些可能是额外的防护,它们使用{{{{ 1}}。
由于成本函数,gs
类型必须与generator
或其实例相同。可以仅为生成器定义排序关系,或者它们的结构可能更简单。如果组具有对算法效率较低的自然排序,则它可能具有不同的名称。
我将留下代码不应该编译的说明,因为我很确定我写了至少一个bug。