Ticket #11880: trac_11880object_oriented.patch
File trac_11880object_oriented.patch, 24.8 KB (added by , 8 years ago) 


doc/en/reference/misc.rst
# HG changeset patch # User Nathann Cohen <nathann.cohen@gmail.com> # Date 1329764537 3600 # Node ID f48c07be6d0ac463c2103bd830cce45945a9b0fd # Parent d84d80415d829517538b92a21dfb3db973cd4d80 ISGCI database  updating the design : from functions to methods diff git a/doc/en/reference/misc.rst b/doc/en/reference/misc.rst
a b 35 35 sage/misc/lazy_import 36 36 sage/misc/log 37 37 sage/misc/persist 38 sage/misc/unknown 38 39 sage/misc/func_persist 39 40 sage/misc/sage_eval 40 41 sage/misc/random_testing 
sage/graphs/isgci.py
diff git a/sage/graphs/isgci.py b/sage/graphs/isgci.py
a b 13 13 How to use it? 14 14  15 15 16 The current limited aim of this module is to provide a pure 17 Sage/Python interface which is easier to deal with than a XML file. I 18 hope it will berewritten many times until it stabilizes :)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 19 20 20 Presently, it is possible to use this database through the variables and methods 21 21 present in the :obj:`graph_classes <sage.graphs.isgci.GraphClasses>` object. … … 24 24 sage: Trees = graph_classes.Tree 25 25 sage: Chordal = graph_classes.Chordal 26 26 27 It is then possible to check the inclusion of classes inside of 28 others, if theinformation is available in the database::27 It is then possible to check the inclusion of classes inside of others, if the 28 information is available in the database:: 29 29 30 30 sage: Trees <= Chordal 31 31 True … … 34 34 35 35 .. WARNING:: 36 36 37 At the moment, only *positive* answers are guaranteed correct! 37 The ISGCI database is not allknowing, 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>`). 38 40 39 A *negative* answer to ``A <= B`` only means that ISGCI can't40 deduce from the information in its database that ``A`` is a41 subclass of ``B`` nor that it is not. For the reverse inclusion42 between Trees and Chordal graphs the answer is correct though::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:: 43 45 44 sage: Chordal <= Trees 45 False 46 47 TODO: what about using a Troolean? 48 49 TODO: what about strict inclusion? 46 sage: graph_classes.Chordal <= graph_classes.Tree 47 Unknown 50 48 51 49 Given a graph class, one can obtain its associated information in the 52 50 ISGCI database with the :meth:`show … … 74 72 3Colourability : Linear 75 73 Recognition : Linear 76 74 77 It is possible to obtain the complete list of the classes stored in 78 ISGCI by calling the :func:`sage.graphs.isgci.show_all` function75 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 79 77 (beware  long output):: 80 78 81 sage: sage.graphs.isgci.show_all()79 sage: graph_classes.show_all() 82 80 ID  name  type  smallgraph 83 81  84 82 gc_309  $K_4$minorfree  base  … … 91 89 ... 92 90 93 91 Until a proper search method is implemented, this lets one find 94 classes which are not listed in :obj:`graph_classes <sage.graphs.isgci.GraphClasses>`. 95 96 TODO: get_class_from_id is currently a method of graph_classes whereas 97 show_all is a function of this module. Should show_all be moved to 98 graph_classes for consistency? 92 classes which do not appear in:obj:`graph_classes.* <sage.graphs.isgci.GraphClasses>`. 99 93 100 94 To retrieve a class of graph from its ISGCI ID one may use 101 :meth:`graph_classes.get_class _from_id <GraphClasses.get_class_from_id>`::95 :meth:`graph_classes.get_class <GraphClasses.get_class>`:: 102 96 103 sage: GC = graph_classes.get_class _from_id("gc_5")97 sage: GC = graph_classes.get_class("gc_5") 104 98 sage: GC 105 Graph class : $P_4$bipartite99 $P_4$bipartite graphs 106 100 107 101 Predefined classes 108 102  109 103 110 104 :obj:`graph_classes <sage.graphs.isgci.GraphClasses>` currently lists the following graph classes 111 105 112 TODO: use .. seealso:: in all entries of this list?113 114 106 .. listtable:: 115 107 :widths: 20 30 116 108 :headerrows: 1 … … 136 128 137 129  :meth:`is_chordal <sage.graphs.generic_graph.GenericGraph.is_chordal>` 138 130 139 *  Clique140 141  :meth:`CompleteGraph <sage.graphs.graph_generators.GraphGenerators.CompleteGraph>`,142 :meth:`is_clique <sage.graphs.generic_graph.GenericGraph.is_clique>`143 144 131 *  Comparability 145 132  146 133 … … 190 177 :meth:`is_tree <sage.graphs.generic_graph.GenericGraph.is_tree>` 191 178 192 179 *  UnitDisk 193  180  :meth:`IntervalGraph <sage.graphs.graph_generators.GraphGenerators.IntervalGraph>`, 194 181 195 182 *  UnitInterval 196 183 197 184  :meth:`is_interval <sage.graphs.generic_graph.GenericGraph.is_interval>` 198 185 186 Sage's view of ISGCI 187  188 189 The database is stored by Sage in two ways. 190 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``:: 195 196 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', 212 'name': 'line'} 213 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:: 218 219 sage: d = graph_classes.inclusion_digraph() 220 sage: d.vertices()[10:] 221 ['gc_990', 'gc_991', 'gc_992', 'gc_993', 'gc_994', 'gc_995', 'gc_996', 'gc_997', 'gc_998', 'gc_999'] 222 223 An arc from ``gc1`` to ``gc2`` means that ``gc1`` is a superclass of 224 ``gc2``. This being said, not all edges are stored ! To ensure that a given 225 class is included in another one, we have to check whether there is in the 226 digraph a ``path`` from the first one to the other:: 227 228 sage: bip_id = graph_classes.Bipartite._gc_id 229 sage: perfect_id = graph_classes.Perfect._gc_id 230 sage: d.has_edge(perfect_id, bip_id) 231 False 232 sage: d.distance(perfect_id, bip_id) 233 2 234 235 Hence bipartite graphs are perfect graphs. We can see how ISGCI obtains this 236 result :: 237 238 sage: d.shortest_path(perfect_id, bip_id) 239 ['gc_56', 'gc_76', 'gc_69'] 240 sage: map(graph_classes.get_class, d.shortest_path(perfect_id, bip_id)) 241 [perfect graphs, unimodular graphs, bipartite graphs] 242 243 What ISGCI knows is that perfect graphs contain unimodular graph which contain 244 bipartite graphs. And so bipartite graphs are perfect ! 245 246 .. note:: 247 248 The inclusion digraph is **NOT ACYCLIC**. Indeed, several entries 249 exist in the ISGCI database which represent the same graph class, 250 for instance Perfect graphs and Berge graphs :: 251 252 sage: graph_classes.inclusion_digraph().is_directed_acyclic() 253 False 254 sage: Berge = graph_classes.get_class("gc_274"); Berge 255 Berge graphs 256 sage: Perfect = graph_classes.get_class("gc_56"); Perfect 257 perfect graphs 258 sage: Berge <= Perfect 259 True 260 sage: Perfect <= Berge 261 True 262 sage: Perfect == Berge 263 True 199 264 200 265 Information for developpers 201 266  202 267 203 * The database is not *so* large, but enough to prevent it from being loaded at 204 Sage's startup. The internal methods using the database should often be 205 preceded by a call to :meth:`_load_ISGCI_if_not_loaded 206 <sage.graphs.isgci._load_ISGCI_if_not_loaded>` or to 207 :meth:`_build_inclusion_digraph_if_not_built 208 <sage.graphs.isgci._build_inclusion_digraph_if_not_built>`. 268 * The database is not *so* large, but enough to avoid loading it at Sage's 269 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. 209 272 210 273 * Once the database has been accessed once, the information is extracted from 211 the ``.sobj`` files in which it is stored and their information can be212 accessed bythe following variables :274 the ``.sobj`` files in which it is stored and their information is stored in 275 the following variables : 213 276 214 * ``sage.graphs.isgci. classes`` (dictionary)215 * ``sage.graphs.isgci. inclusions`` (list of dictionaries)216 * ``sage.graphs.isgci. inclusion_digraph`` (DiGraph)277 * ``sage.graphs.isgci._classes`` (dictionary) 278 * ``sage.graphs.isgci._inclusions`` (list of dictionaries) 279 * ``sage.graphs.isgci._inclusion_digraph`` (DiGraph) 217 280 218 281 Note that the digraph is only built if necessary (for instance if the user 219 282 tried to compare two classes). 220 283 221 * The ``DiGraph`` object ``sage.graphs.isgci.inclusion_digraph`` has for vertex set222 the ID of the graph classes. This digraph contains an edge `uv` if the graph223 class represented by `u` is larger (not necessarily strictly) than the one224 represented by `v`.225 226 227 TODO: this is useful information for the user too. Move it out of228 the developpers section?229 230 Though it represents inclusions of sets, this ``DiGraph`` is **NOT231 ACYCLIC**::232 233 sage: sage.graphs.isgci.inclusion_digraph.is_directed_acyclic()234 False235 236 Indeed, several entries exist in the ISGCI database which represent237 the same graph class::238 239 sage: Berge = graph_classes.get_class_from_id("gc_274"); Berge240 Graph class : Berge241 sage: Perfect = graph_classes.get_class_from_id("gc_56"); Perfect242 Graph class : perfect243 sage: Berge <= Perfect244 True245 sage: Perfect <= Berge246 True247 248 In other words::249 250 sage: Perfect == Berge251 True252 253 284 .. todo:: 254 285 255 286 Technical things: 256 287 288 * Query the database for noninclusion results so that comparisons can 289 return ``False``, and implement strict inclusions. 290 257 291 * Implement a proper search method for the classes not listed in 258 292 :obj:`graph_classes <sage.graphs.isgci.GraphClasses>` 259 293 … … 262 296 * Some of the graph classes appearing in :obj:`graph_classes 263 297 <sage.graphs.isgci.GraphClasses>` already have a recognition 264 298 algorithm implemented in Sage. It would be so nice to be able to 265 write ``g in Trees``, ``g in Perfect``, ``g in Chordal``, ... `:)`299 write ``g in Trees``, ``g in Perfect``, ``g in Chordal``, ... :) 266 300 267 301 Longterm stuff: 268 302 … … 282 316 that a given graph is, say, a tree or a planar graph, and use a 283 317 specialized algorithm for finding an independent set. 284 318 285 286 319 AUTHORS: 287 320  288 321 … … 295 328 296 329 from sage.structure.sage_object import SageObject 297 330 from sage.structure.unique_representation import UniqueRepresentation 298 299 classes = {} 300 inclusions = [] 301 inclusion_digraph = None 331 from sage.misc.unknown import Unknown 302 332 303 333 #***************************************************************************** 304 334 # Copyright (C) 2011 Nathann Cohen <nathann.cohen@gmail.com> … … 323 353 sage: Trees <= Chordal 324 354 True 325 355 sage: Chordal <= Trees 326 False356 Unknown 327 357 328 358 TEST:: 329 359 330 360 sage: Trees >= Chordal 331 False361 Unknown 332 362 sage: Chordal >= Trees 333 363 True 334 364 """ … … 343 373 EXAMPLE:: 344 374 345 375 sage: graph_classes.Chordal 346 Graph class : Chordal376 Chordal graphs 347 377 """ 348 378 return self._name+" graphs" 349 379 … … 358 388 359 389 def __ge__(self, other): 360 390 inclusion_digraph = GraphClasses().inclusion_digraph() 361 return (inclusion_digraph.shortest_path(self._gc_id,other._gc_id) != []) 391 if inclusion_digraph.shortest_path(self._gc_id,other._gc_id) != []: 392 return True 393 else: 394 return Unknown 362 395 363 396 def __eq__(self, other): 364 397 return self.__ge__(other) and other.__ge__(self) … … 396 429 3Colourability : Linear 397 430 Recognition : Linear 398 431 """ 399 global classes 400 _load_ISGCI_if_not_loaded()432 433 classes = GraphClasses().classes() 401 434 402 435 cls = classes[self._gc_id] 403 436 print "Class of graphs : "+self._name … … 415 448 print "{0:30} : ".format(key), 416 449 print value 417 450 418 from sage.misc.cachefunc import cached_ function451 from sage.misc.cachefunc import cached_method 419 452 420 453 class GraphClasses(UniqueRepresentation): 421 def get_class_from_id(self, ID): 454 def __init__(self): 455 self._classes = {} 456 self._inclusions = [] 457 self._inclusion_digraph = None 458 459 def get_class(self, id): 422 460 r""" 423 Returns the class corresponding to the given ID in the ISGCI database. 461 Returns the class corresponding to the given id in the ISGCI database. 462 463 INPUT: 464 465  ``id`` (string)  the desired class' ID 466 467 .. seealso: 468 469 :meth:`show_all <sage.graphs.isgci.GraphClasses.show_all>` 424 470 425 471 EXAMPLE: 426 472 427 With an existing ID::473 With an existing id:: 428 474 429 sage: Cographs = graph_classes.get_class _from_id("gc_151")475 sage: Cographs = graph_classes.get_class("gc_151") 430 476 sage: Cographs 431 Graph class : cograph477 cograph graphs 432 478 433 With a wrong ID::479 With a wrong id:: 434 480 435 sage: graph_classes.get_class _from_id(1)481 sage: graph_classes.get_class(1) 436 482 Traceback (most recent call last): 437 483 ... 438 ValueError: The given class ID does not exist in the ISGCI database. Is the db too old ? You can update it with sage.graphs.isgci.update_db(). 439 440 441 TODO: rename ot ``graph_classes.get_class(id = "gc_151")``? 442 or even ``graph_classes.Class(id = "gc_151")``? 484 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(). 443 485 """ 444 global classes 445 _load_ISGCI_if_not_loaded() 446 if ID in classes: 447 c = classes[ID] 486 classes = self.classes() 487 if id in classes: 488 c = classes[id] 448 489 449 490 if "name" in c and c["name"] != "": 450 491 name = c["name"] 451 492 else: 452 name = "class "+str( ID)493 name = "class "+str(id) 453 494 454 return GraphClass(name, ID) 495 return GraphClass(name, id) 496 else: 497 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().") 455 498 456 else: 457 raise ValueError("The given class ID does not exist in the ISGCI database. Is the db too old ? You can update it with sage.graphs.isgci.update_db().") 499 @cached_method 500 def classes(self): 501 r""" 502 Returns the graph classes as a dictionary. 458 503 459 @cached_function460 def classes():461 global classes462 _load_ISGCI_if_not_loaded()463 return classes504 If the database it has not been built from the local sobj files, this 505 methods load it. 506 """ 507 if self._classes == {}: 508 self._classes, self._inclusions = self._get_ISGCI() 464 509 465 @cached_function 466 def inclusion_digraph(): 467 global inclusion_digraph, classes 468 _build_inclusion_digraph_if_not_built() 469 return inclusion_digraph 510 return self._classes 470 511 471 def _download_db(): 512 @cached_method 513 def inclusion_digraph(self): 514 r""" 515 Returns the class inclusion digraph 516 517 If the database it has not been built from the local sobj files, this 518 methods load it. 519 """ 520 if not (self._inclusion_digraph is None): 521 return 522 523 classes = self.classes() 524 525 from sage.graphs.digraph import DiGraph 526 self._inclusion_digraph = DiGraph() 527 self._inclusion_digraph.add_vertices(classes.keys()) 528 529 for edge in self._inclusions: 530 if edge.get("confidence","") == "unpublished": 531 continue 532 533 self._inclusion_digraph.add_edge(edge['super'], edge['sub']) 534 535 self._inclusions = [] 536 537 return self._inclusion_digraph 538 539 def _download_db(self): 472 540 r""" 473 541 Downloads the current version of the ISGCI db 474 542 475 543 EXAMPLE:: 476 544 477 sage: sage.graphs.isgci._download_db() # Not tested  requires internet545 sage: graph_classes._download_db() # Not tested  requires internet 478 546 """ 479 547 480 548 from sage.misc.misc import SAGE_TMP … … 487 555 z = zipfile.ZipFile(SAGE_TMP+'isgci.zip') 488 556 z.extract(_XML_FILE, SAGE_TMP) 489 557 490 def _create_db( ):558 def _create_db(self): 491 559 r""" 492 560 Parses the ISGCI database and returns its content as Python objects. 493 561 494 562 EXAMPLE:: 495 563 496 sage: sage.graphs.isgci._create_db() # Not tested  requires internet564 sage: graph_classes._create_db() # Not tested  requires internet 497 565 """ 498 566 from sage.misc.misc import SAGE_TMP 499 567 import xml.dom.minidom … … 553 621 554 622 return classes, inclusions 555 623 556 def update_db( verbose = False):624 def update_db(self): 557 625 r""" 558 626 Updates the ISGCI database by downloading the latest version from internet. 559 627 … … 568 636 command is run, one attempt is made at saving the result in Sage's 569 637 directory so that all users can benefit from it. If the 570 638 credentials are not sufficient, the ``.sobj`` files are saved 571 instead in the user's directory. #TODO: be more specific about where in the user's directory? 572 573 INPUT: 574 575  ``verbose``  a boolean (default: False); whether to output 576 information of the update process 639 instead in the user's directory (in the SAGE_DB folder). 577 640 578 641 EXAMPLE:: 579 642 580 sage: sage.graphs.isgci.update_db() # Not tested  requires internet643 sage: graph_classes.update_db() # Not tested  requires internet 581 644 """ 582 645 from sage.misc.misc import SAGE_TMP, SAGE_ROOT, SAGE_LOCAL, SAGE_DB 583 global classes, inclusions, inclusion_digraph584 646 585 try: 586 _download_db() 587 except: 588 # TODO: as such, the user won't get the, probably more 589 # informative, error message thrown by download_db. What about 590 # not catching it? Or at least retransmitting the error 591 # message? 592 raise Exception("There has been a problem while downloading or unzipping the ISGCI database O_o") 647 self._download_db() 593 648 649 print "Database downloaded" 594 650 595 if verbose: 596 print "Database downloaded" 651 self._classes, self._inclusions = self._create_db() 597 652 598 classes, inclusions = _create_db() 599 600 if verbose: 601 print "XML file converted to Python dictionaries" 602 653 print "XML file converted into Python dictionaries" 603 654 604 655 from sage.all import save 605 656 606 657 # Trying to save to Sage's directory 607 658 try: 608 save( classes, SAGE_ROOT+'/data/graphs/isgci_classes.sobj')609 save( inclusions, SAGE_ROOT+'/data/graphs/isgci_inclusions.sobj')610 inclusions =inclusion_digraph = None611 classes = {}612 if verbose:613 print "Database saved to .sobj files in "+SAGE_ROOT+'/data/graphs/'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 = {} 663 print "Database saved to .sobj files in "+SAGE_ROOT+'/data/graphs/' 664 return 614 665 615 return616 666 except IOError: 617 if verbose:618 # TODO: improve!619 print "Could not save save database in "+SAGE_ROOT+'/data/graphs/'667 # TODO: improve! 668 print "Could not save save database in "+SAGE_ROOT+'/data/graphs/' 669 print "Now attempting to save the files to "+str(SAGE_DB) 620 670 pass 621 671 622 672 # Trying to save to the user's home directory 623 try: 624 save(classes, SAGE_DB+"/isgci_classes.sobj") 625 save(inclusions, SAGE_DB+"/isgci_inclusions.sobj") 626 classes = inclusions = inclusion_digraph = None 627 if verbose: 628 print "Database saved to .sobj files in "+SAGE_DB 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 = {} 677 print "Database saved to .sobj files in "+SAGE_DB 629 678 630 return 631 632 except IOError: 633 pass 634 635 # TODO: as above: don't hide the more informative error message 636 # from the system 637 638 # Gloops ! 639 raise Exception("Sage is unable to write the files to your"+ 640 "computer ! This shouldn't have happened. "+ 641 "Could you report the bug ? ;)") 642 643 def get_ISGCI(): 679 def _get_ISGCI(self): 644 680 r""" 645 681 Returns the contents of the ISGCI database. 646 682 … … 659 695 660 696 EXAMPLE:: 661 697 662 sage: classes, inclusions = sage.graphs.isgci.get_ISGCI()698 sage: classes, inclusions = graph_classes._get_ISGCI() 663 699 """ 664 700 665 701 import os.path … … 690 726 691 727 return classes, inclusions 692 728 693 def show_all( ):729 def show_all(self): 694 730 r""" 695 731 Prints all graph classes stored in ISGCI 696 732 697 733 EXAMPLE:: 698 734 699 sage: sage.graphs.isgci.show_all()735 sage: graph_classes.show_all() 700 736 ID  name  type  smallgraph 701 737  702 738 gc_309  $K_4$minorfree  base  … … 708 744 gc_7  $P_4$extendible  base  709 745 ... 710 746 """ 711 global classes 712 _load_ISGCI_if_not_loaded() 747 classes = self.classes() 713 748 classes_list = classes.values() 714 749 715 750 # We want to print the different fields, and this dictionary stores the … … 748 783 smallgraph = entry.get("smallgraph","") 749 784 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] 750 785 751 def _load_ISGCI_if_not_loaded():752 r"""753 Load ISGI if not loaded already754 755 This is here to avoid having to load the db when Sage starts756 """757 global classes, inclusions758 if classes == {}:759 classes, inclusions = get_ISGCI()760 761 def _build_inclusion_digraph_if_not_built():762 r"""763 Builds the class digraph764 """765 global classes, inclusions, inclusion_digraph766 767 if not (inclusion_digraph is None):768 return769 770 _load_ISGCI_if_not_loaded()771 772 from sage.graphs.digraph import DiGraph773 inclusion_digraph = DiGraph()774 inclusion_digraph.add_vertices(classes.keys())775 776 for edge in inclusions:777 if edge.get("confidence","") == "unpublished":778 continue779 780 inclusion_digraph.add_edge(edge['super'], edge['sub'])781 782 inclusions = []783 784 785 786 graph_classes = GraphClasses() 786 787 787 788 # Any object added to this list should also appear in the class' documentation, at the top of the file. … … 789 790 graph_classes.Bipartite = GraphClass("Bipartite", "gc_69") 790 791 graph_classes.Block = GraphClass("Block", "gc_93") 791 792 graph_classes.Chordal = GraphClass("Chordal", "gc_32") 792 graph_classes.Clique = GraphClass("Clique", "gc_141")793 793 graph_classes.Comparability = GraphClass("Comparability", "gc_72") 794 794 graph_classes.Gallai = GraphClass("Gallai", "gc_73") 795 795 graph_classes.Grid = GraphClass("Grid", "gc_464")