Ticket #14618: trac_14618_buckygen.patch

File trac_14618_buckygen.patch, 6.0 KB (added by ncohen, 9 years ago)
  • sage/graphs/graph_generators.py

    # HG changeset patch
    # User Nico Van Cleemput <nico.vancleemput@gmail.com>
    # Date 1369563561 -7200
    # Node ID 0206caa9027833bd0ea5782a1c6237aa8933ea60
    # Parent  0236b69932669105404abce3ffe09bd575f0f84f
    Trac 14618: Added buckygen generator for fullerenes (requires buckygen spkg)
    
    diff --git a/sage/graphs/graph_generators.py b/sage/graphs/graph_generators.py
    a b  
    172172     "line_graph_forbidden_subgraphs",
    173173     "PermutationGraph",
    174174     "SymplecticGraph",
    175      "trees"])
     175     "trees",
     176     "fullerenes"])
    176177
    177178__doc__ += """
    178179**Chessboard graphs**
     
    276277- David Coudert (2012-08-02): added chessboard graphs: Queen, King,
    277278  Knight, Bishop, and Rook graphs
    278279
     280- Nico Van Cleemput (2013-05-26): added fullerenes
     281
    279282Functions and methods
    280283---------------------
    281284"""
     
    905908
    906909        return cospectral_graphs
    907910
     911    def fullerenes(self, order, ipr=False):
     912        r"""
     913        Returns a generator which creates fullerene graphs using
     914        the buckygen generator (see [buckygen]_).
     915
     916        INPUT:
     917
     918        - ``order`` - a positive even integer smaller than or equal to 300.
     919          This specifies the number of vertices in the generated fullerenes.
     920
     921        - ``ipr`` - default: ``False`` - if ``True`` only fullerenes that
     922          satisfy the Isolated Pentagon Rule are generated. This means that
     923          no pentagonal faces share an edge.
     924
     925        OUTPUT:
     926
     927        A generator which will produce the fullerene graphs as Sage graphs
     928        with an embedding set. These will be simple graphs: no loops, no
     929        multiple edges, no directed edges.
     930
     931        EXAMPLES:
     932
     933        There are 1812 isomers of `\textrm{C}_60`, i.e., 1812 fullerene graphs
     934        on 60 vertices:  ::
     935
     936            sage: gen = graphs.fullerenes(60)  # optional buckygen
     937            sage: len(list(gen))  # optional buckygen
     938            1812
     939
     940        However, there is only one IPR fullerene graph on 60 vertices: the famous
     941        Buckminster Fullerene:  ::
     942
     943            sage: gen = graphs.fullerenes(60, ipr=True)  # optional buckygen
     944            sage: gen.next()  # optional buckygen
     945            Graph on 60 vertices
     946            sage: gen.next()  # optional buckygen
     947            Traceback (most recent call last):
     948            ...
     949            StopIteration: Exhausted list of graphs from buckygen
     950
     951        The unique fullerene graph on 20 vertices is isomorphic to the dodecahedron
     952        graph. ::
     953
     954            sage: gen = graphs.fullerenes(20)  # optional buckygen
     955            sage: g = gen.next()  # optional buckygen
     956            sage: g.get_embedding()  # optional buckygen
     957            {1: [2, 3, 4],
     958             2: [1, 5, 6],
     959             3: [1, 7, 8],
     960             4: [1, 9, 10],
     961             5: [2, 10, 11],
     962             6: [2, 12, 7],
     963             7: [3, 6, 13],
     964             8: [3, 14, 9],
     965             9: [4, 8, 15],
     966             10: [4, 16, 5],
     967             11: [5, 17, 12],
     968             12: [6, 11, 18],
     969             13: [7, 18, 14],
     970             14: [8, 13, 19],
     971             15: [9, 19, 16],
     972             16: [10, 15, 17],
     973             17: [11, 16, 20],
     974             18: [12, 20, 13],
     975             19: [14, 20, 15],
     976             20: [17, 19, 18]}
     977            sage: g.plot3d(layout='spring')  # optional buckygen
     978
     979        REFERENCE:
     980
     981        .. [buckygen] G. Brinkmann, J. Goedgebeur and B.D. McKay, Generation of Fullerenes,
     982          Journal of Chemical Information and Modeling, 52(11):2910-2918, 2012.
     983        """
     984        from sage.misc.package import is_package_installed
     985        if not is_package_installed("buckygen"):
     986            raise TypeError, "the optional buckygen package is not installed"
     987
     988        #number of vertices should be positive
     989        if order < 0:
     990            raise ValueError("Number of vertices should be positive 20.")
     991        #buckygen can only handle fullerenes on up to 300 vertices
     992        if order > 300:
     993            raise ValueError("Number of vertices should be at most 300.")
     994        #fullerenes only exist for an even number of vertices
     995        if order % 2 == 1:
     996            raise ValueError("Number of vertices should be even.")
     997
     998        #fullerenes only exist for numbers larger than 20 and different from 22
     999        if order < 20 or order == 22:
     1000            raise StopIteration("Exhausted list of graphs from buckygen")
     1001
     1002        if ipr:
     1003            command = 'buckygen -Id {0}d'.format(order)
     1004        else:
     1005            command = 'buckygen -d {0}d'.format(order)
     1006
     1007        import subprocess
     1008        sp = subprocess.Popen(command, shell=True,
     1009                              stdin=subprocess.PIPE, stdout=subprocess.PIPE,
     1010                              stderr=subprocess.PIPE, close_fds=True)
     1011        out = sp.stdout
     1012
     1013        #start of code to read planar code
     1014
     1015        #read header
     1016        header = out.read(13)
     1017
     1018        assert header == '>>planar_code', 'Not a valid planar code header'
     1019
     1020        c = out.read(1)
     1021
     1022        while c != '<':
     1023            c = out.read(1)
     1024
     1025        #one more character to read full header
     1026        c = out.read(1)
     1027
     1028        #read graph per graph
     1029        c = out.read(1)
     1030        while True:
     1031            if len(c)==0:
     1032                raise StopIteration("Exhausted list of graphs from buckygen")
     1033            order = ord(c)
     1034
     1035            zeroCount = 0
     1036
     1037            l = []
     1038            g = {}
     1039
     1040            while zeroCount < order:
     1041                c = out.read(1)
     1042                if ord(c)==0:
     1043                    zeroCount += 1
     1044                    g[zeroCount] = l
     1045                    l = []
     1046                else:
     1047                    l.append(ord(c))
     1048
     1049            #construct graph based on g
     1050            G = graph.Graph(g)
     1051            G.set_embedding(g)
     1052            yield(G)
     1053
     1054
     1055            #prepare for next graph
     1056            g = {}
     1057
     1058            c = out.read(1)
     1059
    9081060###########################################################################
    9091061# Chessboard graphs
    9101062###########################################################################