Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/graphs/isgci.py
4101 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:`~sage.graphs.generic_graph.GenericGraph.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:`~sage.graphs.generic_graph.GenericGraph.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 UniqueRepresentation
332
from sage.misc.unknown import Unknown
333
334
#*****************************************************************************
335
# Copyright (C) 2011 Nathann Cohen <[email protected]>
336
#
337
# Distributed under the terms of the GNU General Public License (GPL)
338
# http://www.gnu.org/licenses/
339
#*****************************************************************************
340
341
_XML_FILE = "isgci_sage.xml"
342
343
class GraphClass(SageObject, UniqueRepresentation):
344
r"""
345
An instance of this class represents a Graph Class, matching some entry in
346
the ISGCI database.
347
348
EXAMPLE:
349
350
Testing the inclusion of two classes::
351
352
sage: Chordal = graph_classes.Chordal
353
sage: Trees = graph_classes.Tree
354
sage: Trees <= Chordal
355
True
356
sage: Chordal <= Trees
357
Unknown
358
359
TEST::
360
361
sage: Trees >= Chordal
362
Unknown
363
sage: Chordal >= Trees
364
True
365
"""
366
def __init__(self, name, gc_id):
367
r"""
368
Class constructor
369
370
EXAMPLE::
371
372
sage: graph_classes.Chordal # indirect doctest
373
Chordal graphs
374
"""
375
self._name = name
376
self._gc_id = gc_id
377
378
def _repr_(self):
379
r"""
380
Returns a short description of the class
381
382
EXAMPLE::
383
384
sage: graph_classes.Chordal # indirect doctest
385
Chordal graphs
386
"""
387
return self._name+" graphs"
388
389
def __hash__(self):
390
r"""
391
Returns the class' ID hash
392
393
EXAMPLE::
394
395
sage: hash(graph_classes.Chordal) == hash(graph_classes.Chordal)
396
True
397
"""
398
return hash(self._gc_id)
399
400
def __le__(self, other):
401
r"""
402
<= operator
403
404
EXAMPLE::
405
406
sage: graph_classes.Chordal <= graph_classes.Tree
407
Unknown
408
"""
409
return other.__ge__(self)
410
411
def __ge__(self, other):
412
r"""
413
>= operator
414
415
EXAMPLE::
416
417
sage: graph_classes.Chordal >= graph_classes.Tree
418
True
419
"""
420
421
inclusion_digraph = GraphClasses().inclusion_digraph()
422
if inclusion_digraph.shortest_path(self._gc_id,other._gc_id) != []:
423
return True
424
else:
425
return Unknown
426
427
def __eq__(self, other):
428
r"""
429
== operator
430
431
EXAMPLE::
432
433
sage: graph_classes.Chordal == graph_classes.Tree
434
Unknown
435
"""
436
return self.__ge__(other) and other.__ge__(self)
437
438
def __lt__(self, other):
439
r"""
440
>, !=, and < operators
441
442
EXAMPLE::
443
444
sage: graph_classes.Chordal > graph_classes.Tree
445
Traceback (most recent call last):
446
...
447
Exception: Not Implemented
448
sage: graph_classes.Chordal < graph_classes.Tree
449
Traceback (most recent call last):
450
...
451
Exception: Not Implemented
452
sage: graph_classes.Chordal != graph_classes.Tree
453
Traceback (most recent call last):
454
...
455
Exception: Not Implemented
456
"""
457
raise Exception("Not Implemented")
458
459
__gt__ = __ne__ = __lt__
460
461
def description(self):
462
r"""
463
Prints the information of ISGCI about the current class.
464
465
EXAMPLE::
466
467
sage: graph_classes.Chordal.description()
468
Class of graphs : Chordal
469
-------------------------
470
type : base
471
ID : gc_32
472
name : chordal
473
<BLANKLINE>
474
Problems :
475
-----------
476
3-Colourability : Linear
477
Clique : Polynomial
478
Clique cover : Polynomial
479
Cliquewidth : Unbounded
480
Cliquewidth expression : NP-complete
481
Colourability : Linear
482
Domination : NP-complete
483
Independent set : Linear
484
Recognition : Linear
485
Treewidth : Polynomial
486
Weighted clique : Polynomial
487
Weighted independent set : Linear
488
"""
489
490
classes = GraphClasses().classes()
491
492
cls = classes[self._gc_id]
493
print "Class of graphs : "+self._name
494
print "-"*(len(self._name)+18)
495
496
for key, value in cls.iteritems():
497
if value != "" and key != "problems":
498
print "{0:30} : ".format(key),
499
print value
500
501
print "\nProblems :"
502
print "-"*11
503
for key, value in sorted(cls["problems"].iteritems()):
504
if value != "":
505
print "{0:30} : ".format(key),
506
print value
507
508
from sage.misc.cachefunc import cached_method
509
510
class GraphClasses(UniqueRepresentation):
511
def get_class(self, id):
512
r"""
513
Returns the class corresponding to the given id in the ISGCI database.
514
515
INPUT:
516
517
- ``id`` (string) -- the desired class' ID
518
519
.. seealso:
520
521
:meth:`~sage.graphs.isgci.GraphClasses.show_all`
522
523
EXAMPLE:
524
525
With an existing id::
526
527
sage: Cographs = graph_classes.get_class("gc_151")
528
sage: Cographs
529
cograph graphs
530
531
With a wrong id::
532
533
sage: graph_classes.get_class(-1)
534
Traceback (most recent call last):
535
...
536
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().
537
"""
538
classes = self.classes()
539
if id in classes:
540
c = classes[id]
541
542
if "name" in c and c["name"] != "":
543
name = c["name"]
544
else:
545
name = "class "+str(id)
546
547
return GraphClass(name, id)
548
else:
549
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().")
550
551
@cached_method
552
def classes(self):
553
r"""
554
Returns the graph classes, as a dictionary.
555
556
Upon the first call, this loads the database from the local
557
XML file. Subsequent calls are cached.
558
559
EXAMPLES::
560
561
sage: t = graph_classes.classes()
562
sage: type(t)
563
<type 'dict'>
564
sage: sorted(t["gc_151"].keys())
565
['ID', 'name', 'problems', 'type']
566
sage: t["gc_151"]['name']
567
'cograph'
568
sage: t["gc_151"]['problems']['Clique']
569
'Linear'
570
"""
571
classes, inclusions = self._get_ISGCI()
572
self.inclusions.set_cache(inclusions)
573
return classes
574
575
@cached_method
576
def inclusions(self):
577
r"""
578
Returns the graph class inclusions
579
580
OUTPUT:
581
582
a list of dictionaries
583
584
Upon the first call, this loads the database from the local
585
XML file. Subsequent calls are cached.
586
587
EXAMPLES::
588
589
sage: t = graph_classes.inclusions()
590
sage: type(t)
591
<type 'list'>
592
sage: t[0]
593
{'super': 'gc_2', 'sub': 'gc_1'}
594
"""
595
self.classes()
596
return self.inclusions()
597
598
@cached_method
599
def inclusion_digraph(self):
600
r"""
601
Returns the class inclusion digraph
602
603
Upon the first call, this loads the database from the local
604
XML file. Subsequent calls are cached.
605
606
EXAMPLES::
607
608
sage: g = graph_classes.inclusion_digraph(); g
609
Digraph on ... vertices
610
"""
611
classes = self.classes()
612
inclusions = self.inclusions()
613
614
from sage.graphs.digraph import DiGraph
615
inclusion_digraph = DiGraph()
616
inclusion_digraph.add_vertices(classes.keys())
617
618
for edge in inclusions:
619
if edge.get("confidence","") == "unpublished":
620
continue
621
inclusion_digraph.add_edge(edge['super'], edge['sub'])
622
623
return inclusion_digraph
624
625
def _download_db(self):
626
r"""
627
Downloads the current version of the ISGCI db
628
629
EXAMPLE::
630
631
sage: graph_classes._download_db() # Not tested -- requires internet
632
"""
633
634
from sage.misc.misc import SAGE_TMP, SAGE_ROOT
635
import urllib2
636
u = urllib2.urlopen('http://www.graphclasses.org/data.zip')
637
localFile = open(SAGE_TMP+'isgci.zip', 'w')
638
localFile.write(u.read())
639
localFile.close()
640
import os, zipfile
641
z = zipfile.ZipFile(SAGE_TMP+'isgci.zip')
642
643
# Save a systemwide updated copy whenever possible
644
645
try:
646
z.extract(_XML_FILE, SAGE_ROOT+"/data/graphs/")
647
except IOError:
648
z.extract(_XML_FILE, SAGE_TMP)
649
650
651
def _parse_db(self, xml_file):
652
r"""
653
Parses the ISGCI database and returns its content as Python objects.
654
655
INPUT:
656
657
- ``xml_file`` -- the name of an XML file containing the data from ISGCI
658
659
EXAMPLE::
660
661
sage: map(type, graph_classes._parse_db(SAGE_ROOT+"/data/graphs/isgci_sage.xml"))
662
[<type 'dict'>, <type 'list'>]
663
"""
664
import xml.dom.minidom
665
from xml.dom.minidom import Node
666
667
# This method is there to parse the XML file containing the ISGCI
668
# database. It is admittedly not very pretty, but it builds the class we
669
# want from the XML file and that's more or less all we ask it to do :-p
670
671
doc = xml.dom.minidom.parse(xml_file)
672
673
classes = {}
674
675
giveme = lambda x,y : str(x.getAttribute(y))
676
677
for node in doc.getElementsByTagName("GraphClass"):
678
ID = str(node.getAttribute("id"))
679
Dl = {}
680
smallgraph = []
681
Dl["ID"] = giveme(node, "id")
682
problems = {}
683
for node2 in node.childNodes:
684
name = str(node2.nodeName)
685
if name == "name":
686
Dl[name] = str(node2.childNodes[0].nodeValue)
687
688
elif name == "smallgraph":
689
smallgraph.append(str(node2.childNodes[0].nodeValue))
690
691
elif name == "problem":
692
problems[giveme(node2, "name")] = giveme(node2, "complexity")
693
694
Dl["problems"] = problems
695
696
if smallgraph:
697
Dl["smallgraph"] = smallgraph
698
699
if giveme(node, "type"):
700
Dl["type"] = giveme(node, "type")
701
702
703
classes[giveme(node, "id")] = Dl
704
705
inclusions = []
706
for node in doc.getElementsByTagName("incl"):
707
Dl = {}
708
for name in ["proper", "confidence", "super", "sub"]:
709
if giveme(node, name):
710
Dl[name] = giveme(node, name)
711
712
for node2 in node.childNodes:
713
name = str(node2.nodeName)
714
if name == "ref":
715
Dl[name] = str(node2.childNodes[0].nodeValue)
716
717
inclusions.append(Dl)
718
719
return classes, inclusions
720
721
def update_db(self):
722
r"""
723
Updates the ISGCI database by downloading the latest version from internet.
724
725
This method downloads the ISGCI database from the website
726
`GraphClasses.org <http://www.graphclasses.org/>`_. It then extracts the
727
zip file and parses its XML content.
728
729
Depending on the credentials of the user running Sage when this command
730
is run, one attempt is made at saving the result in Sage's directory so
731
that all users can benefit from it. If the credentials are not
732
sufficient, the XML file are saved instead in the user's directory (in
733
the SAGE_DB folder).
734
735
EXAMPLE::
736
737
sage: graph_classes.update_db() # Not tested -- requires internet
738
"""
739
from sage.misc.misc import SAGE_TMP, SAGE_ROOT, SAGE_LOCAL, SAGE_DB
740
741
self._download_db()
742
743
print "Database downloaded"
744
745
self.classes.clear_cache()
746
self.inclusions.clear_cache()
747
self.inclusion_digraph.clear_cache()
748
749
def _get_ISGCI(self):
750
r"""
751
Returns the contents of the ISGCI database.
752
753
This method is mostly for internal use, but often provides useful
754
information during debugging operations.
755
756
OUTPUT:
757
758
A pair ``(classes, inclusions)`` where ``classes`` is a dict of dict, and
759
``inclusions`` is a list of dicts.
760
761
.. NOTE::
762
763
This method returns the data contained in the most recent ISGCI database
764
present on the computer. See :meth:`update_db` to update the latter.
765
766
EXAMPLE::
767
768
sage: classes, inclusions = graph_classes._get_ISGCI()
769
"""
770
771
import os.path
772
from sage.all import save, load
773
from sage.misc.misc import SAGE_TMP, SAGE_ROOT, SAGE_LOCAL, SAGE_DB
774
775
try:
776
open(SAGE_DB+"/"+_XML_FILE)
777
778
# Which copy is the most recent on the disk ?
779
if (os.path.getmtime(SAGE_DB+"/"+_XML_FILE) >
780
os.path.getmtime(SAGE_ROOT+"/data/graphs/"+_XML_FILE)):
781
782
filename = SAGE_DB+"/"+_XML_FILE
783
784
else:
785
filename = SAGE_ROOT+"/data/graphs/"+_XML_FILE
786
787
except IOError as e:
788
filename = SAGE_ROOT+"/data/graphs/"+_XML_FILE
789
790
return self._parse_db(filename)
791
792
def show_all(self):
793
r"""
794
Prints all graph classes stored in ISGCI
795
796
EXAMPLE::
797
798
sage: graph_classes.show_all()
799
ID | name | type | smallgraph
800
----------------------------------------------------------------------------------------------------------------------
801
gc_309 | $K_4$--minor--free | base |
802
gc_541 | $N^*$ | base |
803
gc_215 | $N^*$--perfect | base |
804
gc_5 | $P_4$--bipartite | base |
805
gc_3 | $P_4$--brittle | base |
806
gc_6 | $P_4$--comparability | base |
807
gc_7 | $P_4$--extendible | base |
808
...
809
"""
810
classes = self.classes()
811
classes_list = classes.values()
812
813
# We want to print the different fields, and this dictionary stores the
814
# maximal number of characters of each field.
815
MAX = {
816
"ID" : 0,
817
"type" : 0,
818
"smallgraph": 0,
819
"name": 0
820
}
821
822
# We sort the classes alphabetically, though we would like to display the
823
# meaningful classes at the top of the list
824
classes_list.sort(key = lambda x:x.get("name","zzzzz")+"{0:4}".format(int(x["ID"].split('_')[1])))
825
826
# Maximum width of a field
827
MAX_LEN = 40
828
829
# Computing te max of each field with the database
830
for key in MAX:
831
MAX[key] = len(max(map(lambda x:str(x.get(key,"")),classes_list), key = len))
832
833
# At most MAX characters per field
834
for key, length in MAX.iteritems():
835
MAX[key] = min(length, MAX_LEN)
836
837
# Head of the table
838
print ("{0:"+str(MAX["ID"])+"} | {1:"+str(MAX["name"])+"} | {2:"+str(MAX["type"])+"} | {3:"+str(MAX["smallgraph"])+"}").format("ID", "name", "type", "smallgraph")
839
print "-"*(sum(MAX.values())+9)
840
841
# Entries
842
for entry in classes_list:
843
ID = entry.get("ID","")
844
name = entry.get("name","")
845
type = entry.get("type","")
846
smallgraph = entry.get("smallgraph","")
847
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]
848
849
graph_classes = GraphClasses()
850
851
# Any object added to this list should also appear in the class' documentation, at the top of the file.
852
graph_classes.BinaryTrees = GraphClass("BinaryTrees", "gc_847")
853
graph_classes.Bipartite = GraphClass("Bipartite", "gc_69")
854
graph_classes.Block = GraphClass("Block", "gc_93")
855
graph_classes.Chordal = GraphClass("Chordal", "gc_32")
856
graph_classes.Comparability = GraphClass("Comparability", "gc_72")
857
graph_classes.Gallai = GraphClass("Gallai", "gc_73")
858
graph_classes.Grid = GraphClass("Grid", "gc_464")
859
graph_classes.Interval = GraphClass("Interval", "gc_234")
860
graph_classes.Line = GraphClass("Line", "gc_249")
861
graph_classes.Modular = GraphClass("Modular", "gc_50")
862
graph_classes.Outerplanar = GraphClass("Outerplanar", "gc_110")
863
graph_classes.Perfect = GraphClass("Perfect", "gc_56")
864
graph_classes.Planar = GraphClass("Planar", "gc_43")
865
graph_classes.Split = GraphClass("Split", "gc_39")
866
graph_classes.Tree = GraphClass("Tree", "gc_342")
867
graph_classes.UnitDisk = GraphClass("UnitDisk", "gc_389")
868
graph_classes.UnitInterval = GraphClass("UnitInterval", "gc_299")
869
870