2011-02-15 67 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 

至於實例化每一個算法,生成新的數據類型,您可以在您的庫中的幾個例子,但沒有問題實例化新的 - 這就是問題所在!