“有序功率集”/“图形着色”设置

时间:2011-11-04 12:44:07

标签: f# ocaml

我希望在Ocaml中完成以下操作,但前F#中的答案可以让我有足够的洞察力来自行完成转换。

有序电源设置(从最大设置到最小设置)会让我更进一步解决下面的问题,我希望理想的是要解决这个问题。

对于低效的图形着色,我需要一个函数,它给出了以下内容:

f({a,b,c,d}):

{{a,b,c,d}}
{{a,b,c},{d}}
{{a,b,d},{c}}
{{a,c,d},{b}}
{{b,c,d},{a}}
{{a,b},{c,d}}
{{a,c},{b,d}}
{{a,d},{b,c}}
{{a},{b,c},{d}}
{{a},{b},{c,d}}
{{a},{b,d},{c}}
...
{{a},{b},{c},{d}}

作为集合列表(或更好,作为集合的惰性列表/枚举)

所以我想要在一些集合中表示所有变量。但是我希望它有序,所以我得到的是最先设置最少的那个,以及所有变量最后都设置的那个。

我有一个解决方案是这样的: f: Take powerset -> iterate -> apply f on the rest <- sort the whole list of possibilities

但我想避免排序指数列表。希望我可以使用懒惰列表来完成它,这样我就可以避免迭代所有可能性。

3 个答案:

答案 0 :(得分:6)

这是一个更新的解决方案,因为子集的顺序并不重要:

let rec splits = function
| [] -> Seq.singleton([],[])
| x::xs ->
    seq { 
        for l1,l2 in splits xs do
            yield x::l1,l2
            yield l1,x::l2
    }

let parts =
    let rec parts' = function
    | 0,[] -> Seq.singleton []
    | _,[] -> Seq.empty
    | 1,l -> Seq.singleton [l]
    | n,x::xs ->
        seq {
            for l1,l2 in splits xs do
            for p in parts'(n-1, l2) do
                yield (x::l1)::p
        }
    fun l -> seq { 
        for k = 1 to List.length l do 
            yield! parts'(k,l) 
    }

这里的想法很简单。 splits函数提供了将列表分成两组的所有方法。然后,为了计算列表x::xs的分区集,我们可以将xs的每个分区转换为l1,l2,并为l2的每个分区添加x::l1 } 在前。

但是,这不符合您的订购要求,因此我们将问题进一步解决,并使用嵌套函数part'精确计算列表l的分区n件。然后我们只需按顺序遍历这些分区列表。

答案 1 :(得分:2)

这是一个快速的想法。

懒惰地生成一组大小为N的幂集的一个众所周知的技巧是考虑其二进制表示来迭代从0到(2 ^ N)-1的每个数。每次迭代都会产生一个分区:如果当前数字的第i个数字为1,则将该组的第i个元素放在当前分区中。

你可以在你的情况下做同样的事情:P的分区不是由低于2 ^ N的二进制数给出,而是由低于N ^ N的数字给出,在基数N.现在获得分区的技巧最少的组件是:

  • 首先迭代2 ^ N(这为您提供了2个组件的分区)
  • 然后迭代到3 ^ N,拒绝其表示中没有0,a 1和a 2的数字(这排除了先前生成的分区)
  • 然后迭代到4 ^ N,只采用所有4个不同数字的数字
  • 等......高达N ^ N

显然这会让你操纵相当大的数字。您不需要将它们编码为整数/ bignum。例如在powerset案例中,布尔值列表同样好。可以在分区案例中重用相同的想法。此外,两个连续数字的K-ary表示很接近,因此您可以缓存一些信息以获得更有效的算法:

  • 您可以缓存当前分区的一部分(例如,您可以将当前分区表示为列表数组,并且只是破坏性地更新更改的几个数字)
  • 您可以缓存数字中当前存在的数字的信息(如果您在之前的迭代中已经看过这样的数字,请快速了解)

很天真,没有提议的代码,抱歉,但我希望我的想法很明确,你可以用它做一些有用的东西。知道的人肯定有更直接的想法。

特别是,可能有一种聪明的方法可以知道低于K ^ N的数字是否使用其K-ary表示的所有K个数字。例如,您知道K ^(K-1)以下没有数字(它们有少于K个不同的数字)。

答案 2 :(得分:2)

let rec comb n l =
  match n, l with
  | 0, _  -> [[]]
  | _, [] -> []
  | n, x::xs -> List.map (fun l -> x ::l) (comb (n - 1) xs) @ (comb n xs)

let listToSingleSetSet xs = List.map (Set.singleton) xs |> set

let set_2Item_merge (set_set:Set<Set<'T>>) =
  seq {
    let arX = Set.toArray set_set
    let choice_list = comb 2 [0..(arX.Length-1)]
    for [x; y] in choice_list do
      yield begin
        set_set
        |> Set.remove arX.[x]
        |> Set.remove arX.[y]
        |> Set.add (arX.[x] + arX.[y])
      end
  }

let partitions xs =
  let set_set = listToSingleSetSet xs
  let rec aux sq =
    let x = Seq.head sq
    if Set.count x = 1
    then
      Seq.singleton x
    else
      Seq.append sq (Seq.map set_2Item_merge sq |> Seq.concat |> Seq.distinct |> aux)
  aux <| Seq.singleton set_set

<强>样本

> partitions ['a'..'d'] |> Seq.iter (printfn "%A");;
set [set ['a']; set ['b']; set ['c']; set ['d']]
set [set ['a'; 'b']; set ['c']; set ['d']]
set [set ['a'; 'c']; set ['b']; set ['d']]
set [set ['a'; 'd']; set ['b']; set ['c']]
set [set ['a']; set ['b'; 'c']; set ['d']]
set [set ['a']; set ['b'; 'd']; set ['c']]
set [set ['a']; set ['b']; set ['c'; 'd']]
set [set ['a'; 'b'; 'c']; set ['d']]
set [set ['a'; 'b'; 'd']; set ['c']]
set [set ['a'; 'b']; set ['c'; 'd']]
set [set ['a'; 'c'; 'd']; set ['b']]
set [set ['a'; 'c']; set ['b'; 'd']]
set [set ['a'; 'd']; set ['b'; 'c']]
set [set ['a']; set ['b'; 'c'; 'd']]
set [set ['a'; 'b'; 'c'; 'd']]
val it : unit = ()

如果你想反向seq那么......

Seq.append sq (Seq.map set_2Item_merge sq |> Seq.concat |> Seq.distinct |> aux)

更改为

Seq.append (Seq.map set_2Item_merge sq |> Seq.concat |> Seq.distinct |> aux) sq

结果:

set [set ['a'; 'b'; 'c'; 'd']]
set [set ['a'; 'b'; 'c']; set ['d']]
set [set ['a'; 'b'; 'd']; set ['c']]
set [set ['a'; 'b']; set ['c'; 'd']]
set [set ['a'; 'c'; 'd']; set ['b']]
set [set ['a'; 'c']; set ['b'; 'd']]
set [set ['a'; 'd']; set ['b'; 'c']]
set [set ['a']; set ['b'; 'c'; 'd']]
set [set ['a'; 'b']; set ['c']; set ['d']]
set [set ['a'; 'c']; set ['b']; set ['d']]
set [set ['a'; 'd']; set ['b']; set ['c']]
set [set ['a']; set ['b'; 'c']; set ['d']]
set [set ['a']; set ['b'; 'd']; set ['c']]
set [set ['a']; set ['b']; set ['c'; 'd']]
set [set ['a']; set ['b']; set ['c']; set ['d']]