Visual studio 如何使用序列创建F#中无限集的幂集(组合)?
这是我在这个问题上失败的尝试,任何帮助都将不胜感激 我试着为在渴望列表上工作的电源组想出最好的算法。这部分似乎工作得很好。我遇到的问题是将它转换为序列,这样它就可以在流\无限列表上运行。我真的不喜欢yield语法,可能是因为我不太理解它,但我宁愿不使用yield语法Visual studio 如何使用序列创建F#中无限集的幂集(组合)?,visual-studio,math,f#,functional-programming,Visual Studio,Math,F#,Functional Programming,这是我在这个问题上失败的尝试,任何帮助都将不胜感激 我试着为在渴望列表上工作的电源组想出最好的算法。这部分似乎工作得很好。我遇到的问题是将它转换为序列,这样它就可以在流\无限列表上运行。我真的不喜欢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
//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
您的
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
的细节太多了:
open System.Collections.Generic
let-seq组合(xs:seq)=
let rec combs acc(e:IEnumerator)=
序号{
如果(e.MoveNext()),则
let added=List.map(fun ys->(e.Current)::ys)acc
“屈服!”他补充道
收益率!combs(acc@added)e}
使用枚举器=xs.GetEnumerator()
序号{
收益率[]
yield!combs[[]枚举器
}
我认为,如果你能将无限序列视为首尾序列,就像F#中的有限列表或Haskell中的任何序列一样,这会容易得多。但是很有可能有一种很好的方法可以用F#来表达,我只是没有找到它。我最近在上问了一个类似的问题,得到了一些很好的答案 对于有限集的powerset,上面链接中@Daniel的答案是一个有效的解决方案,可能适合您的目的。您可以拿出一个测试用例来比较他的方法和您的方法 关于无穷集的幂集,这里有一些数学知识。根据,可数无穷集的幂集是不可数无穷的。这意味着即使是以惰性方式,也无法枚举所有整数(可数无限)的幂集。直觉对于实数也是一样的;由于实数是不可数无限的,我们不能用无限序列来模拟它们
因此,没有算法枚举可数无穷集的幂集。或者这种算法根本没有意义。这有点像一个笑话,但实际上会为无限序列生成正确的结果(只是它无法被证明——从经验上,而不是数学上)
在一组大小为N的功率集中有2^N个元素,因此即使是一组只有60个元素的功率集中,您也会看到约10^18个元素的功率集,您永远无法完全枚举这些元素。通过使用序列而不是列表,您可能会使用更少的内存,但如果您能够更好地解释您的目标,这将是非常有帮助的。我的目标是看看我可以将f#中的惰性求值序列推到多大程度,这似乎是一个简单但足够复杂的问题。我想以绝对最懒惰的方式制作无穷集的幂集,同时保持代码的优雅和良好的性能。这很好,但考虑到幂集中的元素数量多得无法计数,即使是一个中等大小的集,如果您想对结果执行任何操作,但尚未指定顺序,则条目的生成顺序将非常重要。您建议按什么顺序返回值。它们能否以可转位的方式返回?实际上,是否可以根据输入计算索引?谢谢。我想不出一个具体的例子,但也许你正在寻找一个服从某些性质的最小集(你知道存在一个)。当然,对于无穷集的幂集,你不能严格按递增顺序进行(或者你只需要复制Daniel对一个元素子集枚举的开玩笑的解决方案),但是你可能会找到一些你知道会影响你所关心的实例的顺序。非常感谢,这解决了我在有限序列方面的问题。你有什么建议让它支持无限序列吗?或者如何在不使用屈服语法的情况下实现它?谢谢。非常感谢。这正是我要找的。如果有更干净的东西出现,我会感兴趣的。谢谢。@AaronStainback请看一看Fibonnaci数的无限序列的要点,它不使用列表,因为这样可能效率低下,因为在列表末尾追加需要重建整个列表:。出于效率原因,Seq.cache很重要。let rec绑定将生成一个警告,因为这不是一个函数。所有解决方案似乎都适用于
list
,而不是seq
,因此您不能使用它们来处理无限序列(至少不能直接使用)。您是对的。依我看,找到无限序列的动力集有点奇怪。将powerset建模为列表的惰性序列(或有限序列)似乎更合理。我同意这很奇怪,但这就是问题所在。这很好,这就是我想要的。试着看看必须编写每个函数来处理无限输入的情况。谢谢你的帮助。哇,这真的让我无法用语言表达,它是无限的。谢谢你提供的信息。这是用什么方法计算值的?当我尝试将代码更新为您的定义时,以下seqCombinations infiniteSequence失败,类型为seq@AaronStainback如我所说,这是个玩笑。因为powerset(S)包括空集,而S本身就是结果——只要您愿意观察
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
}
let powerset s =
seq {
yield Seq.empty
for x in s -> seq [x]
}