Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm Haskell中的平衡划分_Algorithm_Haskell_Partitioning - Fatal编程技术网

Algorithm Haskell中的平衡划分

Algorithm Haskell中的平衡划分,algorithm,haskell,partitioning,Algorithm,Haskell,Partitioning,在haskell中,如何生成集合的平衡分区 假设我有一个集合{1,3,4,6,9},该集合的一个平衡分区将是s1{9,3}和s2{6,4,1},考虑到s1-s2是1,对于暴力,通过为尾部生成分区,然后将头部放在左侧列表或右侧,我们可以递归地生成所有分区: partitions :: [a] -> [([a], [a])] partitions [] = [([], [])] partitions (x : xs) = let ps = partitions xs in [(x :

在haskell中,如何生成集合的平衡分区


假设我有一个集合
{1,3,4,6,9}
,该集合的一个平衡分区将是
s1{9,3}
s2{6,4,1}
,考虑到
s1-s2
1
,对于暴力,通过为尾部生成分区,然后将头部放在左侧列表或右侧,我们可以递归地生成所有分区:

partitions :: [a] -> [([a], [a])]
partitions [] = [([], [])]
partitions (x : xs) = let ps = partitions xs in
    [(x : ys, zs) | (ys, zs) <- ps] ++ [(ys, x : zs) | (ys, zs) <- ps]
然后把它们放在一起:

balancedPartition :: (Num a, Ord a) => [a] -> ([a], [a])
balancedPartition = minimumBy (comparing unbalance) . partitions
以下是完整的模块:

module Balance where

import Data.List(minimumBy)
import Data.Ord(comparing)

partitions :: [a] -> [([a], [a])]
partitions [] = [([], [])]
partitions (x : xs) = let ps = partitions xs in
    [(x : ys, zs) | (ys, zs) <- ps] ++ [(ys, x : zs) | (ys, zs) <- ps]

unbalance :: Num a => ([a], [a]) -> a
unbalance (ys, zs) = abs (sum ys - sum zs)

balancedPartition :: (Num a, Ord a) => [a] -> ([a], [a])
balancedPartition = minimumBy (comparing unbalance) . partitions
模块平衡,其中
导入数据列表(最小值)
导入数据。Ord(比较)
分区::[a]->[([a],[a])]
分区[]=[([],[])]
分区(x:xs)=让ps=分区xs进入
[(x:ys,zs)|(ys,zs)a
不平衡量(ys,zs)=abs(总和ys-总和zs)
余额部分::(数量a,顺序a)=>[a]->([a],[a])
balancedPartition=minimumBy(比较不平衡)。分区

这里有一个更好的解决方案:

balancedPartition :: (Num a, Ord a) => [a] -> ([a], [a])
balancedPartition = snd . head . partitionsByBadness . sort
  where
    -- recursively builds a list of possible partitionings and their badness
    -- sorted by their (increasing) badness
    partitionsByBadness []     = [(0, ([], []))]
    partitionsByBadness (x:xs) = let res = partitionsByBadness xs
                                     withX = map (      (+x) *** first  (x:)) res
                                     sansX = map (subtract x *** second (x:)) res
                                 in merge withX $ normalize sansX

    -- When items are added to the second list, the difference between the sums
    -- decreases - and might become negative
    -- We take those cases and swap the lists, so that the first list has always
    -- a greater sum and the difference is always positive
    -- So that we can sort the list again (with linear complexity)
    normalize xs = let (neg, pos) = span ((<0) . fst) xs
                   in merge pos $ reverse $ map (negate *** swap) neg

-- merge two sorted lists (as known from mergesort, but
-- omits "duplicates" with same badness)
merge :: Ord k => [(k, v)] -> [(k, v)] -> [(k, v)]
merge []         zss        = zss
merge yss        []         = yss
merge yss@(y:ys) zss@(z:zs) = case comparing fst y z of
                                LT -> y : merge ys zss
                                EQ -> merge ys zss
                                GT -> z : merge yss zs
balancedPartition::(数量a,顺序a)=>[a]->([a],[a])
balancedPartition=snd.head.partitionsByBadness.sort
哪里
--递归地建立一个可能的分区及其缺点的列表
--按他们(越来越)坏的程度排序
分区比基性[]=[(0,([],[])]
partitionsByBadness(x:xs)=让res=partitionsByBadness xs
withX=贴图((+x)***第一个(x:)分辨率
sansX=贴图(减去x***秒(x:))分辨率
与X$normalize sansX合并
--当项目添加到第二个列表时,总和之间的差值
--减少-并可能变为负值
--我们处理这些案例并交换列表,以便第一个列表始终保持不变
--一个更大的和,差总是正的
--这样我们可以再次对列表进行排序(线性复杂度)
规范化xs=let(neg,pos)=span([(k,v)]->[(k,v)]->[(k,v)]
合并[]zss=zss
合并yss[]=yss
合并yss@(y:ys)zss@(z:zs)=案例比较fst y z
LT->y:合并ys zss
EQ->merge ys zss
GT->z:合并yss zs

箱子包装效果很好:

% stack ghci --package Binpack
λ: import Data.BinPack
λ: let bins numberOfBins items = let totalSize = sum items; binSize = succ (totalSize `div` (max 1 numberOfBins)) in binpack WorstFit Decreasing id (replicate numberOfBins (emptyBin binSize)) items
λ: bins 2 [1,3,4,6,9]
([(0,[3,9]),(1,[1,4,6])],[])
如果您知道您的输入将放入存储箱,您可以提取分区:

λ: map snd . fst . bins 2 $ [1,3,4,6,9]
[[3,9],[1,4,6]]

DeepRR,根据这个问题,这个问题是NP-难的。因此,寻找更好的蛮力解决方案的希望微乎其微,尽管可能有更好的蛮力解决方案。我将考虑的第一个优化是将不平衡计算与分区相结合。还可以尝试对列表进行排序并修改ORDE。r中,如果存在一个完美的分区,您可以构造分区,使其更有可能尽早找到完美的分区。@D如果有一系列解决方案比蛮力方法更好。@genisage,如果问题是真正的NP难问题,那么这些解决方案在某些情况下(可能甚至在许多情况下)只能比蛮力更好。当然,除非我不知何故错过了有人证明P=NP的消息。@dfeuer quicksort在某些情况下只比气泡排序做得更好。但由于quicksort在一般情况下是一个很大的改进,我并不觉得它更好。当你说没什么希望找到更好的东西时,OP(或未来的读者)是有机会的他们会听你的,不去寻找其他的解决方案。然后他们就不会学习动态规划、贪婪算法或差分算法,这将是令人悲哀的。虽然任何解决方案都可能有指数最坏情况,但对于给定的设置,可能有比暴力更好的技术。此外,在(可能相当常见)在这种情况下,你有一个集合的上界-就像你在一个
Int
s的集合中一样-动态规划方法是二次的。尽管它通常有一个大的常数因子。其他有趣的优化解可以在
λ: map snd . fst . bins 2 $ [1,3,4,6,9]
[[3,9],[1,4,6]]