| 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 | |