Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# Powerset Function

The function below returns the powerset of a set (list).

let rec powerset = function
  | [] -> [[]]
  | x::xs -> List.collect (fun sub -> [sub; x::sub]) (powerset xs)

I don't understand why exactly it works. I understand recursion. I also understand how List.collect works. I know that recursion will continue until an instance of powerset returns [[]]. However, I try to trace the returned values after that point and I never obtain the complete power set.

like image 467
topstarterrhp Avatar asked Sep 27 '16 01:09

topstarterrhp


1 Answers

The algorithm for calculating power set goes like this:

Let's call the original set (aka "input") A. And let's pick out an item from that set, call it x. Now, powerset of A (call it P(A)) is a set of all subsets of A. We can think of all subsets of A as consisting of two groups: subsets that include x and those that don't include x. It's easy to see that subsets that don't include x are all possible subsets of A - x (A with x excluded):

  all subsets of A that don't include x = P(A-x)

How do we get all subsets of A that do include x? By taking all those that don't include x and sticking x into each one!

  all subsets of A that include x = { for each S in P(A-x) : S+x }

Now we just need to combine the two, and we get ourselves P(A):

  P(A) = P(A-x) + { for each S in P(A-x) : S+x }

This is what the last line in your code example does: it calculates P(A-x) by calling powerset xs, and then for each of those subsets, sticks an x onto it, and also includes the subset itself.

like image 78
Fyodor Soikin Avatar answered Sep 20 '22 07:09

Fyodor Soikin