这是我对这个问题的失败尝试,我们将不胜感激。
我试图找到最好的算法,用于在热切列表上工作的电源组。这部分似乎工作正常。我遇到问题的部分是将它转换为与Sequences一起使用,以便它可以在流\无限列表上运行它。我真的不喜欢yield语法可能因为我不太了解它但我宁愿不使用yield语法也是如此。
//All Combinations of items in a list
//i.e. the Powerset given each item is unique
//Note: lists are eager so can't be used for infinite
let listCombinations xs =
List.fold (fun acc x ->
List.collect (fun ys -> ys::[x::ys]) acc) [[]] xs
//This works fine (Still interested if it could be faster)
listCombinations [1;2;3;4;5] |> Seq.iter (fun x -> printfn "%A" x)
//All Combinations of items in a sequence
//i.e. the Powerset given each item is unique
//Note: Not working
let seqCombinations xs =
Seq.fold (fun acc x ->
Seq.collect (fun ys ->
seq { yield ys
yield seq { yield x
yield! ys} }) acc) Seq.empty xs
//All Combinations of items in a sequence
//i.e. the Powerset given each item is unique
//Note: Not working (even wrong type signature)
let seqCombinations2 xs =
Seq.fold (fun acc x ->
Seq.collect (fun ys ->
Seq.append ys (Seq.append x ys)) acc) Seq.empty xs
//Sequences to test on
let infiniteSequence = Seq.initInfinite (fun i -> i + 1)
let finiteSequence = Seq.take 5 infiniteSequence
//This should work easy since its in a finite sequence
//But it does not, so their must be a bug in 'seqCombinations' above
for xs in seqCombinations finiteSequence do
for y in xs do
printfn "%A" y
//This one is much more difficult to get to work
//since its the powerset on the infinate sequence
//None the less If someone could help me find a way to make this work
//This is my ultimate goal
let firstFew = Seq.take 20 (seqCombinations infiniteSequence)
for xs in firstFew do
for y in xs do
printfn "%A" y
答案 0 :(得分:6)
您的seqCombinations
几乎是正确的,但您没有正确地将其从列表转换为序列。相当于[[]]
不是Seq.empty
,而是Seq.singleton Seq.empty
:
let seqCombinations xs =
Seq.fold (fun acc x ->
Seq.collect (fun ys ->
seq { yield ys
yield seq { yield x
yield! ys} }) acc) (Seq.singleton Seq.empty) xs
上面的代码适用于有限序列。但是对于无限的,它不起作用,因为它首先试图达到目的,这显然从来没有为无限序列做过。
如果你想要一个可以使用无限序列的函数,我设法找到两种方法,但它们都不是特别好。其中一个使用可变状态:
let seqCombinations xs =
let combs = ref [[]]
seq {
yield! !combs
for x in xs do
let added = List.map (fun ys -> x::ys) !combs
yield! added
combs := !combs @ added
}
另一个是关于处理seq<T>
的详细信息:
open System.Collections.Generic
let seqCombinations (xs : seq<_>) =
let rec combs acc (e : IEnumerator<_>) =
seq {
if (e.MoveNext()) then
let added = List.map (fun ys -> (e.Current)::ys) acc
yield! added
yield! combs (acc @ added) e }
use enumerator = xs.GetEnumerator()
seq {
yield []
yield! combs [[]] enumerator
}
我认为如果你可以将无限序列视为头部和尾部,比如F#中的有限列表或Haskell中的任何序列,这将会容易得多。但是有可能在F#中有一种很好的表达方式,而我却找不到它。
答案 1 :(得分:3)
我最近在Generate powerset lazily问了一个类似的问题并得到了一些不错的答案。
对于有限集的幂集,@丹尼尔在上述链接中的答案是一种有效的解决方案,可能适合您的目的。你可以拿出一个测试用例来比较他和你的方法。
关于无限集的幂集,这里有一些数学。根据{{3}},可数无限集的幂集是无穷无尽的。这意味着即使以懒惰的方式也无法枚举所有整数的幂集(这是无数的)。真实数字的直觉是相同的;由于实数是无穷无尽的,我们实际上无法使用无限序列对它们进行建模。
因此,没有算法可以枚举可数无限集的幂集。或者那种算法没有意义。
答案 2 :(得分:1)
这是一个笑话,但实际上会为无限序列生成正确的结果(只是它无法证明 - 经验上,而不是数学上)。
let powerset s =
seq {
yield Seq.empty
for x in s -> seq [x]
}