获取具有最高属性的列表的n个元素

时间:2015-06-30 15:15:25

标签: haskell genetic-algorithm

我是Haskell的新手,并试图实现一些遗传算法。 目前,我没有选择个人列表中的n个最佳元素(每个人都是自己的列表)。 个人创建如下:

ind1 :: [Int]
ind1 = [1, 1, 1, 1, 1, 1, 1]
ind2 :: [Int]
ind2 = [0, 0, 0, 0, 0, 0, 0]

适当的人口包括这些人的名单:

pop :: [[Int]]
pop = [ind1, ind2]

我想要达到的目标是获得群体中最好的n个人,其中“最佳”由其元素的总和决定,例如,

> sum ind1
7
> sum ind2
0

我开始创建一个用于创建具有个性及其质量的元组的函数:

f x = [(ind, sum ind) | ind <- x]

所以至少我得到了这样的东西:

[([1, 1, 1, 1, 1, 1, 1], 7), ([0, 0, 0, 0, 0, 0, 0], 0)]

如何从此处获得预期结果?我甚至无法获得“snd == max”中元组的“fst”。 我从不同主题中看到的递归方法开始,但遗憾的是没有合理的结果。 任何建议,可能也在哪里阅读? 谢谢!

2 个答案:

答案 0 :(得分:4)

使用sortByon

> take 2 $ sortBy (flip compare `on` sum) [[1,2],[0,4],[1,1]]
[[0,4],[1,2]]

答案 1 :(得分:4)

此处的最佳选择是使用sortBy中的Data.List

sortBy :: (a -> a -> Ordering) -> [a] -> [a]

sortBy函数是高阶函数,因此它将函数作为其参数之一。它需要的功能是获取两个元素并返回Ordering值(LTEQGT)的函数。您可以编写自己的自定义比较函数,但Data.Ord模块有comparing,它有助于编写这些比较函数:

comparing :: Ord b => (a -> b) -> (a -> a -> Ordering)

希望你能看到comparing如何与sortBy配对,你传递一个函数将你的类型转换为已知的可比类型,然后你有一个正确类型的函数传递给{ {1}}。所以在实践中你可以做到

sortBy

import Data.List (sortBy) import Data.Ord (comparing) -- Some types to make things more readable type Individual = [Int] type Fitness = Int -- Here's our fitness function (change as needed) fitness :: Individual -> Fitness fitness = sum -- Redefining so it can be used with `map` f :: Individual -> (Individual, Fitness) f ind = (ind, fitness ind) -- If you do want to see the fitness of the top n individuals solution1 :: Int -> [Individual] -> [(Individual, Fitness)] solution1 n inds = take n $ sortBy (flip $ comparing snd) $ map f inds -- If you just want the top n individuals solution2 :: Int -> [Individual] -> [Individual] solution2 n inds = take n $ sortBy (flip $ comparing fitness) inds 参数中的flip强制排序降序而不是默认升序,因此从sortBy返回的第一个n值将是{ {1}}具有最高适应度的值,按降序排列。如果您想尝试不同的健身功能,那么您可以执行类似

的操作
sortBy

然后你有

n

但你也可以

fittestBy :: (Individual -> Fitness) -> Int -> [Individual] -> [Individual]
fittestBy fit n = take n . sortBy (flip $ comparing fit)

如果你想将你的适应度函数改为产品而不是总和。