# HG changeset patch
# User Nicolas M. Thiery
# Date 1329571825 3600
# Node ID 93a220ee001973026d6326b12ee5f98ff263632f
# Parent 36cfce1f5e12bc409a3cf23db990224bb4de9bd6
[mq]: trac_11880graph_classesreviewnt.patch
diff git a/sage/graphs/isgci.py b/sage/graphs/isgci.py
 a/sage/graphs/isgci.py
+++ b/sage/graphs/isgci.py
@@ 1,52 +1,53 @@
r"""
Information System on Graph Classes and their Inclusions
This module deals with anything related to the ISGCI database in Sage.
+This module implements an interface to the `ISGCI `_ database in Sage.
The ISGCI database gathers information on graph classes and their inclusions in
each other. It also contains information on the complexity of several
computational problems.
+This database gathers information on graph classes and their
+inclusions in each other. It also contains information on the
+complexity of several computational problems.
It is available on the `GraphClasses.org website
`_ maintained by H.N. de Ridder et al.
+It is available on the `GraphClasses.org `_
+website maintained by H.N. de Ridder et al.
How to use it ?

+How to use it?
+
The current support of the ISGCI database is elementary, and aims at
implementing a pure Sage/Python interface which is easier to deal with than a
XML file. I hope this code will be rewritten many times until it stabilizes :)
+The current limited aim of this module is to provide a pure
+Sage/Python interface which is easier to deal with than a XML file. I
+hope it will be rewritten many times until it stabilizes :)
Presently, it is possible to use this database through the variables and methods
present in the ``graph_classes`` object. For instance ::
+present in the :obj:`graph_classes ` object.
+For instance::
sage: Trees = graph_classes.Tree
sage: Chordal = graph_classes.Chordal
It is then possible to check the inclusion of classes inside of others, if the
information is available in the db::
+It is then possible to check the inclusion of classes inside of
+others, if the information is available in the database::
sage: Trees <= Chordal
True
And indeed, the trees are chordal graphs.
+And indeed, trees are chordal graphs.
.. WARNING::
 At the moment, only the *yes* answers can be assumed to be true !
+ At the moment, only *positive* answers are guaranteed correct!
 ISGCI may not contain the information necessary to prove that a class A is a
 subset of a class B, but that does not mean that class A is **NOT** a subset
 of B. It just means ISGCI has no idea. Hence, no **NO** answer can be
 assumed to be true at the moment.

 When asked to compare Trees and Chordal graphs, though, the correct answer
 is returned (as ISGCI obviously does not contain any proof that all chordal
 graphs are trees, which would be a mistake)::
+ A *negative* answer to ``A <= B`` only means that ISGCI can't
+ deduce from the information in its database that ``A`` is a
+ subclass of ``B`` nor that it is not. For the reverse inclusion
+ between Trees and Chordal graphs the answer is correct though::
sage: Chordal <= Trees
False
+ TODO: what about using a Troolean?
+
+ TODO: what about strict inclusion?
+
Given a graph class, one can obtain its associated information in the
ISGCI database with the :meth:`show
` method::
@@ 73,27 +74,31 @@ ISGCI database with the :meth:`show
3Colourability : Linear
Recognition : Linear
It is possible to obtain the complete list of the classes stored in ISGCI by
calling the :meth:`show_all ` method
+It is possible to obtain the complete list of the classes stored in
+ISGCI by calling the :func:`sage.graphs.isgci.show_all` function
(beware  long output)::
sage: sage.graphs.isgci.show_all()
 ID  name  type  smallgraph
+ ID  name  type  smallgraph

 gc_309  $K_4$minorfree  base 
 gc_541  $N^*$  base 
 gc_215  $N^*$perfect  base 
 gc_5  $P_4$bipartite  base 
 gc_3  $P_4$brittle  base 
 gc_6  $P_4$comparability  base 
 gc_7  $P_4$extendible  base 
+ gc_309  $K_4$minorfree  base 
+ gc_541  $N^*$  base 
+ gc_215  $N^*$perfect  base 
+ gc_5  $P_4$bipartite  base 
+ gc_3  $P_4$brittle  base 
+ gc_6  $P_4$comparability  base 
+ gc_7  $P_4$extendible  base 
...
This lets one find a class which does not appear in ``graph_classes`` (and
should really be replaced by a proper search method). Given the ISGCI ID code
corresponding to a classe, the :meth:`get_class_from_id
` method returns the
corresponding graph class::
+Until a proper search method is implemented, this lets one find
+classes which are not listed in :obj:`graph_classes `.
+
+TODO: get_class_from_id is currently a method of graph_classes whereas
+show_all is a function of this module. Should show_all be moved to
+graph_classes for consistency?
+
+To retrieve a class of graph from its ISGCI ID one may use
+:meth:`graph_classes.get_class_from_id `::
sage: GC = graph_classes.get_class_from_id("gc_5")
sage: GC
@@ 102,7 +107,9 @@ corresponding graph class::
Predefined classes

The ``graph_classes.*`` currently lists the following graph classes
+:obj:`graph_classes ` currently lists the following graph classes
+
+TODO: use .. seealso:: in all entries of this list?
.. listtable::
:widths: 20 30
@@ 204,7 +211,7 @@ Information for developpers
the ``.sobj`` files in which it is stored and their information can be
accessed by the following variables :
 * ``sage.graphs.isgci.classes`` (dictionary)
+ * ``sage.graphs.isgci.classes`` (dictionary)
* ``sage.graphs.isgci.inclusions`` (list of dictionaries)
* ``sage.graphs.isgci.class_digraph`` (DiGraph)
@@ 216,9 +223,18 @@ Information for developpers
class represented by `u` is larger (not necessarily strictly) than the one
represented by `v`.
+
+ TODO: this is useful information for the user too. Move it out of
+ the developpers section?
+
Though it represents inclusions of sets, this ``DiGraph`` is **NOT
 ACYCLIC**. Several entries exist in the ISGCI database whise represent the
 same graph class::
+ ACYCLIC**::
+
+ sage: sage.graphs.isgci.class_digraph.is_directed_acyclic()
+ False
+
+ Indeed, several entries exist in the ISGCI database which represent
+ the same graph class::
sage: Berge = graph_classes.get_class_from_id("gc_274"); Berge
Graph class : Berge
@@ 228,51 +244,50 @@ Information for developpers
True
sage: Perfect <= Berge
True

 (Which is the same as)::
+
+ In other words::
sage: Perfect == Berge
True
 Indeed ::
+.. todo::
 sage: sage.graphs.isgci.class_digraph.is_directed_acyclic()
 False
+ Technical things:
ToDo list

+ * Implement a proper search method for the classes not listed in
+ :obj:`graph_classes `
Technical things :
+ .. seealso: :func:`sage.graphs.isgci.show_all`.
* Find a proper way to find a graph class which does not appear in
 ``graph_classes`` by can be listed by :meth:`show_all
 `.
+ * Some of the graph classes appearing in :obj:`graph_classes
+ ` already have a recognition
+ algorithm implemented in Sage. It would be so nice to be able to
+ write ``g in Trees``, ``g in Perfect``, ``g in Chordal``, ... `:)`
* Some of the graph classes appearing in ``graph_classes.*`` already have a
 recognition algorithm in Sage. It would be so nice to be able to write ``g in
 Trees``, ``g in Perfect``, ``g in Chordal``, ... `:)`
+ Longterm stuff:
Longterm stuff :
+ * Implement simple accessors for all the information in the ISGCI
+ database (as can be done from the website)
* To be able to ask questions to ISGCI from the inside of Sage, easily enough,
 related to any information it contains (for instance everything that can be
 done through the website)
+ * Implement intersection of graph classes
* Write generic recognition algorithms for specific classes (when a graph class
 is defined by the exclusion of subgraphs, one can write a generic algorithm
 checking the existence of each of the graphs, and this method already exists
 in Sage).
+ * Write generic recognition algorithms for specific classes (when a graph class
+ is defined by the exclusion of subgraphs, one can write a generic algorithm
+ checking the existence of each of the graphs, and this method already exists
+ in Sage).
* Modify our algorithms so that they could use the properties of a graph class
 to improve their performances. Right now, the same algorithm is used to find
 an independent set in a tree, in a planar graph, or any other graph.
+ * Improve the performance of Sage's graph library by letting it
+ take advantage of the properties of graph classes. For example,
+ :meth:`Graph.independent_set` could use the library to detect
+ that a given graph is, say, a tree or a planar graph, and use a
+ specialized algorithm for finding an independent set.
AUTHORS:

* H.N. de Ridder et al. (ISGCI database)
* Nathann Cohen (Sage implementation)
+* Nathann Cohen (Sage implementation)
Methods

@@ 284,7 +299,7 @@ class_digraph = None
#*****************************************************************************
# Copyright (C) 2011 Nathann Cohen
+# Copyright (C) 2011 Nathann Cohen
#
# Distributed under the terms of the GNU General Public License (GPL)
# http://www.gnu.org/licenses/
@@ 328,7 +343,7 @@ def _create_db():
# want from the XML file and that's more or less all we ask it to do :p
doc = xml.dom.minidom.parse(SAGE_TMP+_XML_FILE)

+
classes = {}
giveme = lambda x,y : str(x.getAttribute(y))
@@ 358,7 +373,7 @@ def _create_db():
if giveme(node, "type"):
Dl["type"] = giveme(node, "type")

+
classes[giveme(node, "id")] = Dl
inclusions = []
@@ 366,7 +381,7 @@ def _create_db():
Dl = {}
for name in ["proper", "confidence", "super", "sub"]:
if giveme(node, name):
 Dl[name] = giveme(node, name)
+ Dl[name] = giveme(node, name)
for node2 in node.childNodes:
name = str(node2.nodeName)
@@ 379,25 +394,25 @@ def _create_db():
def update_db(verbose = False):
r"""
 Updates the current version of the ISGCI database by download it from internet.
+ Updates the ISGCI database by downloading the latest version from internet.
This method downloads the ISGCI database from the website `GraphClasses.org
 `_.
+ `_.
 It then extracts the zip file and parses its XML content, which is stored as
 two .sobj files, the first one representing the graph classes, and the
 second representing their inclusions.
+ It then extracts the zip file and parses its XML content, which is
+ stored as two ``.sobj`` files, the first one representing the
+ graph classes, and the second representing their inclusions.
 Depending on the rights of the user running Sage when this command is run,
 one attempt is made at saving its result in Sage's directory so that all
 users would benefit from it. If the rights are not sufficient, the .sobj
 files are saved to the current user's directory, so that he will be the only
 one to benefit from the update.
+ Depending on the credentials of the user running Sage when this
+ command is run, one attempt is made at saving the result in Sage's
+ directory so that all users can benefit from it. If the
+ credentials are not sufficient, the ``.sobj`` files are saved
+ instead in the user's directory. #TODO: be more specific about where in the user's directory?
INPUT:
  ``verbose`` (boolean)  whether to output information of the update
 process.
+  ``verbose``  a boolean (default: False); whether to output
+ information of the update process
EXAMPLE::
@@ 405,10 +420,14 @@ def update_db(verbose = False):
"""
from sage.misc.misc import SAGE_TMP, SAGE_ROOT, SAGE_LOCAL, SAGE_DB
global classes, inclusions, class_digraph

+
try:
_download_db()
except:
+ # TODO: as such, the user won't get the, probably more
+ # informative, error message thrown by download_db. What about
+ # not catching it? Or at least retransmitting the error
+ # message?
raise Exception("There has been a problem while downloading or unzipping the ISGCI database O_o")
@@ 419,10 +438,10 @@ def update_db(verbose = False):
if verbose:
print "XML file converted to Python dictionaries"

+
from sage.all import save

+
# Trying to save to Sage's directory
try:
save(classes, SAGE_ROOT+'/data/graphs/isgci_classes.sobj')
@@ 434,6 +453,9 @@ def update_db(verbose = False):
return
except IOError:
+ if verbose:
+ # TODO: improve!
+ print "Could not save save database in "+SAGE_ROOT+'/data/graphs/'
pass
# Trying to save to the user's home directory
@@ 449,6 +471,9 @@ def update_db(verbose = False):
except IOError:
pass
+ # TODO: as above: don't hide the more informative error message
+ # from the system
+
# Gloops !
raise Exception("Sage is unable to write the files to your"+
"computer ! This shouldn't have happened. "+
@@ 465,11 +490,11 @@ def get_ISGCI():
A pair ``(classes, inclusions)`` where ``classes`` is a dict of dict, and
``inclusions`` is a list of dicts.

+
.. NOTE::
 This method returns the data contained in the most recent version of the
 ISGCI database present on the computer. See ``update_db`` to update it.
+ This method returns the data contained in the most recent ISGCI database
+ present on the computer. See :func:`update_db` to update the latter.
EXAMPLE::
@@ 480,13 +505,16 @@ def get_ISGCI():
from sage.all import save, load
from sage.misc.misc import SAGE_TMP, SAGE_ROOT, SAGE_LOCAL, SAGE_DB
+ # TODO: or systematically use the user's version if it exists,
+ # throwing a warning if it is not the most recent?
+
try:
open(SAGE_DB+"/isgci_classes.sobj")
# Which copy is the most recent on the disk ?
if (os.path.getmtime(SAGE_DB+"/isgci_classes.sobj") >
os.path.getmtime(SAGE_ROOT+"/data/graphs/isgci_classes.sobj")):

+
classes = load(SAGE_DB+"/isgci_classes.sobj")
inclusions = load(SAGE_DB+"/isgci_inclusions.sobj")
@@ 508,15 +536,15 @@ def show_all():
EXAMPLE::
sage: sage.graphs.isgci.show_all()
 ID  name  type  smallgraph
+ ID  name  type  smallgraph

 gc_309  $K_4$minorfree  base 
 gc_541  $N^*$  base 
 gc_215  $N^*$perfect  base 
 gc_5  $P_4$bipartite  base 
 gc_3  $P_4$brittle  base 
 gc_6  $P_4$comparability  base 
 gc_7  $P_4$extendible  base 
+ gc_309  $K_4$minorfree  base 
+ gc_541  $N^*$  base 
+ gc_215  $N^*$perfect  base 
+ gc_5  $P_4$bipartite  base 
+ gc_3  $P_4$brittle  base 
+ gc_6  $P_4$comparability  base 
+ gc_7  $P_4$extendible  base 
...
"""
global classes
@@ 553,7 +581,7 @@ def show_all():
# Entries
for entry in classes_list:
 ID = entry.get("ID","")
+ ID = entry.get("ID","")
name = entry.get("name","")
type = entry.get("type","")
smallgraph = entry.get("smallgraph","")
@@ 589,9 +617,10 @@ def _build_class_digraph_if_not_built():
continue
class_digraph.add_edge(edge['super'], edge['sub'])

+
inclusions = []
+# TODO: maybe inherit from SageObject?
class GraphClass:
r"""
An instance of this class represents a Graph Class, matching some entry in
@@ 700,7 +729,7 @@ class GraphClass:
if value != "":
print "{0:30} : ".format(key),
print value

+
class GraphClasses:
@@ 722,6 +751,10 @@ class GraphClasses:
Traceback (most recent call last):
...
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().
+
+
+ TODO: rename ot ``graph_classes.get_class(id = "gc_151")``?
+ or even ``graph_classes.Class(id = "gc_151")``?
"""
global classes
_load_ISGCI_if_not_loaded()
@@ 764,4 +797,3 @@ graph_classes.Split = GraphClass("Split"
graph_classes.Tree = GraphClass("Tree", "gc_342")
graph_classes.UnitDisk = GraphClass("UnitDisk", "gc_389")
graph_classes.UnitInterval = GraphClass("UnitInterval", "gc_299")
