Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/graphs/isgci.py
8815 views
1
r"""
2
Information System on Graph Classes and their Inclusions
3
4
This module implements an interface to the `ISGCI <http://www.graphclasses.org/>`_ database in Sage.
5
6
This database gathers information on graph classes and their
7
inclusions in each other. It also contains information on the
8
complexity of several computational problems.
9
10
It is available on the `GraphClasses.org <http://www.graphclasses.org/>`_
11
website maintained by H.N. de Ridder et al.
12
13
How to use it?
14
--------------
15
16
The current limited aim of this module is to provide a pure Sage/Python
17
interface which is easier to deal with than a XML file. I hope it will be
18
rewritten many times until it stabilizes :-)
19
20
Presently, it is possible to use this database through the variables and methods
21
present in the :obj:`graph_classes <GraphClasses>` object.
22
For instance::
23
24
sage: Trees = graph_classes.Tree
25
sage: Chordal = graph_classes.Chordal
26
27
It is then possible to check the inclusion of classes inside of others, if the
28
information is available in the database::
29
30
sage: Trees <= Chordal
31
True
32
33
And indeed, trees are chordal graphs.
34
35
.. WARNING::
36
37
The ISGCI database is not all-knowing, and so comparing two classes can
38
return ``True``, ``False``, or ``Unknown`` (see the :mod:`documentation of
39
the Unknown truth value <sage.misc.unknown>`).
40
41
An *unknown* answer to ``A <= B`` only means that ISGCI cannot deduce from
42
the information in its database that ``A`` is a subclass of ``B`` nor that
43
it is not. For instance, ISGCI does not know at the moment that some chordal
44
graphs are not trees::
45
46
sage: graph_classes.Chordal <= graph_classes.Tree
47
Unknown
48
49
Given a graph class, one can obtain its associated information in the
50
ISGCI database with the :meth:`~GraphClass.description` method::
51
52
sage: Chordal.description()
53
Class of graphs : Chordal
54
-------------------------
55
type : base
56
ID : gc_32
57
name : chordal
58
<BLANKLINE>
59
Problems :
60
-----------
61
3-Colourability : Linear
62
Clique : Polynomial
63
Clique cover : Polynomial
64
Cliquewidth : Unbounded
65
Cliquewidth expression : NP-complete
66
Colourability : Linear
67
Domination : NP-complete
68
Independent set : Linear
69
Recognition : Linear
70
Treewidth : Polynomial
71
Weighted clique : Polynomial
72
Weighted independent set : Linear
73
74
It is possible to obtain the complete list of the classes stored in ISGCI by
75
calling the :meth:`~GraphClasses.show_all` method (beware -- long output)::
76
77
sage: graph_classes.show_all()
78
ID | name | type | smallgraph
79
----------------------------------------------------------------------------------------------------------------------
80
gc_309 | $K_4$--minor--free | base |
81
gc_541 | $N^*$ | base |
82
gc_215 | $N^*$--perfect | base |
83
gc_5 | $P_4$--bipartite | base |
84
gc_3 | $P_4$--brittle | base |
85
gc_6 | $P_4$--comparability | base |
86
gc_7 | $P_4$--extendible | base |
87
...
88
89
Until a proper search method is implemented, this lets one find
90
classes which do not appear in :obj:`graph_classes.* <GraphClasses>`.
91
92
To retrieve a class of graph from its ISGCI ID one may use
93
the :meth:`~GraphClasses.get_class` method::
94
95
sage: GC = graph_classes.get_class("gc_5")
96
sage: GC
97
$P_4$--bipartite graphs
98
99
Predefined classes
100
------------------
101
102
:obj:`graph_classes <GraphClasses>` currently predefines the following graph classes
103
104
.. list-table::
105
:widths: 20 30
106
:header-rows: 1
107
108
* - Class
109
- Related methods
110
111
* - BinaryTrees
112
113
- :meth:`~sage.graphs.graph_generators.GraphGenerators.BalancedTree`,
114
:meth:`~Graph.is_tree`
115
116
* - Bipartite
117
118
- :meth:`~sage.graphs.graph_generators.GraphGenerators.BalancedTree`,
119
:meth:`~sage.graphs.graph.Graph.is_bipartite`
120
121
* - Block
122
123
- :meth:`~sage.graphs.generic_graph.GenericGraph.blocks_and_cut_vertices`,
124
125
* - Chordal
126
127
- :meth:`~sage.graphs.generic_graph.GenericGraph.is_chordal`
128
129
* - Comparability
130
-
131
132
* - Gallai
133
134
- :meth:`~sage.graphs.generic_graph.GenericGraph.is_gallai_tree`
135
136
* - Grid
137
138
- :meth:`~sage.graphs.graph_generators.GraphGenerators.Grid2dGraph`,
139
:meth:`~sage.graphs.graph_generators.GraphGenerators.GridGraph`
140
141
* - Interval
142
143
- :meth:`~sage.graphs.graph_generators.GraphGenerators.RandomInterval`,
144
:meth:`~sage.graphs.graph_generators.GraphGenerators.IntervalGraph`,
145
:meth:`~sage.graphs.generic_graph.GenericGraph.is_interval`
146
147
* - Line
148
149
- :meth:`~sage.graphs.graph_generators.GraphGenerators.line_graph_forbidden_subgraphs`,
150
:meth:`~sage.graphs.graph.Graph.is_line_graph`
151
152
* - Modular
153
154
- :meth:`~sage.graphs.graph.Graph.modular_decomposition`
155
156
* - Outerplanar
157
158
- :meth:`~sage.graphs.generic_graph.GenericGraph.is_circular_planar`
159
160
* - Perfect
161
162
- :meth:`~sage.graphs.graph.Graph.is_perfect`
163
164
* - Planar
165
166
- :meth:`~sage.graphs.generic_graph.GenericGraph.is_planar`
167
168
* - Split
169
170
- :meth:`~sage.graphs.graph.Graph.is_split`
171
172
* - Tree
173
174
- :meth:`~sage.graphs.graph_generators.GraphGenerators.trees`,
175
:meth:`~Graph.is_tree`
176
177
* - UnitDisk
178
- :meth:`~sage.graphs.graph_generators.GraphGenerators.IntervalGraph`,
179
180
* - UnitInterval
181
182
- :meth:`~sage.graphs.generic_graph.GenericGraph.is_interval`
183
184
Sage's view of ISGCI
185
--------------------
186
187
The database is stored by Sage in two ways.
188
189
**The classes**: the list of all graph classes and their properties is stored
190
in a huge dictionary (see :meth:`~sage.graphs.isgci.GraphClasses.classes`).
191
Below is what Sage knows of ``gc_249``::
192
193
sage: graph_classes.classes()['gc_249'] # random
194
{'problems':
195
{'Independent set': 'Polynomial',
196
'Treewidth': 'Unknown',
197
'Weighted independent set': 'Polynomial',
198
'Cliquewidth expression': 'NP-complete',
199
'Weighted clique': 'Polynomial',
200
'Clique cover': 'Unknown',
201
'Domination': 'NP-complete',
202
'Clique': 'Polynomial',
203
'Colourability': 'NP-complete',
204
'Cliquewidth': 'Unbounded',
205
'3-Colourability': 'NP-complete',
206
'Recognition': 'Linear'},
207
'type': 'base',
208
'ID': 'gc_249',
209
'name': 'line'}
210
211
**The class inclusion digraph**: Sage remembers the class inclusions through
212
the inclusion digraph (see :meth:`~sage.graphs.isgci.GraphClasses.inclusion_digraph`).
213
Its nodes are ID of ISGCI classes::
214
215
sage: d = graph_classes.inclusion_digraph()
216
sage: d.vertices()[-10:]
217
['gc_990', 'gc_991', 'gc_992', 'gc_993', 'gc_994', 'gc_995', 'gc_996', 'gc_997', 'gc_998', 'gc_999']
218
219
An arc from ``gc1`` to ``gc2`` means that ``gc1`` is a superclass of
220
``gc2``. This being said, not all edges are stored ! To ensure that a given
221
class is included in another one, we have to check whether there is in the
222
digraph a ``path`` from the first one to the other::
223
224
sage: bip_id = graph_classes.Bipartite._gc_id
225
sage: perfect_id = graph_classes.Perfect._gc_id
226
sage: d.has_edge(perfect_id, bip_id)
227
False
228
sage: d.distance(perfect_id, bip_id)
229
2
230
231
Hence bipartite graphs are perfect graphs. We can see how ISGCI obtains this
232
result ::
233
234
sage: p = d.shortest_path(perfect_id, bip_id)
235
sage: len(p) - 1
236
2
237
sage: print p # random
238
['gc_56', 'gc_76', 'gc_69']
239
sage: for c in p:
240
... print graph_classes.get_class(c)
241
perfect graphs
242
...
243
bipartite graphs
244
245
What ISGCI knows is that perfect graphs contain unimodular graph which contain
246
bipartite graphs. Therefore bipartite graphs are perfect !
247
248
.. note::
249
250
The inclusion digraph is **NOT ACYCLIC**. Indeed, several entries
251
exist in the ISGCI database which represent the same graph class,
252
for instance Perfect graphs and Berge graphs::
253
254
sage: graph_classes.inclusion_digraph().is_directed_acyclic()
255
False
256
sage: Berge = graph_classes.get_class("gc_274"); Berge
257
Berge graphs
258
sage: Perfect = graph_classes.get_class("gc_56"); Perfect
259
perfect graphs
260
sage: Berge <= Perfect
261
True
262
sage: Perfect <= Berge
263
True
264
sage: Perfect == Berge
265
True
266
267
Information for developpers
268
----------------------------
269
270
* The database is loaded not *so* large, but it is still preferable to
271
only load it on demand. This is achieved through the cached methods
272
:meth:`~sage.graphs.isgci.GraphClasses.classes` and
273
:meth:`~sage.graphs.isgci.GraphClasses.inclusion_digraph`.
274
275
* Upon the first access to the database, the information is extracted
276
from the XML file and stored in the cache of three methods:
277
278
* ``sage.graphs.isgci._classes`` (dictionary)
279
* ``sage.graphs.isgci._inclusions`` (list of dictionaries)
280
* ``sage.graphs.isgci._inclusion_digraph`` (DiGraph)
281
282
Note that the digraph is only built if necessary (for instance if
283
the user tries to compare two classes).
284
285
.. todo::
286
287
Technical things:
288
289
* Query the database for non-inclusion results so that comparisons can
290
return ``False``, and implement strict inclusions.
291
292
* Implement a proper search method for the classes not listed in
293
:obj:`graph_classes <GraphClasses>`
294
295
.. seealso: :func:`sage.graphs.isgci.show_all`.
296
297
* Some of the graph classes appearing in :obj:`graph_classes
298
<GraphClasses>` already have a recognition
299
algorithm implemented in Sage. It would be so nice to be able to
300
write ``g in Trees``, ``g in Perfect``, ``g in Chordal``, ... :-)
301
302
Long-term stuff:
303
304
* Implement simple accessors for all the information in the ISGCI
305
database (as can be done from the website)
306
307
* Implement intersection of graph classes
308
309
* Write generic recognition algorithms for specific classes (when a graph class
310
is defined by the exclusion of subgraphs, one can write a generic algorithm
311
checking the existence of each of the graphs, and this method already exists
312
in Sage).
313
314
* Improve the performance of Sage's graph library by letting it
315
take advantage of the properties of graph classes. For example,
316
:meth:`Graph.independent_set` could use the library to detect
317
that a given graph is, say, a tree or a planar graph, and use a
318
specialized algorithm for finding an independent set.
319
320
AUTHORS:
321
--------
322
323
* H.N. de Ridder et al. (ISGCI database)
324
* Nathann Cohen (Sage implementation)
325
326
Methods
327
-------
328
"""
329
330
from sage.structure.sage_object import SageObject
331
from sage.structure.unique_representation import CachedRepresentation, UniqueRepresentation
332
from sage.misc.unknown import Unknown
333
from sage.misc.misc import SAGE_SHARE
334
335
#*****************************************************************************
336
# Copyright (C) 2011 Nathann Cohen <[email protected]>
337
#
338
# Distributed under the terms of the GNU General Public License (GPL)
339
# http://www.gnu.org/licenses/
340
#*****************************************************************************
341
342
_XML_FILE = "isgci_sage.xml"
343
344
class GraphClass(SageObject, CachedRepresentation):
345
r"""
346
An instance of this class represents a Graph Class, matching some entry in
347
the ISGCI database.
348
349
EXAMPLE:
350
351
Testing the inclusion of two classes::
352
353
sage: Chordal = graph_classes.Chordal
354
sage: Trees = graph_classes.Tree
355
sage: Trees <= Chordal
356
True
357
sage: Chordal <= Trees
358
Unknown
359
360
TEST::
361
362
sage: Trees >= Chordal
363
Unknown
364
sage: Chordal >= Trees
365
True
366
"""
367
def __init__(self, name, gc_id):
368
r"""
369
Class constructor
370
371
EXAMPLE::
372
373
sage: graph_classes.Chordal # indirect doctest
374
Chordal graphs
375
"""
376
self._name = name
377
self._gc_id = gc_id
378
379
def _repr_(self):
380
r"""
381
Returns a short description of the class
382
383
EXAMPLE::
384
385
sage: graph_classes.Chordal # indirect doctest
386
Chordal graphs
387
"""
388
return self._name+" graphs"
389
390
def __hash__(self):
391
r"""
392
Returns the class' ID hash
393
394
EXAMPLE::
395
396
sage: hash(graph_classes.Chordal) == hash(graph_classes.Chordal)
397
True
398
"""
399
return hash(self._gc_id)
400
401
def __le__(self, other):
402
r"""
403
<= operator
404
405
EXAMPLE::
406
407
sage: graph_classes.Chordal <= graph_classes.Tree
408
Unknown
409
"""
410
return other.__ge__(self)
411
412
def __ge__(self, other):
413
r"""
414
>= operator
415
416
EXAMPLE::
417
418
sage: graph_classes.Chordal >= graph_classes.Tree
419
True
420
"""
421
422
inclusion_digraph = GraphClasses().inclusion_digraph()
423
if inclusion_digraph.shortest_path(self._gc_id,other._gc_id) != []:
424
return True
425
else:
426
return Unknown
427
428
def __eq__(self, other):
429
r"""
430
== operator
431
432
EXAMPLE::
433
434
sage: graph_classes.Chordal == graph_classes.Tree
435
Unknown
436
"""
437
return self.__ge__(other) and other.__ge__(self)
438
439
def __lt__(self, other):
440
r"""
441
>, !=, and < operators
442
443
EXAMPLE::
444
445
sage: graph_classes.Chordal > graph_classes.Tree
446
Traceback (most recent call last):
447
...
448
NotImplementedError
449
sage: graph_classes.Chordal < graph_classes.Tree
450
Traceback (most recent call last):
451
...
452
NotImplementedError
453
sage: graph_classes.Chordal != graph_classes.Tree
454
Traceback (most recent call last):
455
...
456
NotImplementedError
457
"""
458
raise NotImplementedError
459
460
__gt__ = __ne__ = __lt__
461
462
def description(self):
463
r"""
464
Prints the information of ISGCI about the current class.
465
466
EXAMPLE::
467
468
sage: graph_classes.Chordal.description()
469
Class of graphs : Chordal
470
-------------------------
471
type : base
472
ID : gc_32
473
name : chordal
474
<BLANKLINE>
475
Problems :
476
-----------
477
3-Colourability : Linear
478
Clique : Polynomial
479
Clique cover : Polynomial
480
Cliquewidth : Unbounded
481
Cliquewidth expression : NP-complete
482
Colourability : Linear
483
Domination : NP-complete
484
Independent set : Linear
485
Recognition : Linear
486
Treewidth : Polynomial
487
Weighted clique : Polynomial
488
Weighted independent set : Linear
489
"""
490
491
classes = GraphClasses().classes()
492
493
cls = classes[self._gc_id]
494
print "Class of graphs : "+self._name
495
print "-"*(len(self._name)+18)
496
497
for key, value in cls.iteritems():
498
if value != "" and key != "problems":
499
print "{0:30} : ".format(key),
500
print value
501
502
print "\nProblems :"
503
print "-"*11
504
for key, value in sorted(cls["problems"].iteritems()):
505
if value != "":
506
print "{0:30} : ".format(key),
507
print value
508
509
from sage.misc.cachefunc import cached_method
510
511
class GraphClasses(UniqueRepresentation):
512
def get_class(self, id):
513
r"""
514
Returns the class corresponding to the given id in the ISGCI database.
515
516
INPUT:
517
518
- ``id`` (string) -- the desired class' ID
519
520
.. seealso:
521
522
:meth:`~sage.graphs.isgci.GraphClasses.show_all`
523
524
EXAMPLE:
525
526
With an existing id::
527
528
sage: Cographs = graph_classes.get_class("gc_151")
529
sage: Cographs
530
cograph graphs
531
532
With a wrong id::
533
534
sage: graph_classes.get_class(-1)
535
Traceback (most recent call last):
536
...
537
ValueError: The given class id does not exist in the ISGCI database. Is the db too old ? You can update it with graph_classes.update_db().
538
"""
539
classes = self.classes()
540
if id in classes:
541
c = classes[id]
542
543
if "name" in c and c["name"] != "":
544
name = c["name"]
545
else:
546
name = "class "+str(id)
547
548
return GraphClass(name, id)
549
else:
550
raise ValueError("The given class id does not exist in the ISGCI database. Is the db too old ? You can update it with graph_classes.update_db().")
551
552
@cached_method
553
def classes(self):
554
r"""
555
Returns the graph classes, as a dictionary.
556
557
Upon the first call, this loads the database from the local
558
XML file. Subsequent calls are cached.
559
560
EXAMPLES::
561
562
sage: t = graph_classes.classes()
563
sage: type(t)
564
<type 'dict'>
565
sage: sorted(t["gc_151"].keys())
566
['ID', 'name', 'problems', 'type']
567
sage: t["gc_151"]['name']
568
'cograph'
569
sage: t["gc_151"]['problems']['Clique']
570
'Linear'
571
"""
572
classes, inclusions = self._get_ISGCI()
573
self.inclusions.set_cache(inclusions)
574
return classes
575
576
@cached_method
577
def inclusions(self):
578
r"""
579
Returns the graph class inclusions
580
581
OUTPUT:
582
583
a list of dictionaries
584
585
Upon the first call, this loads the database from the local
586
XML file. Subsequent calls are cached.
587
588
EXAMPLES::
589
590
sage: t = graph_classes.inclusions()
591
sage: type(t)
592
<type 'list'>
593
sage: t[0]
594
{'super': 'gc_2', 'sub': 'gc_1'}
595
"""
596
self.classes()
597
return self.inclusions()
598
599
@cached_method
600
def inclusion_digraph(self):
601
r"""
602
Returns the class inclusion digraph
603
604
Upon the first call, this loads the database from the local
605
XML file. Subsequent calls are cached.
606
607
EXAMPLES::
608
609
sage: g = graph_classes.inclusion_digraph(); g
610
Digraph on ... vertices
611
"""
612
classes = self.classes()
613
inclusions = self.inclusions()
614
615
from sage.graphs.digraph import DiGraph
616
inclusion_digraph = DiGraph()
617
inclusion_digraph.add_vertices(classes.keys())
618
619
for edge in inclusions:
620
if edge.get("confidence","") == "unpublished":
621
continue
622
inclusion_digraph.add_edge(edge['super'], edge['sub'])
623
624
return inclusion_digraph
625
626
def _download_db(self):
627
r"""
628
Downloads the current version of the ISGCI db
629
630
EXAMPLE::
631
632
sage: graph_classes._download_db() # Not tested -- requires internet
633
"""
634
635
from sage.misc.misc import SAGE_TMP
636
import urllib2
637
import os.path
638
u = urllib2.urlopen('http://www.graphclasses.org/data.zip')
639
localFile = open(os.path.join(SAGE_TMP,'isgci.zip'), 'w')
640
localFile.write(u.read())
641
localFile.close()
642
import os, zipfile
643
z = zipfile.ZipFile(os.path.join(SAGE_TMP,'isgci.zip'))
644
645
# Save a systemwide updated copy whenever possible
646
647
try:
648
z.extract(_XML_FILE, os.path.join(SAGE_SHARE,'graphs'))
649
except IOError:
650
z.extract(_XML_FILE, SAGE_TMP)
651
652
653
def _parse_db(self, xml_file):
654
r"""
655
Parses the ISGCI database and returns its content as Python objects.
656
657
INPUT:
658
659
- ``xml_file`` -- the name of an XML file containing the data from ISGCI
660
661
EXAMPLE::
662
663
sage: import os
664
sage: from sage.misc.misc import SAGE_SHARE
665
sage: map(type, graph_classes._parse_db(os.path.join(SAGE_SHARE,'graphs','isgci_sage.xml')))
666
[<type 'dict'>, <type 'list'>]
667
"""
668
import xml.dom.minidom
669
from xml.dom.minidom import Node
670
671
# This method is there to parse the XML file containing the ISGCI
672
# database. It is admittedly not very pretty, but it builds the class we
673
# want from the XML file and that's more or less all we ask it to do :-p
674
675
doc = xml.dom.minidom.parse(xml_file)
676
677
classes = {}
678
679
giveme = lambda x,y : str(x.getAttribute(y))
680
681
for node in doc.getElementsByTagName("GraphClass"):
682
ID = str(node.getAttribute("id"))
683
Dl = {}
684
smallgraph = []
685
Dl["ID"] = giveme(node, "id")
686
problems = {}
687
for node2 in node.childNodes:
688
name = str(node2.nodeName)
689
if name == "name":
690
Dl[name] = str(node2.childNodes[0].nodeValue)
691
692
elif name == "smallgraph":
693
smallgraph.append(str(node2.childNodes[0].nodeValue))
694
695
elif name == "problem":
696
problems[giveme(node2, "name")] = giveme(node2, "complexity")
697
698
Dl["problems"] = problems
699
700
if smallgraph:
701
Dl["smallgraph"] = smallgraph
702
703
if giveme(node, "type"):
704
Dl["type"] = giveme(node, "type")
705
706
707
classes[giveme(node, "id")] = Dl
708
709
inclusions = []
710
for node in doc.getElementsByTagName("incl"):
711
Dl = {}
712
for name in ["proper", "confidence", "super", "sub"]:
713
if giveme(node, name):
714
Dl[name] = giveme(node, name)
715
716
for node2 in node.childNodes:
717
name = str(node2.nodeName)
718
if name == "ref":
719
Dl[name] = str(node2.childNodes[0].nodeValue)
720
721
inclusions.append(Dl)
722
723
return classes, inclusions
724
725
def update_db(self):
726
r"""
727
Updates the ISGCI database by downloading the latest version from internet.
728
729
This method downloads the ISGCI database from the website
730
`GraphClasses.org <http://www.graphclasses.org/>`_. It then extracts the
731
zip file and parses its XML content.
732
733
Depending on the credentials of the user running Sage when this command
734
is run, one attempt is made at saving the result in Sage's directory so
735
that all users can benefit from it. If the credentials are not
736
sufficient, the XML file are saved instead in the user's directory (in
737
the SAGE_DB folder).
738
739
EXAMPLE::
740
741
sage: graph_classes.update_db() # Not tested -- requires internet
742
"""
743
from sage.misc.misc import SAGE_TMP, SAGE_DB
744
745
self._download_db()
746
747
print "Database downloaded"
748
749
self.classes.clear_cache()
750
self.inclusions.clear_cache()
751
self.inclusion_digraph.clear_cache()
752
753
def _get_ISGCI(self):
754
r"""
755
Returns the contents of the ISGCI database.
756
757
This method is mostly for internal use, but often provides useful
758
information during debugging operations.
759
760
OUTPUT:
761
762
A pair ``(classes, inclusions)`` where ``classes`` is a dict of dict, and
763
``inclusions`` is a list of dicts.
764
765
.. NOTE::
766
767
This method returns the data contained in the most recent ISGCI database
768
present on the computer. See :meth:`update_db` to update the latter.
769
770
EXAMPLE::
771
772
sage: classes, inclusions = graph_classes._get_ISGCI() # long time (4s on sage.math, 2012)
773
"""
774
775
import os.path
776
from sage.all import save, load
777
from sage.misc.misc import SAGE_TMP, SAGE_DB
778
779
try:
780
open(os.path.join(SAGE_DB,_XML_FILE))
781
782
# Which copy is the most recent on the disk ?
783
if (os.path.getmtime(os.path.join(SAGE_DB,_XML_FILE)) >
784
os.path.getmtime(os.path.join(SAGE_SHARE,'graphs',_XML_FILE))):
785
786
filename = os.path.join(SAGE_DB,_XML_FILE)
787
788
else:
789
filename = os.path.join(SAGE_SHARE,'graphs',_XML_FILE)
790
791
except IOError as e:
792
filename = os.path.join(SAGE_SHARE,'graphs',_XML_FILE)
793
794
return self._parse_db(filename)
795
796
def show_all(self):
797
r"""
798
Prints all graph classes stored in ISGCI
799
800
EXAMPLE::
801
802
sage: graph_classes.show_all()
803
ID | name | type | smallgraph
804
----------------------------------------------------------------------------------------------------------------------
805
gc_309 | $K_4$--minor--free | base |
806
gc_541 | $N^*$ | base |
807
gc_215 | $N^*$--perfect | base |
808
gc_5 | $P_4$--bipartite | base |
809
gc_3 | $P_4$--brittle | base |
810
gc_6 | $P_4$--comparability | base |
811
gc_7 | $P_4$--extendible | base |
812
...
813
"""
814
classes = self.classes()
815
classes_list = classes.values()
816
817
# We want to print the different fields, and this dictionary stores the
818
# maximal number of characters of each field.
819
MAX = {
820
"ID" : 0,
821
"type" : 0,
822
"smallgraph": 0,
823
"name": 0
824
}
825
826
# We sort the classes alphabetically, though we would like to display the
827
# meaningful classes at the top of the list
828
classes_list.sort(key = lambda x:x.get("name","zzzzz")+"{0:4}".format(int(x["ID"].split('_')[1])))
829
830
# Maximum width of a field
831
MAX_LEN = 40
832
833
# Computing te max of each field with the database
834
for key in MAX:
835
MAX[key] = len(max(map(lambda x:str(x.get(key,"")),classes_list), key = len))
836
837
# At most MAX characters per field
838
for key, length in MAX.iteritems():
839
MAX[key] = min(length, MAX_LEN)
840
841
# Head of the table
842
print ("{0:"+str(MAX["ID"])+"} | {1:"+str(MAX["name"])+"} | {2:"+str(MAX["type"])+"} | {3:"+str(MAX["smallgraph"])+"}").format("ID", "name", "type", "smallgraph")
843
print "-"*(sum(MAX.values())+9)
844
845
# Entries
846
for entry in classes_list:
847
ID = entry.get("ID","")
848
name = entry.get("name","")
849
type = entry.get("type","")
850
smallgraph = entry.get("smallgraph","")
851
print ("{0:"+str(MAX["ID"])+"} | {1:"+str(MAX["name"])+"} | {2:"+str(MAX["type"])+"} | ").format(ID, name[:MAX_LEN], type[:MAX_LEN])+str(smallgraph)[:MAX_LEN]
852
853
graph_classes = GraphClasses()
854
855
# Any object added to this list should also appear in the class' documentation, at the top of the file.
856
graph_classes.BinaryTrees = GraphClass("BinaryTrees", "gc_847")
857
graph_classes.Bipartite = GraphClass("Bipartite", "gc_69")
858
graph_classes.Block = GraphClass("Block", "gc_93")
859
graph_classes.Chordal = GraphClass("Chordal", "gc_32")
860
graph_classes.Comparability = GraphClass("Comparability", "gc_72")
861
graph_classes.Gallai = GraphClass("Gallai", "gc_73")
862
graph_classes.Grid = GraphClass("Grid", "gc_464")
863
graph_classes.Interval = GraphClass("Interval", "gc_234")
864
graph_classes.Line = GraphClass("Line", "gc_249")
865
graph_classes.Modular = GraphClass("Modular", "gc_50")
866
graph_classes.Outerplanar = GraphClass("Outerplanar", "gc_110")
867
graph_classes.Perfect = GraphClass("Perfect", "gc_56")
868
graph_classes.Planar = GraphClass("Planar", "gc_43")
869
graph_classes.Split = GraphClass("Split", "gc_39")
870
graph_classes.Tree = GraphClass("Tree", "gc_342")
871
graph_classes.UnitDisk = GraphClass("UnitDisk", "gc_389")
872
graph_classes.UnitInterval = GraphClass("UnitInterval", "gc_299")
873
874