Ticket #11880: trac_11880isgcimorereviewnt.patch
File trac_11880isgcimorereviewnt.patch, 17.5 KB (added by , 9 years ago) 


sage/graphs/isgci.py
# HG changeset patch # User Nicolas M. Thiery <nthiery@users.sf.net> # Date 1331035007 3600 # Node ID 3b2ec16872f736785e2e3a3748f5841f2aa62ebe # Parent 8ecaf1bedc84712727f5c47863fabf88ac99e11d [mq]: trac_11880isgcireviewnt.patch diff git a/sage/graphs/isgci.py b/sage/graphs/isgci.py
a b interface which is easier to deal with t 18 18 rewritten many times until it stabilizes :) 19 19 20 20 Presently, it is possible to use this database through the variables and methods 21 present in the :obj:`graph_classes < sage.graphs.isgci.GraphClasses>` object.21 present in the :obj:`graph_classes <GraphClasses>` object. 22 22 For instance:: 23 23 24 24 sage: Trees = graph_classes.Tree … … And indeed, trees are chordal graphs. 47 47 Unknown 48 48 49 49 Given a graph class, one can obtain its associated information in the 50 ISGCI database with the :meth:`show 51 <sage.graphs.isgci.GraphClass.show>` method:: 50 ISGCI database with the :meth:`~GraphClass.show` method:: 52 51 53 52 sage: Chordal.show() 54 53 Class of graphs : Chordal … … ISGCI database with the :meth:`show 73 72 Recognition : Linear 74 73 75 74 It is possible to obtain the complete list of the classes stored in ISGCI by 76 calling the :meth:`show_all <sage.graphs.isgci.GraphClasses.show_all>` function 77 (beware  long output):: 75 calling the :meth:`~GraphClasses.show_all` method (beware  long output):: 78 76 79 77 sage: graph_classes.show_all() 80 78 ID  name  type  smallgraph … … calling the :meth:`show_all <sage.graphs 89 87 ... 90 88 91 89 Until a proper search method is implemented, this lets one find 92 classes which do not appear in :obj:`graph_classes.* <sage.graphs.isgci.GraphClasses>`.90 classes which do not appear in :obj:`graph_classes.* <GraphClasses>`. 93 91 94 92 To retrieve a class of graph from its ISGCI ID one may use 95 :meth:`graph_classes.get_class <GraphClasses.get_class>`::93 the :meth:`~GraphClasses.get_class` method:: 96 94 97 95 sage: GC = graph_classes.get_class("gc_5") 98 96 sage: GC … … To retrieve a class of graph from its IS 101 99 Predefined classes 102 100  103 101 104 :obj:`graph_classes < sage.graphs.isgci.GraphClasses>` currently lists the following graph classes102 :obj:`graph_classes <GraphClasses>` currently predefines the following graph classes 105 103 106 104 .. listtable:: 107 105 :widths: 20 30 … … Predefined classes 112 110 113 111 *  BinaryTrees 114 112 115  :meth:` BalancedTree <sage.graphs.graph_generators.GraphGenerators.BalancedTree>`,116 :meth:` is_tree <sage.graphs.generic_graph.GenericGraph.is_tree>`113  :meth:`~sage.graphs.graph_generators.GraphGenerators.BalancedTree`, 114 :meth:`~sage.graphs.generic_graph.GenericGraph.is_tree` 117 115 118 116 *  Bipartite 119 117 120  :meth:` BalancedTree <sage.graphs.graph_generators.GraphGenerators.BalancedTree>`,121 :meth:` is_bipartite <sage.graphs.graph.Graph.is_bipartite>`118  :meth:`~sage.graphs.graph_generators.GraphGenerators.BalancedTree`, 119 :meth:`~sage.graphs.graph.Graph.is_bipartite` 122 120 123 121 *  Block 124 122 125  :meth:` blocks_and_cut_vertices <sage.graphs.generic_graph.GenericGraph.blocks_and_cut_vertices>`,123  :meth:`~sage.graphs.generic_graph.GenericGraph.blocks_and_cut_vertices`, 126 124 127 125 *  Chordal 128 126 129  :meth:` is_chordal <sage.graphs.generic_graph.GenericGraph.is_chordal>`127  :meth:`~sage.graphs.generic_graph.GenericGraph.is_chordal` 130 128 131 129 *  Comparability 132 130  133 131 134 132 *  Gallai 135 133 136  :meth:` is_gallai_tree <sage.graphs.generic_graph.GenericGraph.is_gallai_tree>`134  :meth:`~sage.graphs.generic_graph.GenericGraph.is_gallai_tree` 137 135 138 136 *  Grid 139 137 140  :meth:` Grid2dGraph <sage.graphs.graph_generators.GraphGenerators.Grid2dGraph>`,141 :meth:` GridGraph <sage.graphs.graph_generators.GraphGenerators.GridGraph>`138  :meth:`~sage.graphs.graph_generators.GraphGenerators.Grid2dGraph`, 139 :meth:`~sage.graphs.graph_generators.GraphGenerators.GridGraph` 142 140 143 141 *  Interval 144 142 145  :meth:` RandomInterval <sage.graphs.graph_generators.GraphGenerators.RandomInterval>`,146 :meth:` IntervalGraph <sage.graphs.graph_generators.GraphGenerators.IntervalGraph>`,147 :meth:` is_interval <sage.graphs.generic_graph.GenericGraph.is_interval>`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` 148 146 149 147 *  Line 150 148 151  :meth:` line_graph_forbidden_subgraphs <sage.graphs.graph_generators.GraphGenerators.line_graph_forbidden_subgraphs>`,152 :meth:` is_line_graph <sage.graphs.graph.Graph.is_line_graph>`149  :meth:`~sage.graphs.graph_generators.GraphGenerators.line_graph_forbidden_subgraphs`, 150 :meth:`~sage.graphs.graph.Graph.is_line_graph` 153 151 154 152 *  Modular 155 153 156  :meth:` modular_decomposition <sage.graphs.graph.Graph.modular_decomposition>`154  :meth:`~sage.graphs.graph.Graph.modular_decomposition` 157 155 158 156 *  Outerplanar 159 157 160  :meth:` is_circular_planar <sage.graphs.generic_graph.GenericGraph.is_circular_planar>`158  :meth:`~sage.graphs.generic_graph.GenericGraph.is_circular_planar` 161 159 162 160 *  Perfect 163 161 164  :meth:` is_perfect <sage.graphs.graph.Graph.is_perfect>`162  :meth:`~sage.graphs.graph.Graph.is_perfect` 165 163 166 164 *  Planar 167 165 168  :meth:` is_planar <sage.graphs.generic_graph.GenericGraph.is_planar>`166  :meth:`~sage.graphs.generic_graph.GenericGraph.is_planar` 169 167 170 168 *  Split 171 169 172  :meth:` is_split <sage.graphs.graph.Graph.is_split>`170  :meth:`~sage.graphs.graph.Graph.is_split` 173 171 174 172 *  Tree 175 173 176  :meth:` trees <sage.graphs.graph_generators.GraphGenerators.trees>`,177 :meth:` is_tree <sage.graphs.generic_graph.GenericGraph.is_tree>`174  :meth:`~sage.graphs.graph_generators.GraphGenerators.trees`, 175 :meth:`~sage.graphs.generic_graph.GenericGraph.is_tree` 178 176 179 177 *  UnitDisk 180  :meth:` IntervalGraph <sage.graphs.graph_generators.GraphGenerators.IntervalGraph>`,178  :meth:`~sage.graphs.graph_generators.GraphGenerators.IntervalGraph`, 181 179 182 180 *  UnitInterval 183 181 184  :meth:` is_interval <sage.graphs.generic_graph.GenericGraph.is_interval>`182  :meth:`~sage.graphs.generic_graph.GenericGraph.is_interval` 185 183 186 184 Sage's view of ISGCI 187 185  188 186 189 187 The database is stored by Sage in two ways. 190 188 191 **The classes :** the list of all graph classes and their properties is stored 192 in a huge dictionary (see :meth:`classes() 193 <sage.graphs.isgci.GraphClasses.classes>`). Below is what Sage knows of 194 ``gc_249``:: 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``:: 195 192 196 193 sage: graph_classes.classes()['gc_249'] 197 {'problems': 198 {'Independent set': 'Polynomial', 199 'Treewidth': 'Unknown', 200 'Weighted independent set': 'Polynomial', 201 'Cliquewidth expression': 'NPcomplete', 202 'Weighted clique': 'Polynomial', 203 'Clique cover': 'Unknown', 204 'Domination': 'NPcomplete', 205 'Clique': 'Polynomial', 206 'Colourability': 'NPcomplete', 207 'Cliquewidth': 'Unbounded', 208 '3Colourability': 'NPcomplete', 209 'Recognition': 'Linear'}, 210 'type': 'base', 211 'ID': 'gc_249', 194 {'problems': 195 {'Independent set': 'Polynomial', 196 'Treewidth': 'Unknown', 197 'Weighted independent set': 'Polynomial', 198 'Cliquewidth expression': 'NPcomplete', 199 'Weighted clique': 'Polynomial', 200 'Clique cover': 'Unknown', 201 'Domination': 'NPcomplete', 202 'Clique': 'Polynomial', 203 'Colourability': 'NPcomplete', 204 'Cliquewidth': 'Unbounded', 205 '3Colourability': 'NPcomplete', 206 'Recognition': 'Linear'}, 207 'type': 'base', 208 'ID': 'gc_249', 212 209 'name': 'line'} 213 210 214 **The class inclusion digraph :** Sage remembers the class inclusions through 215 the inclusion digraph (see :meth:`inclusion_digraph() 216 <sage.graphs.isgci.GraphClasses.inclusion_digraph>`). Its nodes are ID of ISGCI 217 classes:: 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:: 218 214 219 sage: d = graph_classes.inclusion_digraph() 220 sage: d.vertices()[10:] 215 sage: d = graph_classes.inclusion_digraph() 216 sage: d.vertices()[10:] 221 217 ['gc_990', 'gc_991', 'gc_992', 'gc_993', 'gc_994', 'gc_995', 'gc_996', 'gc_997', 'gc_998', 'gc_999'] 222 218 223 219 An arc from ``gc1`` to ``gc2`` means that ``gc1`` is a superclass of … … result :: 241 237 [perfect graphs, unimodular graphs, bipartite graphs] 242 238 243 239 What ISGCI knows is that perfect graphs contain unimodular graph which contain 244 bipartite graphs. And sobipartite graphs are perfect !240 bipartite graphs. Therefore bipartite graphs are perfect ! 245 241 246 242 .. note:: 247 243 248 244 The inclusion digraph is **NOT ACYCLIC**. Indeed, several entries 249 245 exist in the ISGCI database which represent the same graph class, 250 for instance Perfect graphs and Berge graphs 246 for instance Perfect graphs and Berge graphs:: 251 247 252 248 sage: graph_classes.inclusion_digraph().is_directed_acyclic() 253 249 False … … bipartite graphs. And so bipartite graph 265 261 Information for developpers 266 262  267 263 268 * The database is not *so* large, but enough to avoid loading it at Sage's269 startup. This is the reason why the methods :meth:`classes()270 <sage.graphs.isgci.GraphClasses.classes>` and :meth:`inclusion_digraph()271 <sage.graphs.isgci.GraphClasses.inclusion_digraph>` are cached.264 * The database is loaded not *so* large, but it is still preferable to 265 only load it on demand. This is achieved through the cached methods 266 :meth:`~sage.graphs.isgci.GraphClasses.classes` and 267 :meth:`~sage.graphs.isgci.GraphClasses.inclusion_digraph`. 272 268 273 * Once the database has been accessed once, the information is extracted from 274 the ``.sobj`` files in which it is stored and their information is stored in 275 the following variables : 269 * Upon the first access to the database, the information is extracted 270 from the ``.sobj`` files and stored in the following variables : 276 271 277 272 * ``sage.graphs.isgci._classes`` (dictionary) 278 273 * ``sage.graphs.isgci._inclusions`` (list of dictionaries) 279 274 * ``sage.graphs.isgci._inclusion_digraph`` (DiGraph) 280 275 281 Note that the digraph is only built if necessary (for instance if the user282 t riedto compare two classes).276 Note that the digraph is only built if necessary (for instance if 277 the user tries to compare two classes). 283 278 284 279 .. todo:: 285 280 … … Information for developpers 289 284 return ``False``, and implement strict inclusions. 290 285 291 286 * Implement a proper search method for the classes not listed in 292 :obj:`graph_classes < sage.graphs.isgci.GraphClasses>`287 :obj:`graph_classes <GraphClasses>` 293 288 294 289 .. seealso: :func:`sage.graphs.isgci.show_all`. 295 290 296 291 * Some of the graph classes appearing in :obj:`graph_classes 297 < sage.graphs.isgci.GraphClasses>` already have a recognition292 <GraphClasses>` already have a recognition 298 293 algorithm implemented in Sage. It would be so nice to be able to 299 294 write ``g in Trees``, ``g in Perfect``, ``g in Chordal``, ... :) 300 295 … … class GraphClass(SageObject, UniqueRepre 366 361 self._name = name 367 362 self._gc_id = gc_id 368 363 369 def _ _repr__(self):364 def _repr_(self): 370 365 r""" 371 366 Returns a short description of the class 372 367 373 368 EXAMPLE:: 374 369 375 sage: graph_classes.Chordal 370 sage: graph_classes.Chordal # indirect doctest 376 371 Chordal graphs 377 372 """ 378 373 return self._name+" graphs" … … class GraphClass(SageObject, UniqueRepre 451 446 from sage.misc.cachefunc import cached_method 452 447 453 448 class GraphClasses(UniqueRepresentation): 454 def __init__(self):455 self._classes = {}456 self._inclusions = []457 self._inclusion_digraph = None458 459 449 def get_class(self, id): 460 450 r""" 461 451 Returns the class corresponding to the given id in the ISGCI database. … … class GraphClasses(UniqueRepresentation) 466 456 467 457 .. seealso: 468 458 469 :meth:` show_all <sage.graphs.isgci.GraphClasses.show_all>`459 :meth:`~sage.graphs.isgci.GraphClasses.show_all` 470 460 471 461 EXAMPLE: 472 462 … … class GraphClasses(UniqueRepresentation) 499 489 @cached_method 500 490 def classes(self): 501 491 r""" 502 Returns the graph classes as a dictionary.492 Returns the graph classes, as a dictionary. 503 493 504 If the database it has not been built from the local sobj files, this 505 methods load it. 494 Upon the first call, this loads the database from the local 495 sobj files. Subsequent calls are cached. 496 497 EXAMPLES:: 498 499 sage: t = graph_classes.classes() 500 sage: type(t) 501 <type 'dict'> 502 sage: sorted(t["gc_151"].keys()) 503 ['ID', 'name', 'problems', 'type'] 504 sage: t["gc_151"]['name'] 505 'cograph' 506 sage: t["gc_151"]['problems']['Clique'] 507 'Linear' 506 508 """ 507 if self._classes == {}: 508 self._classes, self._inclusions = self._get_ISGCI() 509 classes, inclusions = self._get_ISGCI() 510 self.inclusions.set_cache(inclusions) 511 return classes 509 512 510 return self._classes 513 @cached_method 514 def inclusions(self): 515 r""" 516 Returns the graph class inclusions 517 518 OUTPUT: 519 520 a list of dictionaries 521 522 Upon the first call, this loads the database from the local 523 sobj files. Subsequent calls are cached. 524 525 EXAMPLES:: 526 527 sage: t = graph_classes.inclusions() 528 sage: type(t) 529 <type 'list'> 530 sage: t[0] 531 {'super': 'gc_2', 'sub': 'gc_1'} 532 """ 533 self.classes() 534 return self.inclusions() 511 535 512 536 @cached_method 513 537 def inclusion_digraph(self): 514 538 r""" 515 539 Returns the class inclusion digraph 516 540 517 If the database it has not been built from the local sobj files, this 518 methods load it. 541 Upon the first call, this loads the database from the local 542 sobj files. Subsequent calls are cached. 543 544 EXAMPLES:: 545 546 sage: g = graph_classes.inclusion_digraph(); g 547 Digraph on ... vertices 519 548 """ 520 if not (self._inclusion_digraph is None): 521 return 522 523 classes = self.classes() 549 classes = self.classes() 550 inclusions = self.inclusions() 524 551 525 552 from sage.graphs.digraph import DiGraph 526 self._inclusion_digraph = DiGraph()527 self._inclusion_digraph.add_vertices(classes.keys())553 inclusion_digraph = DiGraph() 554 inclusion_digraph.add_vertices(classes.keys()) 528 555 529 for edge in self._inclusions:556 for edge in inclusions: 530 557 if edge.get("confidence","") == "unpublished": 531 558 continue 559 inclusion_digraph.add_edge(edge['super'], edge['sub']) 532 560 533 self._inclusion_digraph.add_edge(edge['super'], edge['sub']) 534 535 self._inclusions = [] 536 537 return self._inclusion_digraph 561 return inclusion_digraph 538 562 539 563 def _download_db(self): 540 564 r""" … … class GraphClasses(UniqueRepresentation) 648 672 649 673 print "Database downloaded" 650 674 651 self._classes, self._inclusions = self._create_db()675 classes, inclusions = self._create_db() 652 676 653 677 print "XML file converted into Python dictionaries" 654 678 655 679 from sage.all import save 656 680 657 681 # Trying to save to Sage's directory 682 # TODO: get rid of duplication 658 683 try: 659 save(self._classes, SAGE_ROOT+'/data/graphs/isgci_classes.sobj') 660 save(self._inclusions, SAGE_ROOT+'/data/graphs/isgci_inclusions.sobj') 661 self._inclusions = self._inclusion_digraph = None 662 self._classes = {} 684 save(classes, SAGE_ROOT+'/data/graphs/isgci_classes.sobj') 685 save(inclusions, SAGE_ROOT+'/data/graphs/isgci_inclusions.sobj') 686 self.classes.clear_cache() 687 self.inclusions.clear_cache() 688 self.inclusion_digraph.clear_cache() 663 689 print "Database saved to .sobj files in "+SAGE_ROOT+'/data/graphs/' 664 690 return 665 691 … … class GraphClasses(UniqueRepresentation) 667 693 # TODO: improve! 668 694 print "Could not save save database in "+SAGE_ROOT+'/data/graphs/' 669 695 print "Now attempting to save the files to "+str(SAGE_DB) 670 pass671 696 672 697 # Trying to save to the user's home directory 673 save(self._classes, SAGE_DB+"/isgci_classes.sobj") 674 save(self._inclusions, SAGE_DB+"/isgci_inclusions.sobj") 675 self._inclusions = self._inclusion_digraph = None 676 self._classes = {} 698 save(classes, SAGE_DB+"/isgci_classes.sobj") 699 save(inclusions, SAGE_DB+"/isgci_inclusions.sobj") 700 self.classes.clear_cache() 701 self.inclusions.clear_cache() 702 self.inclusion_digraph.clear_cache() 677 703 print "Database saved to .sobj files in "+SAGE_DB 678 704 679 705 def _get_ISGCI(self): … … class GraphClasses(UniqueRepresentation) 691 717 .. NOTE:: 692 718 693 719 This method returns the data contained in the most recent ISGCI database 694 present on the computer. See : func:`update_db` to update the latter.720 present on the computer. See :meth:`update_db` to update the latter. 695 721 696 722 EXAMPLE:: 697 723