[Tutor] review of beginner's code requested
James Cunningham
jameshcunningham at gmail.com
Tue Nov 14 18:47:08 CET 2006
Hello.
I'm new to Python; for a project to get to know the language I wrote up an
api for representing finite topologies, and for subsets of topologies for
which the orbit (the number of ways to use closure, interior, and complement
operators to get separate sets) is fourteen.
It can be used like this:
some_set = [[1, 2, 3], [1, 2], [2, 3], [1, 3], [1], [2], [3], []]
a = FiniteTopology(some_set, [1, 2, 3])
...
With all attendant methods. The constructor will take a list of lists or a
set of sets.
orbits_of_fourteen(8)
will generate all topologies on subsets of [1, 2, 3, 4, 5, 6, 7, 8], and
look for subsets of those topologies whose orbits are of length fourteen.
(It will also never end. I wouldn't recommend trying that; I put it in as an
exercise.)
One thing I'm not sure of: if the user tries to create a FiniteTopology with
a collection of sets that's not a topology, I throw a NotATopologyError in
the constructor. But it looks like the FiniteTopology instance is still
created. Is there any way to keep the instance from being created at all?
I'm also interested in tips about documentation and style.
Thanks a lot!
Best,
James
#!/usr/bin/env python
class NotATopologyError(Exception):
pass
class FiniteTopology(object):
"""This represents a finite topology on a set of elements that can be
represented by Python's builtin set class. Its representation is of a
set
of frozensets, but its constructor will take a list of lists; let it be
stressed that the elements on which the topology is defined must be
immutable."""
def __init__(self, topology, main_set):
"""Creates an instance of FiniteTopology, checking first to make
sure
that it *is* a topology. If it isn't, we raise a NotATopology
exception."""
self.topology = set([frozenset(element) for element in topology])
self.main_set = set(main_set)
if not self._is_a_topology():
raise NotATopologyError()
def get_topology(self):
return self.topology
def _is_a_topology(self):
"""Checks if self.topology is a topology."""
check_one = self._check_contains_empty_main()
check_two = self._check_unions()
check_three = self._check_intersections()
return check_one and check_two and check_three
def _check_contains_empty_main(self):
"""A topology contains its set and the empty set."""
return self.main_set in self.topology and set([]) in self.topology
def _check_unions(self):
"""A topology contains all unions of open sets."""
for i in xrange(1, len(self.topology) + 1):
for subset in combinations(self.as_list(), i):
current_union = set()
for one_set in subset:
current_union = current_union.union(one_set)
if not current_union in self.topology:
return False
return True
def _check_intersections(self):
"""A topology contains all pairwise intersections of open sets."""
for item in self.topology:
for next_item in self.topology:
intersect = set(item).intersection(next_item)
if not intersect in self.topology:
return False
return True
def as_list(self):
"""Returns a list representation of the topology."""
return [[i for i in j] for j in self.topology]
def orbit(self, subset):
"""Calculates the maximum number of ways we can use take
complements,
interiors, and closures of a set to make unique sets. There are at
most 14 ways to do this, and usually less."""
orbit = set()
complement = self.complement
closure = self.closure
interior = self.interior
orbit.add(frozenset(subset))
orbit.add(frozenset(complement(subset)))
orbit.add(frozenset(complement(interior(subset))))
orbit.add(frozenset(complement(interior(complement(subset)))))
orbit.add
(frozenset(complement(interior(complement(closure(subset))))))
orbit.add(frozenset(interior(subset)))
orbit.add(frozenset(interior(closure(subset))))
orbit.add(frozenset(interior(complement(subset))))
orbit.add(frozenset(interior(complement(interior(subset)))))
orbit.add(frozenset(interior(closure(interior(subset)))))
orbit.add
(frozenset(interior(closure(interior(complement(subset))))))
orbit.add(frozenset(closure(subset)))
orbit.add(frozenset(closure(interior(subset))))
orbit.add(frozenset(closure(interior(complement(subset)))))
return orbit
def closure(self, subset):
"""A limit point p of a set X is such that all open sets containing
p
contain another point of X not equal to p. The closure of a set is
the
set plus all of its limit points.
This finds all of the limit points of the subset and adds them."""
subset = set(subset)
set_of_lps = set()
for maybe_lp in self.main_set:
is_lp = True
for open_set in self.topology:
if maybe_lp in open_set:
p = [i for i in open_set if i != maybe_lp and i in
subset]
if not len(p):
is_lp = False
if is_lp:
set_of_lps.add(maybe_lp)
return subset.union(set_of_lps)
def interior(self, subset):
"""The interior of a subset X is the union of all open subsets of
X."""
subsets = set()
for one_set in self.topology:
if set(one_set).issubset(subset):
subsets = subsets.union(one_set)
return subsets
def complement(self, subset):
"""Returns the complement of a subset."""
return set(self.main_set) - set(subset)
def combinations(sequence, n):
"""Generates all unique n-combinations of a sequence."""
if n == 0:
yield []
else:
for i in xrange(len(sequence) - (n - 1)):
for smaller_comb in combinations(sequence[i + 1:], n - 1):
yield [sequence[i]] + smaller_comb
def power_set(some_set, return_as_sets=False):
"""This returns the power set (set of all subsets) of some set, as a
list
of lists or a set of sets."""
# set_list = [[i for i in j] for j in some_set]
power_set = [[]]
for i in xrange(1, len(some_set) + 1):
for j in combinations(some_set, i):
power_set.extend([j])
if return_as_sets:
power_set = set([frozenset(subset) for subset in power_set])
return power_set
def all_collections(some_set):
"""This returns all collections of subsets of a particular set, as a
list
of lists. Takes a list."""
the_power_set = power_set(some_set)
collections = []
for i in xrange(1, len(the_power_set) + 1):
for j in combinations(the_power_set, i):
collections.append(j)
return collections
def all_topologies_on_set_of_ints(upper_index):
"""This will find all topologies on a set like [1, 2, ..., upper_index].
They'll be returned as a list."""
all_topologies = []
coll = all_collections(range(1, upper_index + 1))
for some_set in coll:
try:
curr_top = FiniteTopology(some_set, some_set[len(some_set) - 1])
except:
pass
else:
all_topologies.append(some_set)
return all_topologies
def orbits_of_fourteen(upper_index):
"""Prints topologies and subsets for which the orbit of that subset in
the
topology is fourteen."""
all_t = all_topologies_on_set_of_ints(upper_index)
for i in all_t:
for j in xrange(1, len(i[len(i) - 1]) + 1):
for comb in combinations(i[len(i) - 1], j):
orb_len = len(FiniteTopology(i, i[len(i) - 1]).orbit(comb))
if orb_len == 14:
print str(comb) + " " + str(all_t)
def main():
possible_topology = [[1, 2, 3], [1, 2], [1, 3], [2, 3], [1], [2], [3],
[]]
FiniteTopology(possible_topology, [1, 2, 3])
if __name__ == '__main__':
main()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.python.org/pipermail/tutor/attachments/20061114/8d804e15/attachment-0001.html
More information about the Tutor
mailing list