def sssr(molecule):
    """molecule -> generate the molecule.cycles that contain
    the smallest set of smallest rings"""
    results = {}
    lookup = {}
    fullSet = {}
    oatoms = {}
    # XXX FIX ME
    # copy atom.oatoms to atom._oatoms
    # atom._oatoms will be modified my the routine

    for atom in molecule.atoms:
        atom.rings = []
	fullSet[atom.handle] = 1
	lookup[atom.handle] = atom
        oatoms[atom.handle] = atom.oatoms[:]

    for bond in molecule.bonds:
        bond.rings = []
        
    trimSet = []

    while fullSet:
	nodesN2 = []
        minimum, minimum_degree = None, 100000


	# find the N2 atoms and remove atoms with degree 0
	for atomID in fullSet.keys():
	    atom = lookup[atomID]
	    degree = len(oatoms[atom.handle])
	    if degree == 0:
		del fullSet[atomID]
		#fullSet.remove(atomID)
	    elif degree == 2:
		nodesN2.append(atom)

	    # keep track of the minimum degree
	    if (degree > 0) and ( (not minimum) or 
		                (degree < minimum_degree)):
		minimum, minimum_degree = atom, degree

	if not minimum:
	    # nothing to do!  (i.e. can't have a ring)
	    break

	if minimum_degree == 1:
	    # these cannot be in rings so trim and remove
	    # my version of trimming
            for oatom in oatoms[minimum.handle]:
		oatoms[oatom.handle].remove(minimum)
            oatoms[minimum.handle] = []
	    del fullSet[minimum.handle]

	elif minimum_degree == 2:
	    # find the rings!
	    startNodes = []
	    for atom in nodesN2:
		ring, bonds = getRing(atom, fullSet, lookup, oatoms)

		if ring:
                    rlookup = ring[:]
                    rlookup.sort()
                    rlookup = tuple(rlookup)
		    if (not results.has_key(rlookup)):# not in results):
			results[rlookup] = ring, bonds
			startNodes.append(atom)

	    # in case we didn't get a ring remove the head of the nodesN2
	    startNodes = startNodes or [nodesN2[0]]
	    for atom in startNodes:
		# again, my version of trimming
                if oatoms[atom.handle]:
		    oatom = oatoms[atom.handle].pop()
		    oatoms[oatom.handle].remove(atom)

	elif minimum_degree > 2:
	    # no N2 nodes so remove the "optimum" edge to create
	    # N2 nodes in the next go-around.
	    ring, bonds = getRing(minimum, fullSet, lookup, oatoms)
            if ring:
                key = ring[:]
                key.sort()
                key = tuple(key)
                if not results.has_key(key):
                    results[key] = ring, bonds
                    atoms = map(lookup.get, ring)
                    atoms, bonds = toposort(atoms, bonds)
                    checkEdges(atoms, lookup, oatoms)
            else:
                del fullSet[minimum.handle]
 	else:
	    raise ShouldntGetHereError

    # assign the ring index to the atom
    rings = []
    index = 0

    # transform the handles back to atoms
    for result, bonds in results.values():
	ring = []
        for atomID in result:
	    atom = lookup[atomID]
            assert atom.handle == atomID
	    ring.append(atom)
	rings.append((ring, bonds))
        index = index + 1

    molecule.rings = rings
    potentialCycles = []
    index = 0
    for atoms, bonds in rings:
        # due to the dictionaries used in getRing
        # the atoms are not in the order found
        # we need to topologically sort these
        # for the cycle
        atoms, bonds = toposort(atoms, bonds)
        potentialCycles.append((atoms, bonds))

    rings = potentialCycles#checkRings(potentialCycles)
    molecule.rings = rings
    molecule.cycles = [Cycle(atoms, bonds) for atoms, bonds in rings]
    return molecule