2011-02-15 124 views
16

我是新来的Haskell编程的世界,我正在削减我的牙齿在一个简单的遗传算法找到旅行推销员问题的好办法。我代表的解决方案,对整数排列,所以我有这种类型的同义词哈斯克尔:抽象遗传算法

type Genome = [Int] 

的算法本身是一组这对解决方案进行操作的功能:

mutation :: Genome -> Genome 
selectParents :: [Genome] -> [Genome] -> [Genome] 
crossover :: Genome -> Genome -> (Genome, Genome) 
selectSurvivors :: [Genome] -> [Genome] -> [Genome] 

我不知道怎么样我的许多代码与我的问题有关,所以请询问是否需要更多细节。有一点值得一提的是,上面的类型签名实际上是简化的,实际上我使用State monad来承载StdGen,所有这些函数实际上都返回有状态的计算。

有几件事我想用这个做,但不能让我头脑发热。我希望能够为解决方案选择不同的表示形式,在我看来,这将是一个使用类型类的自然地方,因此Genome将是类型类,而[Int]是此Genome的特定实例。

现在,我希望能够尝试实现,并且希望能够在其他项目中使用代码。使用这样的类型类将需要我创建的每个新算法都需要我创建Genome的另一个实例,这是创建一个库的好方法吗?

一个额外的问题,只是一个困扰着我的东西,有什么办法可以创建类似于函数的类型同义词的东西,所以如果我正在编写一个函数作为参数,我可以写同义词而不是而不是函数的整个类型签名,所以像下面这样的东西可以工作。

type someFunc = [Int] -> [Int] -> Int 
someOtherFunc :: someFunc -> [Int] -> Int 

权,希望这就是问题的清醒足够的解释,觉得我已经错过了真正的答案很明显,但它并没有在我跳了出来。欢呼声

+0

哪些功能会的情况下, Genome需要定义? `突变',`selectParents`等?还是有一个更小(更简单)的函数集,你可以用这些函数来定义这些函数? – rampion 2011-02-15 22:35:15

+0

我可能是错的,但我认为这些功能尽可能简单。也许我只是试图让它比一般的更普遍。 – 2011-02-15 22:41:49

回答

7

不幸的是,理想的解决方案通常取决于您的问题领域。 This blog post讨论类型类方法和按位方法。我个人认为如果你想要灵活性,混合方法是最好的。如果有一个很好的按位映射,你可以定义它,并且实现是从那个派生的,否则你可以手动实现交叉和变异。

ja的方法实际上不起作用。你的一些基因的功能将需要随机输入,您可以通过在状态单子用随机数生成器运行得like this thread

class Genome a where 
    fitness :: a -> Int 
    breed :: (RandomGen g, MonadState g m) => a -> a -> m a 
    mutate :: (RandomGen g, MonadState g m) => a -> m a 

然后你有实现对套基因组的工作,无论常用功能。

selectParents :: (Genome a, RandomGen g, MonadState g m) => [a] -> m [a] 
selectSurvivors :: (Genome a, RandomGen g, MonadState g m) => [a] -> m [a] 

如果你有一个好一点的映射,你可以只定义在BitArrays固定功能(请注意,每个将不得不采取适应度函数作为参数)

breed :: (RandomGen g, MonadState g m) => BitArray -> BitArray -> m BitArray 
mutate :: (RandomGen g, MonadState g m) => BitArray -> m BitArray 
selectParents :: (RandomGen g, MonadState g m) => (BitArray -> Int) -> [BitArray] -> m [BitArray] 
selectSurvivors :: (RandomGen g, MonadState g m) => (BitArray -> Int) -> [BitArray] -> m [BitArray] 
2

是的,使用类型类来表示基因组是一个好方法。事情是这样的:

 
class Genome a where 
    mutation :: a -> a 
    selectParents :: [a] -> [a] -> [a] 
    crossover :: a -> a -> (a, a) 
    selectSurvivors :: [a] -> [a] -> [a] 
instance Genome [a] where 
    mutation l = l 
    selectParents l1 l2 = l1 
    crossover g1 g2 = (g1,g2) 
    selectSurvivors l1 l2 = l1 
data Tree a = Leaf a | Branch [Tree a] 
instance Genome (Tree a) where 
    mutation t = t 
    selectParents l1 l2 = l1 
    crossover g1 g2 = (g1,g2) 
    selectSurvivors l1 l2 = l1 

至于实例化每一个算法,生成新的数据类型,您可以在您的库中的几个例子,但没有问题实例化新的 - 这就是问题所在!