Advanced Usage

Visualization

With the help of the optional Graphviz graph layout library and this Python interface, the bitsets.visualize module can create Hasse diagrams of all bitsets from your domain:

Download and install Graphviz. Then install the Python interface (documentation):

$ pip install "graphviz~=0.7"

Make sure that the bin/ directory of Graphviz is on your system path.

>>> from bitsets import bitset, visualize
>>> Four = bitset('Four', (1, 2, 3, 4))

>>> dot = visualize.bitset(Four)

>>> print(dot.source)  
// <class bitsets.meta.bitset('Four', (1, 2, 3, 4), 0x..., BitSet, None, None)>
digraph Four {
    edge [dir=none]
            b0 [label=0000]
            b1 [label=1000]
                    b1 -> b0
            b2 [label=0100]
                    b2 -> b0
            b3 [label=1100]
                    b3 -> b1
                    b3 -> b2
...
_images/hasse-bits.svg

Show members instead of bits:

>>> dot = visualize.bitset(Four, member_label=True)

>>> print(dot.source)  
// <class bitsets.meta.bitset('Four', (1, 2, 3, 4), 0x..., BitSet, None, None)>
digraph Four {
    edge [dir=none]
            b0 [label="{}"]
            b1 [label="{1}"]
                    b1 -> b0
            b2 [label="{2}"]
                    b2 -> b0
            b3 [label="{1,2}"]
                    b3 -> b1
                    b3 -> b2
...
_images/hasse-members.svg

Remember that the graphs have 2 ** domain_size nodes.

Containers

When activated, each bitset class comes with tailored collection classes (BitSet.List and BitSet.Tuple) for its instances.

>>> Letters = bitset('Letters', 'abcdef', list=True)

>>> Letters.List.frommembers(['a', 'bcd', 'ef'])
LettersList('100000', '011100', '000011')

The collection classes have convenience methods for set intersection and union of the contained sets (reduce_and() and reduce_or()):

>>> import string

>>> Ascii = bitset('Ascii', string.ascii_lowercase, list=True)
>>> ascii = Ascii.List.frommembers(['spam', 'eggspam', 'ham'])

>>> ascii.reduce_and()
Ascii(['a', 'm'])

>>> ascii.reduce_or()
Ascii(['a', 'e', 'g', 'h', 'm', 'p', 's'])

Customization

To use a customized bitset class, extend one of the classes from the bitsets.bases module and pass it to the bitset() function.

>>> import bitsets

>>> class ProperSet(bitsets.bases.BitSet):
...     def issubset_proper(self, other):
...         return self & other == self != other

>>> Ints = bitset('Ints', (1, 2, 3, 4, 5, 6), base=ProperSet)

>>> issubclass(Ints, ProperSet)
True

>>> Ints([1]).issubset_proper(Ints([1, 2]))
True

>>> Ints([1, 2]).issubset_proper(Ints([1, 2]))
False

To use a customized bitset collection class, extend one of the classes from the bitsets.series module and pass it to the bitset() function.

>>> from functools import reduce
>>> import operator

>>> class ReduceList(bitsets.series.List):
...     def intersection(self):
...         return self.BitSet.fromint(reduce(operator.and_, self))
...     def union(self):
...         return self.BitSet.fromint(reduce(operator.or_, self))

>>> Nums = bitset('Nums', (1, 2, 3), list=ReduceList)

>>> issubclass(Nums.List, ReduceList)
True

>>> numslist = Nums.List.frommembers([(1, 2, 3), (1, 2), (2, 3)])

>>> numslist.intersection()
Nums([2])

>>> numslist.union()
Nums([1, 2, 3])

Note that since version 0.4, this very functionality was added to the bitsets.series classes as reduce_and() and reduce_or() methods (see above).

Persistence

Bitset classes, collection classes and their instances are pickleable:

>>> import pickle

>>> PYTHONS = ('Chapman', 'Cleese', 'Gilliam', 'Idle', 'Jones', 'Palin')
>>> Pythons = bitset('Pythons', PYTHONS)

>>> pickle.loads(pickle.dumps(Pythons)) is Pythons
True

>>> pickle.loads(pickle.dumps(Pythons()))
Pythons()

>>> pickle.loads(pickle.dumps(Pythons(), protocol=pickle.HIGHEST_PROTOCOL))
Pythons()

>>> pickle.loads(pickle.dumps(Letters.List)) is Letters.List
True

>>> pickle.loads(pickle.dumps(Letters.List()))
LettersList()

As long as customized bitset collection classes are defined at the top-level of an importable module, the class and its instances are pickleable.

>>> pickle.loads(pickle.dumps(Nums.List)) is Nums.List  
True

>>> pickle.loads(pickle.dumps(Nums.List()))  
NumsList()