简体   繁体   English

无限深度和无限宽度玫瑰树的懒惰折叠到其边缘路径

[英]Lazy Folding of Infinite Depth & Infinite Breadth Rose Tree to its Edge Paths

This question haskell fold rose tree paths delved into the code for folding a rose tree to its paths. 这个问题包括将玫瑰树折叠成路径的代码折叠玫瑰树路径。 I was experimenting with infinite rose trees, and I found that the provided solution was not lazy enough to work on infinite rose trees with infinity in both depth and breadth. 我正在尝试无限的玫瑰树,我发现所提供的解决方案并不足以在宽度和宽度上无限的玫瑰树上工作。

Consider a rose tree like: 考虑像玫瑰树一样:

data Rose a = Rose a [Rose a] deriving (Show, Functor)

Here's a finite rose tree: 这是一棵有限的玫瑰树:

finiteTree = Rose "root" [ 
    Rose "a" [ 
        Rose "d" [], 
        Rose "e" []
    ], 
    Rose "b" [ 
        Rose "f" [] 
    ], 
    Rose "c" [] 
]

The output of the edge path list should be: 边路径列表的输出应为:

[["root","a","d"],["root","a","e"],["root","b","f"],["root","c"]]

Here is an infinite Rose tree in both dimensions: 这是两个维度中的无限玫瑰树:

infiniteRoseTree :: [[a]] -> Rose a
infiniteRoseTree ((root:_):breadthGens) = Rose root (infiniteRoseForest breadthGens)

infiniteRoseForest :: [[a]] -> [Rose a]
infiniteRoseForest (breadthGen:breadthGens) = [ Rose x (infiniteRoseForest breadthGens) | x <- breadthGen ]

infiniteTree = infiniteRoseTree depthIndexedBreadths where
    depthIndexedBreadths = iterate (map (+1)) [0..]

The tree looks like this (it's just an excerpt, there's infinite depth and infinite breadth): 树看起来像这样(它只是一个摘录,有无限的深度和无限的宽度):

      0
      |
      |
    [1,2..]
    /  \
   /    \
  /      \
[2,3..]  [2,3..]

The paths would look like: 路径看起来像:

[[0,1,2..]..[0,2,2..]..] 

Here was my latest attempt (doing it on GHCi causes an infinite loop, no streaming output): 这是我最近的尝试(在GHCi上执行此操作会导致无限循环,没有流输出):

rosePathsLazy (Rose x []) = [[x]]
rosePathsLazy (Rose x children) = 
    concat [ map (x:) (rosePathsLazy child) | child <- children ]

rosePathsLazy infiniteTree

The provided solution in the other answer also did not produce any output: 另一个答案中提供的解决方案也没有产生任何输出:

foldRose f z (Rose x []) = [f x z]
foldRose f z (Rose x ns) = [f x y | n <- ns, y <- foldRose f z n]

foldRose (:) [] infiniteTree

Both of the above work for the finite rose tree. 上述两种工作都适用于有限玫瑰树。

I tried a number of variations, but I can't figure out to make the edge folding operation lazy for infinite 2-dimensional rose tree. 我尝试了很多变化,但我无法弄清楚边缘折叠操作是否对于无限的二维玫瑰树来说是懒惰的。 I feel like it has something to do with infinite amounts of concat . 我觉得它与无限量的concat

Since the output is a 2 dimensional list. 由于输出是二维列表。 I can run a 2 dimensional take and project with a depth-limit or a breadth-limit or both at the same time! 我可以同时运行具有深度限制或宽度限制或两者的二维take和项目!

Any help is appreciated! 任何帮助表示赞赏!


After reviewing the answers here and thinking about it a bit more. 在回顾了这里的答案并思考了一下之后。 I came to the realisation that this is unfoldable, because the resulting list is uncountably infinite. 我又意识到,这是展开的,因为产生的名单是不可数无穷。 This is because an infinite depth & breadth rose tree is not a 2 dimensional data structure, but an infinite dimensional data structure. 这是因为无限深度和宽度玫瑰树不是二维数据结构,而是无限维数据结构。 Each depth level confers an extra dimension. 每个深度级别都赋予额外的维度。 In other words, it is somewhat equivalent to an infinite dimensional matrix, imagine a matrix where each field is another matrix.. ad-infinitum. 换句话说,它有点等同于无限维矩阵,想象一个矩阵,其中每个场是另一个矩阵.ad-infinitum。 The cardinality of the infinite matrix is infinity ^ infinity , which has been proven (I think) to be uncountably infinite. 无限矩阵的基数是infinity ^ infinity ,已被证明(我认为)无穷无尽。 This means any infinite dimensional data structure is not really computable in a useful sense. 这意味着任何无限维数据结构在有用的意义上都不是真正可计算的。

To apply this to the rose tree, if we have infinite depth, then the paths never enumerate past the far left of the rose tree. 要将此应用于玫瑰树,如果我们有无限深度,那么路径永远不会枚举玫瑰树的最左边。 That is this tree: 就是这棵树:

      0
      |
      |
    [1,2..]
    /  \
   /    \
  /      \
[2,3..]  [2,3..]

Would produce a path like: [[0,1,2..], [0,1,2..], [0,1,2..]..] , and we'd never get past [0,1,2..] . 会产生如下路径: [[0,1,2..], [0,1,2..], [0,1,2..]..] ,我们永远不会超过[0,1,2..]

Or in another way, if we have a list containing lists ad-infinitum. 或者换句话说,如果我们有一个包含ad-infinitum列表的列表。 We can also never count (enumerate) it either, as there would be an infinite amount of dimensions that the code would jump to. 我们也可以永远不会计算(枚举)它,因为代码会跳转到无限量的维度。

This also has some relationship to real numbers being uncountably infinite too. 这也与实数无关也有一些关系。 In a lazy list of infinite real numbers would just infinitely produce 0.000.. and never enumerate past that. 在一个懒惰的无限实数列表中,它将无限地产生0.000..并且永远不会枚举过去。

I'm not sure how to formalise the above explanation, but that's my intuition. 我不确定如何形式化上述解释,但那是我的直觉。 (For reference see: https://en.wikipedia.org/wiki/Uncountable_set ) It'd be cool to see someone expand on applying https://en.wikipedia.org/wiki/Cantor's_diagonal_argument to this problem. (有关参考,请参阅: https//en.wikipedia.org/wiki/Uncountable_set )看到有人将https://en.wikipedia.org/wiki/Cantor's_diagonal_argument应用于此问题,这很酷。

This book seems to expand on it: https://books.google.com.au/books?id=OPFoJZeI8MEC&pg=PA140&lpg=PA140&dq=haskell+uncountably+infinite&source=bl&ots=Z5hM-mFT6A&sig=ovzWV3AEO16M4scVPCDD-gyFgII&hl=en&sa=X&redir_esc=y#v=onepage&q=haskell%20uncountably%20infinite&f=false 本书似乎对此进行了扩展: https//books.google.com.au/books?id = OPFoJZeI8MEC&gt = PA140&lpg = PA140&div = haskell +uncountably+infinite&source=bl&ots=Z5hM-mFT6A&sig=ovzWV3AEO16M4scVPCDD-gyFgII&hl=en&sa=X&redir_esc= Y#v = onepage&q =哈斯克尔%20uncountably%20infinite&F =假

For some reason, dfeuer has deleted his answer, which included a very nice insight and only a minor, easily-fixed problem. 出于某种原因,dfeuer删除了他的答案,其中包括一个非常好的洞察力,只有一个轻微的,容易解决的问题。 Below I discuss his nice insight, and fix the easily-fixed problem. 下面我讨论他很好的见解,并修复容易解决的问题。

His insight is that the reason the original code hangs is because it is not obvious to concat that any of the elements of its argument list are non-empty. 他的观点是,原来的代码挂原因是因为它并不明显concat任何参数列表中的元素都是非空。 Since we can prove this (outside of Haskell, with paper and pencil), we can cheat just a little bit to convince the compiler that it's so. 既然我们可以证明这一点(在Haskell之外,用纸和笔),我们可以稍微欺骗一下来说服编译器它就是这样。

Unfortunately, concat isn't quite good enough: if you give concat a list like [[1..], foo] , it will never draw elements from foo . 不幸的是, concat还不够好:如果你给concat一个像[[1..], foo]这样的列表,它永远不会从foo提取元素。 The universe collection of packages can help here with its diagonal function, which does draw elements from all sublists. universe包的集合可以在这里帮助它的diagonal函数,它可以从所有子列表中绘制元素。

Together, these two insights lead to the following code: 总之,这两个见解导致以下代码:

import Data.Tree
import Data.Universe.Helpers

paths (Node x []) = [[x]]
paths (Node x children) = map (x:) (p:ps) where
    p:ps = diagonal (map paths children)

If we define a particular infinite tree: 如果我们定义一个特定的无限树:

infTree x = Node x [infTree (x+i) | i <- [1..]]

We can look at how it behaves in ghci: 我们可以看看它在ghci中的表现如何:

> let v = paths (infTree 0)
> take 5 (head v)
[0,1,2,3,4]
> take 5 (map head v)
[0,0,0,0,0]

Looks pretty good! 看起来不错! Of course, as observed by ErikR, we cannot have all paths in here. 当然,正如ErikR所观察到的,我们不能在这里拥有所有路径。 However, given any finite prefix p of an infinite path through t , there is a finite index in paths t whose element starts with prefix p . 然而,给出的任何有限的前缀p通过一个无限路径的t ,存在一个有限索引paths t其元素与前缀开始p

Not a complete answer, but you might be interested in this detailed answer on how Haskell's permutations function is written so that it works on infinite lists: 不是一个完整的答案,但你可能会对这个关于如何编写Haskell的permutations函数的详细答案感兴趣,以便它可以在无限列表上运行:

What does this list permutations implementation in Haskell exactly do? 这个列表在Haskell中的排列实现到底是做什么的?

Update 更新

Here's a simpler way to create an infinite Rose tree: 这是创建无限Rose树的更简单方法:

iRose x = Rose x [ iRose (x+i) | i <- [1..] ]

rindex (Rose a rs) [] = a
rindex (Rose _ rs) (x:xs) = rindex (rs !! x) xs

Examples: 例子:

rindex (iRose 0) [0,1,2,3,4,5,6]     -- returns: 26
rindex infiniteTree [0,1,2,3,4,5,6]  -- returns: 13

Infinite Depth 无限深度

If a Rose tree has infinite depth and non-trivial width (> 1) there can't be an algorithm to list all of the paths just using a counting argument - the number of total paths is uncountable. 如果Rose树具有无限深度和非平凡宽度(> 1),则不能使用计数参数列出所有路径的算法 - 总路径数不可数。

Finite Depth & Infinite Breadth 有限深度和无限宽度

If the Rose tree has finite depth the number of paths is countable even if the trees have infinite breadth, and there is an algorithm which can produce all possible paths. 如果Rose树具有有限的深度,即使树具有无限宽度,路径的数量也是可数的,并且存在可以产生所有可能路径的算法。 Watch this space for updates. 观看此空间以获取更新。

ErikR has explained why you can't produce a list that necessarily contains all the paths, but it is possible to list paths lazily from the left. ErikR解释了为什么你不能生成一个必须包含所有路径的列表,但是可以从左边懒洋洋地列出路径。 The simplest trick, albeit a dirty one, is to recognize that the result is never empty and force that fact on Haskell. 最简单的技巧,虽然是一个肮脏的技巧,但是要认识到结果永远不会是空的并且在Haskell上强制这个事实。

paths (Rose x []) = [[x]]
paths (Rose x children) = map (x :) (a : as)
  where
    a : as = concatMap paths children
    -- Note that we know here that children is non-empty, and therefore
    -- the result will not be empty.

For making very infinite rose trees, consider 为了制作非常无限的玫瑰树,请考虑

infTree labels = Rose labels (infForest labels)
infForest labels = [Rose labels' (infForest labels')
                      | labels' <- map (: labels) [0..]]

As chi points out , while this definition of paths is productive, it will in some cases repeat the leftmost path forever, and never reach any more. 正如chi 指出的那样 ,虽然这种paths定义是有效的,但在某些情况下,它会永远地重复最左边的路径,而且永远不会再到达。 Oops! 哎呀! So some attempt at fairness or diagonal traversal is necessary to give interesting/useful results. 因此,为了给出有趣/有用的结果,有必要进行公平或对角遍历。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM