如何高效地枚举二进制黑白树,并考虑对称性?

huangapple go评论63阅读模式
英文:

How to efficiently enumerate binary black-white trees, while accounting for symmetry?

问题

考虑以下类型的黑白二叉树:

data BW = Black BW BW | White BW BW | Leaf Nat

具有以下等价关系:

 a b c d . Black (White a b) (White c d) == White (Black a c) (Black b d)

因此,例如,Black (White 0 1) (White 2 3)White (Black 0 2) (Black 1 3) 是等价的。我对高效地枚举给定大小的所有唯一树感兴趣(树的大小仅是构造函数的计数)。蛮力方法将涉及枚举给定深度的所有树,然后过滤出等价的树。这将非常低效,有两个原因:

  1. 它会浪费地生成/考虑大量等价的树。

  2. 过滤将是二次的,因为它将需要与所有先前的树进行比较。

是否有一种高效的算法可以生成给定深度的所有 BW 树,而不生成相同的树?

英文:

Consider the following type of black-white binary trees:

data BW = Black BW BW | White BW BW | Leaf Nat

With the following equivalence relation:

∀ a b c d . Black (White a b) (White c d) == White (Black a c) (Black b d)

So, for example, Black (White 0 1) (White 2 3) and White (Black 0 2) (Black 1 3) are equivalent. I'm interested in enumerating all unique trees of given size (where the size of a tree is just the count of constructors) as efficiently as possible. A brute-force approach would involve just enumerating all trees of given depth, and filtering out equivalent trees. This would be very inefficient for two reasons:

  1. It would wastefully generate / consider a huge number of equivalent trees

  2. Filtering would be quadratic, as it would require comparing with all former trees

Is there an efficient algorithm to generate all BW trees of given depth, without generating identical trees?

答案1

得分: 6

给定任何BW树,您可以从根递归地将其转换为一个等价的树,该树不包含具有两个黑孩子的"白"节点。

此外,结果的"黑色偏向"树将与原始树的大小相同,除非它们完全相同,否则不会有两个这样的黑色偏向树等价。

因此,黑色偏向树可以用作规范形式,并且您可以枚举给定大小的黑色偏向树:

data BT = Black BBT BBT | BTLeaf Nat 
data WT = WhiteWW WT WT | WhiteWB WT BT | WhiteBW BT WT | WTLeaf Nat 
data BBT = BT BT | WT WT 
英文:

Given any BW tree, you can systematically transform it into an equivalent tree that contains no White nodes with two Black children, working recursively from the root.

Furthermore, the resulting "Black-biased" tree will be the same size as the original tree, and no two such Black-biased trees will be equivalent unless they are exactly the same.

Black-biased trees can therefore be used as a canonical form, and you can just enumerate the Black-biased trees of a given size:

data BT = Black BBT BBT | BTLeaf Nat
data WT = WhiteWW WT WT | WhiteWB WT BT | WhiteBW BT WT | WTLeaf Nat
data BBT = BT BT | WT WT

答案2

得分: 3

以下是翻译好的代码部分:

这是一个解决无数树的解决方案,应该很容易适应您的问题。

data BW = Black BW BW | White BW BW | Leaf deriving Show

notBlack :: BW -> Bool
notBlack (Black _ _ ) = False
notBlack _ = True

-- 生成BW树,其中没有白色节点有两个黑色子节点
gen :: Int -> [BW]
gen 1 = [Leaf]
gen n = do
  n1 <- [1..n-2]
  t1 <- gen n1
  let n2 = n-1-n1
  t2 <- gen n2
  Black t1 t2 : [White t1 t2 | notBlack t1 || notBlack t2]

main = mapM_ print (gen 7)

虽然在类型系统中可以强制执行约束,但结果会更加繁琐:

data BlackT = Black T T deriving Show
data NotBlackT = WW NotBlackT NotBlackT | WB NotBlackT BlackT | BW BlackT NotBlackT | Leaf deriving Show
data T = B BlackT | NB NotBlackT deriving Show

genB :: Int -> [BlackT]
genB n = [Black t1 t2 | n1 <- [1..n-2], t1 <- gen n1, t2 <- gen (n-1-n1)]

genNB :: Int -> [NotBlackT]
genNB 1 = [Leaf]
genNB n = [WW t1 t2 | n1 <- [1..n-2], t1 <- genNB n1, t2 <- genNB (n-1-n1)]
       ++ [WB t1 t2 | n1 <- [1..n-2], t1 <- genNB n1, t2 <- genB  (n-1-n1)]
       ++ [BW t1 t2 | n1 <- [1..n-2], t1 <- genB  n1, t2 <- genNB (n-1-n1)]

gen :: Int -> [T]
gen n = map B (genB n) ++ map NB (genNB n)

main = mapM_ print (gen 7)
英文:

Here's a solution for numberless trees, that should easily adapt to your problem.

data BW = Black BW BW | White BW BW | Leaf deriving Show

notBlack :: BW -&gt; Bool
notBlack (Black _ _ ) = False
notBlack _ = True

-- generate BW trees in which no White node has two Black children
gen :: Int -&gt; [BW]
gen 1 = [Leaf]
gen n = do
  n1 &lt;- [1..n-2]
  t1 &lt;- gen n1
  let n2 = n-1-n1
  t2 &lt;- gen n2
  Black t1 t2 : [White t1 t2 | notBlack t1 || notBlack t2]

main = mapM_ print (gen 7)

While it's possible to enforce the constraint in the type system, the result is rather more cumbersome:

data BlackT = Black T T deriving Show
data NotBlackT = WW NotBlackT NotBlackT | WB NotBlackT BlackT | BW BlackT NotBlackT | Leaf deriving Show
data T = B BlackT | NB NotBlackT deriving Show

genB :: Int -&gt; [BlackT]
genB n = [Black t1 t2 | n1 &lt;- [1..n-2], t1 &lt;- gen n1, t2 &lt;- gen (n-1-n1)]

genNB :: Int -&gt; [NotBlackT]
genNB 1 = [Leaf]
genNB n = [WW t1 t2 | n1 &lt;- [1..n-2], t1 &lt;- genNB n1, t2 &lt;- genNB (n-1-n1)]
       ++ [WB t1 t2 | n1 &lt;- [1..n-2], t1 &lt;- genNB n1, t2 &lt;- genB  (n-1-n1)]
       ++ [BW t1 t2 | n1 &lt;- [1..n-2], t1 &lt;- genB  n1, t2 &lt;- genNB (n-1-n1)]

gen :: Int -&gt; [T]
gen n = map B (genB n) ++ map NB (genNB n)

main = mapM_ print (gen 7)

huangapple
  • 本文由 发表于 2023年6月16日 07:48:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76486142.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定