In [ ]:
from rmgpy.molecule import Molecule
from rmgpy.molecule.group import Group

import pdb
from IPython.display import display

In [ ]:
m = Molecule(SMILES='C12C3C4C1C5C4C6C5C2C36')
m.getSmallestSetOfSmallestRings()

In [ ]:
for i in range(10000):
    out = m.getSmallestSetOfSmallestRings()
    sizes = [len(ring) for ring in out]
    if sum(sizes) != 25:
        raise Exception('Test Failed')

In [ ]:


In [ ]:
n = Molecule(SMILES='C12CCC1C3CC2CC3')
display(n)
n.getSmallestSetOfSmallestRings()

In [ ]:
n.getRelevantCycles()

In [ ]:
o = Molecule(SMILES='C1C2C3C4CC(C5C4C4CCC5CC4)C3C(C2)C1')
display(o)
o.getSmallestSetOfSmallestRings()

In [ ]:
o.getRelevantCycles()

In [ ]:
a = Group().fromAdjacencyList("""
1 *1 C u0 p0 c0 {2,S} {4,S} {6,S}
2 *2 C u0 p0 c0 {1,S} {3,S} {7,S}
3 *3 C u0 p0 c0 {2,S} {4,S} {8,S}
4 *4 C u0 p0 c0 {1,S} {3,S} {5,S}
5 *5 C u0 p0 c0 {4,S} {6,S} {8,S}
6 *6 C u0 p0 c0 {1,S} {5,S} {7,S}
7 *7 C u0 p0 c0 {2,S} {6,S} {8,S}
8 *8 C u0 p0 c0 {3,S} {5,S} {7,S}
""")
display(a)

In [ ]:
a.getSmallestSetOfSmallestRings()

In [ ]:
a.getSSSR()

In [ ]:
b = Group().fromAdjacencyList("""
1 *1 C u0 p0 c0 {2,S} {5,S}
2 *2 C u0 p0 c0 {1,S} {3,S}
3 *3 C u0 p0 c0 {2,S} {4,S}
4 *4 C u0 p0 c0 {3,S} {5,S}
5 *5 C u0 p0 c0 {1,S} {4,S}
""")
display(b)

In [ ]:
b.getSmallestCycle(b.vertices[0])

In [ ]:
b.getSSSR()

In [ ]:
def getSmallestCycle(self, rootVertex):
    # Initialize queue
    queue = [(neighbor, rootVertex) for neighbor in rootVertex.edges.iterkeys()]
    # Initialize paths dictionary
    paths = {}
    for neighbor, source in queue:
        paths[neighbor] = set([neighbor, source])
    
    # Begin loop
    while queue and len(paths) < len(self.vertices):
        frontVertex, source = queue.pop(0)
        for neighbor in frontVertex.edges.iterkeys():
            if neighbor is not source:
                if neighbor not in paths:
                    paths[neighbor] = paths[frontVertex].copy()
                    paths[neighbor].add(neighbor)
                    queue.append((neighbor, frontVertex))
                elif len(paths[frontVertex] & paths[neighbor]) == 1:
                    return frozenset(paths[frontVertex] | paths[neighbor])
                
    return None

In [ ]:


In [ ]:


In [ ]:
def getSSSR(self):
    # Make a copy of the graph so we don't modify the original
    graph = self.copy(deep=True)
    vertices = graph.vertices[:]
    cycleList = []

    counter = 0
    while len(graph.vertices) > 0:
        graph.updateConnectivityValues()
        minDegree = min([vertex.connectivity1 for vertex in graph.vertices])
        
        if minDegree == 0:
            # Remove unconnected vertices
            done = False
            while not done:
                verticesToRemove = []
                for vertex in graph.vertices:
                    if vertex.connectivity1 == 0: verticesToRemove.append(vertex)
                done = len(verticesToRemove) == 0
                # Remove identified vertices from graph
                for vertex in verticesToRemove:
                    graph.removeVertex(vertex)
        if minDegree == 1:
            # Remove all terminal vertices
            done = False
            while not done:
                verticesToRemove = []
                for vertex in graph.vertices:
                    if vertex.connectivity1 == 1: verticesToRemove.append(vertex)
                done = len(verticesToRemove) == 0
                # Remove identified vertices from graph
                for vertex in verticesToRemove:
                    graph.removeVertex(vertex)
        elif minDegree == 2:
            # Identify all N2 vertices
            N2 = [vertex for vertex in graph.vertices if vertex.connectivity1 == 2]

            for vertex in N2:
                # Get all cycles involving the root vertex
                cycles = graph.getAllCycles(vertex)
                if len(cycles) > 0:
                    # Keep the smallest of the cycles found
                    cycle = cycles[0]
                    for c in cycles[1:]:
                        if len(c) < len(cycle):
                            cycle = c
                    cycleList.append(cycle)

            # Remove all N2 vertices
            for vertex in N2:
                graph.removeVertex(vertex)
        elif minDegree == 3:
            # Get any N3 vertex
            for vertex in graph.vertices:
                if vertex.connectivity1 == 3:
                    N3 = vertex
                    break
            # Get all cycles involving the root vertex
            cycles = graph.getAllCycles(N3)
            if len(cycles) > 0:
                # Keep the smallest of the cycles found
                cycle = cycles[0]
                for c in cycles[1:]:
                    if len(c) < len(cycle):
                        cycle = c
                cycleList.append(cycle)
            # Remove one of the bonds from the cycle
            for vertex, edge in N3.edges.iteritems():
                if vertex in cycle:
                    graph.removeEdge(edge)
                    break
        
        counter += 1
        if counter == 100:
            pdb.set_trace()
    
    # Remove duplicate cycles
    cycleSet = set([frozenset(cycle) for cycle in cycleList])
    # Convert back to lists
    cycleList = [list(cycle) for cycle in cycleSet]
    
    # Map atoms in cycles back to atoms in original graph
    for i in range(len(cycleList)):
        cycleList[i] = [self.vertices[vertices.index(v)] for v in cycleList[i]]

    return cycleList

In [ ]: