Ticket #11880: trac_11880-graph_classes-review-nt.patch

File trac_11880-graph_classes-review-nt.patch, 19.2 KB (added by nthiery, 8 years ago)
  • sage/graphs/isgci.py

    # HG changeset patch
    # User Nicolas M. Thiery <nthiery@users.sf.net>
    # Date 1329571825 -3600
    # Node ID 93a220ee001973026d6326b12ee5f98ff263632f
    # Parent  36cfce1f5e12bc409a3cf23db990224bb4de9bd6
    [mq]: trac_11880-graph_classes-review-nt.patch
    
    diff --git a/sage/graphs/isgci.py b/sage/graphs/isgci.py
    a b  
    11r"""
    22Information System on Graph Classes and their Inclusions
    33
    4 This module deals with anything related to the ISGCI database in Sage.
     4This module implements an interface to the `ISGCI <http://www.graphclasses.org/>`_ database in Sage.
    55
    6 The ISGCI database gathers information on graph classes and their inclusions in
    7 each other. It also contains information on the complexity of several
    8 computational problems.
     6This database gathers information on graph classes and their
     7inclusions in each other. It also contains information on the
     8complexity of several computational problems.
    99
    10 It is available on the `GraphClasses.org website
    11 <http://www.graphclasses.org/>`_ maintained by H.N. de Ridder et al.
     10It is available on the `GraphClasses.org <http://www.graphclasses.org/>`_
     11website maintained by H.N. de Ridder et al.
    1212
    13 How to use it ?
    14 ---------------
     13How to use it?
     14--------------
    1515
    16 The current support of the ISGCI database is elementary, and aims at
    17 implementing a pure Sage/Python interface which is easier to deal with than a
    18 XML file. I hope this code will be rewritten many times until it stabilizes :-)
     16The current limited aim of this module is to provide a pure
     17Sage/Python interface which is easier to deal with than a XML file. I
     18hope it will be rewritten many times until it stabilizes :-)
    1919
    2020Presently, it is possible to use this database through the variables and methods
    21 present in the ``graph_classes`` object. For instance ::
     21present in the :obj:`graph_classes <sage.graphs.isgci.GraphClasses>` object.
     22For instance::
    2223
    2324    sage: Trees = graph_classes.Tree
    2425    sage: Chordal = graph_classes.Chordal
    2526
    26 It is then possible to check the inclusion of classes inside of others, if the
    27 information is available in the db::
     27It is then possible to check the inclusion of classes inside of
     28others, if the information is available in the database::
    2829
    2930    sage: Trees <= Chordal
    3031    True
    3132
    32 And indeed, the trees are chordal graphs.
     33And indeed, trees are chordal graphs.
    3334
    3435.. WARNING::
    3536
    36     At the moment, only the *yes* answers can be assumed to be true !
     37    At the moment, only *positive* answers are guaranteed correct!
    3738
    38     ISGCI may not contain the information necessary to prove that a class A is a
    39     subset of a class B, but that does not mean that class A is **NOT** a subset
    40     of B. It just means ISGCI has no idea. Hence, no **NO** answer can be
    41     assumed to be true at the moment.
    42 
    43     When asked to compare Trees and Chordal graphs, though, the correct answer
    44     is returned (as ISGCI obviously does not contain any proof that all chordal
    45     graphs are trees, which would be a mistake)::
     39    A *negative* answer to ``A <= B`` only means that ISGCI can't
     40    deduce from the information in its database that ``A`` is a
     41    subclass of ``B`` nor that it is not. For the reverse inclusion
     42    between Trees and Chordal graphs the answer is correct though::
    4643
    4744        sage: Chordal <= Trees
    4845        False
    4946
     47    TODO: what about using a Troolean?
     48
     49    TODO: what about strict inclusion?
     50
    5051Given a graph class, one can obtain its associated information in the
    5152ISGCI database with the :meth:`show
    5253<sage.graphs.isgci.GraphClass.show>` method::
    ISGCI database with the :meth:`show 
    7374    3-Colourability                :  Linear
    7475    Recognition                    :  Linear
    7576
    76 It is possible to obtain the complete list of the classes stored in ISGCI by
    77 calling the :meth:`show_all <sage.graphs.isgci.show_all>` method
     77It is possible to obtain the complete list of the classes stored in
     78ISGCI by calling the :func:`sage.graphs.isgci.show_all` function
    7879(beware -- long output)::
    7980
    8081    sage: sage.graphs.isgci.show_all()
    81     ID        | name                                     | type                 | smallgraph                             
     82    ID        | name                                     | type                 | smallgraph
    8283    ----------------------------------------------------------------------------------------------------------------------
    83     gc_309    | $K_4$--minor--free                       | base                 | 
    84     gc_541    | $N^*$                                    | base                 | 
    85     gc_215    | $N^*$--perfect                           | base                 | 
    86     gc_5      | $P_4$--bipartite                         | base                 | 
    87     gc_3      | $P_4$--brittle                           | base                 | 
    88     gc_6      | $P_4$--comparability                     | base                 | 
    89     gc_7      | $P_4$--extendible                        | base                 | 
     84    gc_309    | $K_4$--minor--free                       | base                 |
     85    gc_541    | $N^*$                                    | base                 |
     86    gc_215    | $N^*$--perfect                           | base                 |
     87    gc_5      | $P_4$--bipartite                         | base                 |
     88    gc_3      | $P_4$--brittle                           | base                 |
     89    gc_6      | $P_4$--comparability                     | base                 |
     90    gc_7      | $P_4$--extendible                        | base                 |
    9091    ...
    9192
    92 This lets one find a class which does not appear in ``graph_classes`` (and
    93 should really be replaced by a proper search method). Given the ISGCI ID code
    94 corresponding to a classe, the :meth:`get_class_from_id
    95 <sage.graphs.isgci.GraphClasses.get_class_from_id>` method returns the
    96 corresponding graph class::
     93Until a proper search method is implemented, this lets one find
     94classes which are not listed in :obj:`graph_classes <sage.graphs.isgci.GraphClasses>`.
     95
     96TODO: get_class_from_id is currently a method of graph_classes whereas
     97show_all is a function of this module. Should show_all be moved to
     98graph_classes for consistency?
     99
     100To 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>`::
    97102
    98103    sage: GC = graph_classes.get_class_from_id("gc_5")
    99104    sage: GC
    corresponding graph class:: 
    102107Predefined classes
    103108------------------
    104109
    105 The ``graph_classes.*`` currently lists the following graph classes
     110:obj:`graph_classes <sage.graphs.isgci.GraphClasses>` currently lists the following graph classes
     111
     112TODO: use .. seealso:: in all entries of this list?
    106113
    107114.. list-table::
    108115   :widths: 20 30
    Information for developpers 
    204211  the ``.sobj`` files in which it is stored and their information can be
    205212  accessed by the following variables :
    206213
    207   * ``sage.graphs.isgci.classes`` (dictionary) 
     214  * ``sage.graphs.isgci.classes`` (dictionary)
    208215  * ``sage.graphs.isgci.inclusions`` (list of dictionaries)
    209216  * ``sage.graphs.isgci.class_digraph`` (DiGraph)
    210217
    Information for developpers 
    216223  class represented by `u` is larger (not necessarily strictly) than the one
    217224  represented by `v`.
    218225
     226
     227  TODO: this is useful information for the user too. Move it out of
     228  the developpers section?
     229
    219230  Though it represents inclusions of sets, this ``DiGraph`` is **NOT
    220   ACYCLIC**. Several entries exist in the ISGCI database whise represent the
    221   same graph class::
     231  ACYCLIC**::
     232
     233      sage: sage.graphs.isgci.class_digraph.is_directed_acyclic()
     234      False
     235
     236  Indeed, several entries exist in the ISGCI database which represent
     237  the same graph class::
    222238
    223239    sage: Berge = graph_classes.get_class_from_id("gc_274"); Berge
    224240    Graph class : Berge
    Information for developpers 
    228244    True
    229245    sage: Perfect <= Berge
    230246    True
    231      
    232   (Which is the same as)::
     247
     248  In other words::
    233249
    234250    sage: Perfect == Berge
    235251    True
    236252
    237   Indeed ::
     253.. todo::
    238254
    239     sage: sage.graphs.isgci.class_digraph.is_directed_acyclic()
    240     False
     255    Technical things:
    241256
    242 ToDo list
    243 ---------
     257    * Implement a proper search method for the classes not listed in
     258      :obj:`graph_classes <sage.graphs.isgci.GraphClasses>`
    244259
    245 Technical things :
     260      .. seealso: :func:`sage.graphs.isgci.show_all`.
    246261
    247 * Find a proper way to find a graph class which does not appear in
    248   ``graph_classes`` by can be listed by :meth:`show_all
    249   <sage.graphs.isgci.show_all>`.
     262    * Some of the graph classes appearing in :obj:`graph_classes
     263      <sage.graphs.isgci.GraphClasses>` already have a recognition
     264      algorithm implemented in Sage. It would be so nice to be able to
     265      write ``g in Trees``, ``g in Perfect``, ``g in Chordal``, ... `:-)`
    250266
    251 * Some of the graph classes appearing in ``graph_classes.*`` already have a
    252   recognition algorithm in Sage. It would be so nice to be able to write ``g in
    253   Trees``, ``g in Perfect``, ``g in Chordal``, ... `:-)`
     267    Long-term stuff:
    254268
    255 Long-term stuff :
     269    * Implement simple accessors for all the information in the ISGCI
     270      database (as can be done from the website)
    256271
    257 * To be able to ask questions to ISGCI from the inside of Sage, easily enough,
    258   related to any information it contains (for instance everything that can be
    259   done through the website)
     272    * Implement intersection of graph classes
    260273
    261 * Write generic recognition algorithms for specific classes (when a graph class
    262   is defined by the exclusion of subgraphs, one can write a generic algorithm
    263   checking the existence of each of the graphs, and this method already exists
    264   in Sage).
     274    * Write generic recognition algorithms for specific classes (when a graph class
     275      is defined by the exclusion of subgraphs, one can write a generic algorithm
     276      checking the existence of each of the graphs, and this method already exists
     277      in Sage).
    265278
    266 * Modify our algorithms so that they could use the properties of a graph class
    267   to improve their performances. Right now, the same algorithm is used to find
    268   an independent set in a tree, in a planar graph, or any other graph.
     279    * Improve the performance of Sage's graph library by letting it
     280      take advantage of the properties of graph classes. For example,
     281      :meth:`Graph.independent_set` could use the library to detect
     282      that a given graph is, say, a tree or a planar graph, and use a
     283      specialized algorithm for finding an independent set.
    269284
    270285
    271286AUTHORS:
    272287--------
    273288
    274289* H.N. de Ridder et al. (ISGCI database)
    275 * Nathann Cohen (Sage implementation) 
     290* Nathann Cohen (Sage implementation)
    276291
    277292Methods
    278293-------
    class_digraph = None 
    284299
    285300
    286301#*****************************************************************************
    287 #      Copyright (C) 2011 Nathann Cohen <nathann.cohen@gmail.com>           
     302#      Copyright (C) 2011 Nathann Cohen <nathann.cohen@gmail.com>
    288303#
    289304# Distributed  under  the  terms  of  the  GNU  General  Public  License (GPL)
    290305#                         http://www.gnu.org/licenses/
    def _create_db(): 
    328343    # want from the XML file and that's more or less all we ask it to do :-p
    329344
    330345    doc = xml.dom.minidom.parse(SAGE_TMP+_XML_FILE)
    331    
     346
    332347    classes = {}
    333348
    334349    giveme = lambda x,y : str(x.getAttribute(y))
    def _create_db(): 
    358373        if giveme(node, "type"):
    359374            Dl["type"] = giveme(node, "type")
    360375
    361    
     376
    362377        classes[giveme(node, "id")] = Dl
    363378
    364379    inclusions = []
    def _create_db(): 
    366381        Dl = {}
    367382        for name in ["proper", "confidence", "super", "sub"]:
    368383            if giveme(node, name):
    369                 Dl[name] = giveme(node, name)           
     384                Dl[name] = giveme(node, name)
    370385
    371386        for node2 in node.childNodes:
    372387            name = str(node2.nodeName)
    def _create_db(): 
    379394
    380395def update_db(verbose = False):
    381396    r"""
    382     Updates the current version of the ISGCI database by download it from internet.
     397    Updates the ISGCI database by downloading the latest version from internet.
    383398
    384399    This method downloads the ISGCI database from the website `GraphClasses.org
    385     <http://www.graphclasses.org/>`_. 
     400    <http://www.graphclasses.org/>`_.
    386401
    387     It then extracts the zip file and parses its XML content, which is stored as
    388     two .sobj files, the first one representing the graph classes, and the
    389     second representing their inclusions.
     402    It then extracts the zip file and parses its XML content, which is
     403    stored as two ``.sobj`` files, the first one representing the
     404    graph classes, and the second representing their inclusions.
    390405
    391     Depending on the rights of the user running Sage when this command is run,
    392     one attempt is made at saving its result in Sage's directory so that all
    393     users would benefit from it. If the rights are not sufficient, the .sobj
    394     files are saved to the current user's directory, so that he will be the only
    395     one to benefit from the update.
     406    Depending on the credentials of the user running Sage when this
     407    command is run, one attempt is made at saving the result in Sage's
     408    directory so that all users can benefit from it. If the
     409    credentials are not sufficient, the ``.sobj`` files are saved
     410    instead in the user's directory. #TODO: be more specific about where in the user's directory?
    396411
    397412    INPUT:
    398413
    399     - ``verbose`` (boolean) -- whether to output information of the update
    400       process.
     414    - ``verbose`` -- a boolean (default: False); whether to output
     415      information of the update process
    401416
    402417    EXAMPLE::
    403418
    def update_db(verbose = False): 
    405420    """
    406421    from sage.misc.misc import SAGE_TMP, SAGE_ROOT, SAGE_LOCAL, SAGE_DB
    407422    global classes, inclusions, class_digraph
    408    
     423
    409424    try:
    410425        _download_db()
    411426    except:
     427        # TODO: as such, the user won't get the, probably more
     428        # informative, error message thrown by download_db. What about
     429        # not catching it? Or at least retransmitting the error
     430        # message?
    412431        raise Exception("There has been a problem while downloading or unzipping the ISGCI database O_o")
    413432
    414433
    def update_db(verbose = False): 
    419438
    420439    if verbose:
    421440        print "XML file converted to Python dictionaries"
    422    
     441
    423442
    424443    from sage.all import save
    425    
     444
    426445    # Trying to save to Sage's directory
    427446    try:
    428447        save(classes, SAGE_ROOT+'/data/graphs/isgci_classes.sobj')
    def update_db(verbose = False): 
    434453
    435454        return
    436455    except IOError:
     456        if verbose:
     457            # TODO: improve!
     458            print "Could not save save database in "+SAGE_ROOT+'/data/graphs/'
    437459        pass
    438460
    439461    # Trying to save to the user's home directory
    def update_db(verbose = False): 
    449471    except IOError:
    450472        pass
    451473
     474    # TODO: as above: don't hide the more informative error message
     475    # from the system
     476
    452477    # Gloops !
    453478    raise Exception("Sage is unable to write the files to your"+
    454479                    "computer ! This shouldn't have happened. "+
    def get_ISGCI(): 
    465490
    466491    A pair ``(classes, inclusions)`` where ``classes`` is a dict of dict, and
    467492    ``inclusions`` is a list of dicts.
    468    
     493
    469494    .. NOTE::
    470495
    471         This method returns the data contained in the most recent version of the
    472         ISGCI database present on the computer. See ``update_db`` to update it.
     496        This method returns the data contained in the most recent ISGCI database
     497        present on the computer. See :func:`update_db` to update the latter.
    473498
    474499    EXAMPLE::
    475500
    def get_ISGCI(): 
    480505    from sage.all import save, load
    481506    from sage.misc.misc import SAGE_TMP, SAGE_ROOT, SAGE_LOCAL, SAGE_DB
    482507
     508    # TODO: or systematically use the user's version if it exists,
     509    # throwing a warning if it is not the most recent?
     510
    483511    try:
    484512        open(SAGE_DB+"/isgci_classes.sobj")
    485513
    486514        # Which copy is the most recent on the disk ?
    487515        if (os.path.getmtime(SAGE_DB+"/isgci_classes.sobj") >
    488516            os.path.getmtime(SAGE_ROOT+"/data/graphs/isgci_classes.sobj")):
    489            
     517
    490518            classes = load(SAGE_DB+"/isgci_classes.sobj")
    491519            inclusions = load(SAGE_DB+"/isgci_inclusions.sobj")
    492520
    def show_all(): 
    508536    EXAMPLE::
    509537
    510538        sage: sage.graphs.isgci.show_all()
    511         ID        | name                                     | type                 | smallgraph                             
     539        ID        | name                                     | type                 | smallgraph
    512540        ----------------------------------------------------------------------------------------------------------------------
    513         gc_309    | $K_4$--minor--free                       | base                 | 
    514         gc_541    | $N^*$                                    | base                 | 
    515         gc_215    | $N^*$--perfect                           | base                 | 
    516         gc_5      | $P_4$--bipartite                         | base                 | 
    517         gc_3      | $P_4$--brittle                           | base                 | 
    518         gc_6      | $P_4$--comparability                     | base                 | 
    519         gc_7      | $P_4$--extendible                        | base                 | 
     541        gc_309    | $K_4$--minor--free                       | base                 |
     542        gc_541    | $N^*$                                    | base                 |
     543        gc_215    | $N^*$--perfect                           | base                 |
     544        gc_5      | $P_4$--bipartite                         | base                 |
     545        gc_3      | $P_4$--brittle                           | base                 |
     546        gc_6      | $P_4$--comparability                     | base                 |
     547        gc_7      | $P_4$--extendible                        | base                 |
    520548        ...
    521549    """
    522550    global classes
    def show_all(): 
    553581
    554582    # Entries
    555583    for entry in classes_list:
    556         ID = entry.get("ID","") 
     584        ID = entry.get("ID","")
    557585        name = entry.get("name","")
    558586        type = entry.get("type","")
    559587        smallgraph = entry.get("smallgraph","")
    def _build_class_digraph_if_not_built(): 
    589617            continue
    590618
    591619        class_digraph.add_edge(edge['super'], edge['sub'])
    592    
     620
    593621    inclusions = []
    594622
     623# TODO: maybe inherit from SageObject?
    595624class GraphClass:
    596625    r"""
    597626    An instance of this class represents a Graph Class, matching some entry in
    class GraphClass: 
    700729            if value != "":
    701730                print "{0:30} : ".format(key),
    702731                print value
    703        
     732
    704733
    705734
    706735class GraphClasses:
    class GraphClasses: 
    722751            Traceback (most recent call last):
    723752            ...
    724753            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().
     754
     755
     756        TODO: rename ot     ``graph_classes.get_class(id = "gc_151")``?
     757        or even ``graph_classes.Class(id = "gc_151")``?
    725758        """
    726759        global classes
    727760        _load_ISGCI_if_not_loaded()
    graph_classes.Split = GraphClass("Split" 
    764797graph_classes.Tree = GraphClass("Tree", "gc_342")
    765798graph_classes.UnitDisk = GraphClass("UnitDisk", "gc_389")
    766799graph_classes.UnitInterval = GraphClass("UnitInterval", "gc_299")
    767