[英]Arbitrary instance for generating unbiased graphs for quickcheck
module Main where
import Test.QuickCheck
import Data.Set as Set
data Edge v = Edge {source :: v, target :: v}
deriving (Show,Eq,Ord)
data Graph v = Graph {nodes :: Set v, edges :: Set (Edge v)}
deriving Show
instance Arbitrary v => Int-> Arbitrary (Edge v) where
arbitrary = sized aux
where aux n = do s <- arbitrary
t <- arbitrary `suchThat` (/= s)
return $ Edge {source = s, target = t}
instance (Ord v, Arbitrary v) => Arbitrary (Graph v) where
arbitrary = aux `suchThat` isValid
where aux = do ns <- arbitrary
es <- arbitrary
return $ Graph {nodes = fromList ns, edges = fromList es}
實例的當前定義正在生成幾乎沒有邊緣的圖,如何更改它以減少偏見並滿足這兩個功能? :
-| 函數“ isDAG”測試圖是否為非循環圖。
isDAG :: Ord v => Graph v -> Bool
isDAG g = isValid g && all nocycle (nodes g)
where nocycle v = all (\a -> v `notMember` reachable g a) $ Set.map target (adj g v)
-| 函數'isForest'測試一個有效的DAG是否是一個小植物(一組樹),換句話說,-如果每個節點(頂點)最多具有一個相鄰節點。
isForest :: Ord v => DAG v -> Bool
isForest g = isDAG g && all (\v -> length (adj g v) <= 1) (nodes g)
首先,您必須弄清楚如何構造滿足這些屬性的圖。
DAG:如果您的節點接受某種排序,並且對於每個邊(u,v)
您的u < v
則該圖是非循環的。 此排序完全可以是任何排序,因此您可以在圖形中的節點集上制造任意排序。
森林:如果圖形沒有邊,則可以輕松滿足此屬性。 最初,您可以添加源為任何節點的任何邊。 如果添加邊緣,請從其余可用節點中刪除該邊緣的源。
我想最大的問題是如何將其轉換為代碼。 QuickCheck提供了許多組合器,尤其是。 用於從列表中進行選擇,有或沒有替代品,各種尺寸等。
instance (Ord v, Arbitrary v) => Arbitrary (Graph v) where
arbitrary = do
ns <- Set.fromList <$> liftA2 (++) (replicateM 10 arbitrary) arbitrary
首先,您生成一組隨機節點。
let ns' = map reverse $ drop 2 $ inits $ Set.toList ns
對於每個節點,這將計算(大於)該節點“(非空)”的節點集。 在這里,“更大”僅表示根據列表中元素順序產生的任意順序。 這將為您提供DAG屬性。
es <- sublistOf ns' >>=
mapM (\(f:ts) -> Edge f <$> elements ts)
然后,您將獲得該列表的一個隨機子列表(這將為您提供林屬性),並為該隨機子列表中的每個元素創建一條從該集合中“最大”節點指向“較小”節點的邊。
return $ Graph ns (Set.fromList es)
這樣就完成了! 像這樣測試:
main = quickCheck $ forAll arbitrary (liftA2 (&&) (isDAG :: Graph Integer -> Bool) isForest)
構造圖的一種自然方法是歸納法,一次添加一個節點。 然后,確保所需的屬性成立變得非常容易:
adj
函數,因此不清楚“森林”是否意味着從一個節點到一個節點最多有一條邊。) 因此,生成此類圖的過程將如下所示:
此處的主要因素是確定是否添加邊。 通過調整此參數,您可以在森林中獲得更多或更少的樹木。 一種選擇是為此使用frequency
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.