A Little Off Code, Computers, Photography and Guns

13Mar/090

Power Set Generator

Recently I had a bout of programming withdrawal so I set out to write a power-set generator.

So a little background on the power set. The power set of a given set A is the set containing all subsets of A. Suppose that we have a set:

A = \{x,y,z\}

The power set of A would be:

\mathcal{P}(A) = \left\{\emptyset, \{x\}, \{y\}, \{z\}, \{x, y\}, \{x, z\}, \{y, z\}, \{x, y, z\}\right\}\,\!.

Now looking more carefully at the power set of A you'll notice that it contains 2 to the power of the cardinality of A subsets, always containing the empty set.

2^{|A|} = 8

The code I came up with for this is short and more or less simple[1]:

1
2
3
4
5
6
7
8
9
10
def PowerSet(base):
    power_set = []
    b = len(base)
    map(lambda g: power_set.append(map(lambda x: base[x],
        filter(lambda x: g[x], range(0, b)))),
        map(lambda value: map(lambda x: (value >> x) & 1, range(b - 1, -1, -1)),
        map(lambda value: value ^ (value / 2), range(0, 2**b))))
    return power_set

print PowerSet([1,2,3])

I figured out shortly after I wrote this that I had the right general idea but in this particular case, since I'm not actually using set types... the graycode I'm generating is useless for this sort of thing.

The point of generating graycode for this is that graycode is used for binary counting such that only one digit is changed from one consecutive value to the next. It was originally designed so that mechanical switches in early computers wouldn't cause a race condition while counting fast enough.

In this particular solution using graycode is useful for only having to add one new element to a set at a time which if I were actually using sets, would be faster, but since I'm not, it isn't. I'll probably rewrite it later to make it play nicer with graycode.

The basic procedure here is that given a set A we're going to count from 0 to 2^|A| - 1 and in binary graycode, the 1's determine the elements of the base set that will be added as a new set to the power set and 0's indicate that that element of the base set will be ignored in the current subset.

  1. I lied, i just got a little pythonic functional programming happy. []