Closed dcoudert closed 11 years ago
Description changed:
---
+++
@@ -1,2 +1,3 @@
This patch implements the generators for Queen, King, and Knight graphs.
+These graphs are useful for testing graph coloring algorithms, hamiltonian cycles, etc.
Two comments:
1) What about supporting d-dimensional chess boards? i.e. G = graphs.QueenGraph(2, 2, 2) or G = graphs.QueenGraph(5,6,7,8,9)
2) Your input checks require n to be of type Integer. This excludes python ints and other things considered an integer. What about: "if n not in ZZ:"?
Replying to @sagetrac-sluther:
Two comments:
1) What about supporting d-dimensional chess boards? i.e. G = graphs.QueenGraph(2, 2, 2) or G = graphs.QueenGraph(5,6,7,8,9)
Why not, but what would be the definition of valid movements?
2) Your input checks require n to be of type Integer. This excludes python ints and other things considered an integer. What about: "if n not in ZZ:"?
Yes, that's much better.
Thanks, D.
I'd think in directions. There are two types. The first type is defined by the nearest neighbours in the d-dimensional lattice, i.e. those points that change one coordinate by one. The second type is defined by the second nearest heighbours, i.e. those points that change the coordinate in two different dimensions by one each.
The allowed directions then are:
King: 1 + 2
Rook: 1
Bishop: 2
Queen: 1 + 2
Your definition for the knight makes sense.
I found a nice and generic way to implement all the chessboard graphs. I'm using a hidden function that takes many parameters and allows to add edges to all vertices along one dimension and/or on the diagonals of any pairs of dimensions and/or knight-like movements in any pairs of dimensions. The function also allows to control the radius of the visibility ball (could be useful).
Hope you'll like it.
Description changed:
---
+++
@@ -1,3 +1,4 @@
-This patch implements the generators for Queen, King, and Knight graphs.
+This patch implements generators for multi-dimensional chessboard graphs: Queen, King, Knight, Bishop, and Rook graphs. Variations of these graphs can be constructed changing the radius of the ball in which a chess piece can move.
These graphs are useful for testing graph coloring algorithms, hamiltonian cycles, etc.
+
Excellent idea to organize it that way!
Some coding comments though.
try:
8297 if isinstance(dim_list,dict):
8298 dim = [dim_list[a] for a in dim_list]
8299 else:
8300 dim = [a for a in dim_list]
8301 nb_dim = len(dim)
8302 except:
8303 raise ValueError('The first parameter must be an iterable object.')
1) if dim is a dict the keys aren't ordered. This means dim = {1: 2, 2: 3} might end up as dim = [3, 2] instead of [2,3]. Suggestion: dim = [dim_list[a] for a in sorted(dim_list)]
2) "dim = [a for a in dim_list]" can be replaced with "dim = list(dim_list)"
3) Never use except statements without an exception type to be catched. The reason is that this also catches things like SystemExit, which is raised by CTRL+C. Suggestion: "except TypeError:"
dimstr = ''
8307 for a in dim:
8308 if not a in ZZ or a < 1:
8309 raise ValueError('The dimensions must be positive integers larger than 1.')
8310 if dimstr == '':
8311 dimstr = '('+str(a)
8312 else:
8313 dimstr += ','+str(a)
8314 dimstr += ')'
4) This could be split into:
if any(a not in ZZ or a < 1 for a in dim):
raise ValueError('The dimensions must be positive integers larger than 1.')
dimstr = '(%s)' % "".join(dim)
5) In the code flowing code, there are checks like "rook_radius < 1 or not rook_radius in ZZ:". These could be reversed, i.e. "not rook_radius in ZZ or rook_radius < 1". The reason is that the comparison might raise an exception if it doesn't make sense.
6)
8331 v = [0 for a in dim]
8332 V = [v]
8332 V = [ [0]*nb_dim ]
7) In the code below, there are some instances of "u = [x for x in v]". These should be replaced by "u = v[:]".
8)
8343 combin = combinations([i for i in xrange(nb_dim)],2)
8343 combin = combinations(range(nb_dim),2)
I hope I don't discourage you with my nitpicking. Most the comments concern only style and efficiency, the only show stopper is 3).
Thanks for the propositions. I have incorporated all of them but the following which causes a type error
sage: dim = [2,3,4,5]
sage: dimstr = '(%s)' % "".join(dim)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/Users/dcoudert/<ipython console> in <module>()
TypeError: sequence item 0: expected string, int found
Instead, I use the following code which is in fact easier:
dimstr = str(tuple(dim))
This is much better now !
1) There are white space issues, see patchbot output.
2) I would have expected the following:
G = graphs.QueenGraph( [3,3,3], radius=1 );
len(G.neighbors((1,1,1))) == 26
but the result is 18. This is because the second nearest neighbors in the third dimension are missing.
Replying to @sagetrac-sluther:
1) There are white space issues, see patchbot output.
Removed. Why isn't it automatic :(
2) I would have expected the following:
G = graphs.QueenGraph( [3,3,3], radius=1 ); len(G.neighbors((1,1,1))) == 26
but the result is 18. This is because the second nearest neighbors in the third dimension are missing.
I disagree. The correct result is 18.
Replying to @dcoudert:
Replying to @sagetrac-sluther:
2) I would have expected the following:
G = graphs.QueenGraph( [3,3,3], radius=1 ); len(G.neighbors((1,1,1))) == 26
but the result is 18. This is because the second nearest neighbors in the third dimension are missing.
I disagree. The correct result is 18.
- 26 is not multiple of 3. so you could have expected 24
- Although we have 8 neighbors per pairs of dimensions, the sum is not 24 but 18 since you must remove redundancy.
- in x,y you have 8 neighbors
- in x,z you also have 8 neighbors, but 2 of them were found with x,y => 6 more
- in y,z you have 8 neighbors, but 2 were already in x,y and 2 in x,z => 4 more
- 8+6+4 = 18
26 = 3**3-1
In general I would expect 3**d -1
directions. They are defined by the 3^d
points in {-1,0,1}^d
. Only the central point doesn't define a direction.
We said before (#comment:4) that the Queen could move either in 1 dimension or in 2 dimensions, and adding an edge from (1,1,1) to (2,2,2) means moving in the 3 dimensions. That's why 8 points are not reachable from (1,1,1).
In general I would expect
3**d -1
directions. They are defined by the3^d
points in{-1,0,1}^d
. Only the central point doesn't define a direction.
I don't understand.
Replying to @dcoudert:
We said before (#comment:4) that the Queen could move either in 1 dimension or in 2 > dimensions, and adding an edge from (1,1,1) to (2,2,2) means moving in the 3 dimensions. That's why 8 points are not reachable from (1,1,1).
You're right that's what I said, but not what I meant. Sorry.
In general I would expect
3**d -1
directions. They are defined by the3^d
points in{-1,0,1}^d
. Only the central point doesn't define a direction.I don't understand.
A point in the d-dimensional lattice has d integer coordinates, say x_i (i=1..d). All points with x_i restricted to the set {-1,0,1} (for all i), lie in a hypercube.
This hypercube:
is centered at the origin
has all edges parralel to the coordinate axes
has only edges of lenght 2
contains exactly 3^d
lattice points
Now define a valid direction as the vector from the origin (0,0,...,0) to any other of the 3^d-1
points.
And here is the fun question: Which definition makes more sense?
I'd propse the following: If you don't feel like putting more work into this, we'll leave it as is. If you're willing to work on it: What about adding a parameter, say 'higher_diagonals' that switches between the two definitions?
I prefer to let the patch as it is for now.
If one needs it, we can latter add this "super-queen" definition. Also, your alternative definition should also be used for bishops and it would make bishops much more powerful than rooks (only able to move along one dimension at a time). And what about knights?
Reviewer: Sebastian Luther
The n\equiv 1,5 \pmod(6)
in the QueenGraph doc string looks strange, both on the command line and in the html doc.
Once this is fixed, I'll give it a positive review.
I changed it to n\equiv 1,5 \bmod{6}
and the output is now correct: n\equiv 1,5 (mod 6).
Tests good, docs good -> positive review
Many thanks for the help improving this patch.
This patch adds again a considerable amount of code to sage/graphs/graph_generators.py
.
At some point, I will have to refuse such patches before that file gets really too big.
Then what could be the solution: split the file into several pieces (graph_generators_1.py, graph_generators_2.py, etc...) with a bounded number of lines per file ?
Replying to @dcoudert:
Then what could be the solution: split the file into several pieces (graph_generators_1.py, graph_generators_2.py, etc...) with a bounded number of lines per file ?
Perhaps, although a better solution would be to group "related" graphs together.
For example, put all the code added in this ticket inside a new file
sage/graphs/generators/chessboard.py
I can try to do that, but I don't know how to expose the functions inside the GraphGenerators class. Should I use something like
import types
import sage.graphs.generators.chessboard
GraphGenerators.QueenGraph = types.MethodType(sage.graphs.generators.chessboard.QueenGraph, None, Graph)
I tried but it produces an error: ImportError: No module named generators.chessboard
Any help is more than welcome.
Did you add an __init__.py
to sage/graphs/generators?
I added such a file but it's still not working.
Is the procedure documented somewhere? I haven't find it in the documentation yet.
See [1] for how to add a new directory. But I'd say you should skip the addition of all.py and the addition to the existing all.py files as you want these things to be visible through the GraphGenerators class only.
After that add an import like "import sage.graphs.generators.chessboard" to graph_generators.py.
Then:
class GraphGenerators():
[...]
QueenGraph = sage.graphs.generators.chessboard.QueenGraph
[1] http://www.sagemath.org/doc/developer/coding_in_python.html#creating-a-new-directory
OK! it took me some time but know it's working! From my computer, everything is working (build, doc, tests,...). I have not added the new file for docbuild since the documentation of the functions are build with the documentation of graph_generator.py.
I hope this new version will satisfy everyone.
Description changed:
---
+++
@@ -2,3 +2,8 @@
These graphs are useful for testing graph coloring algorithms, hamiltonian cycles, etc.
+In addition, this patch creates directory `sage/graphs/generators/` to store new generators. The new functions of this patch are located in file `sage/graphs/generators/chessboard.py}}. The functions are then included inside the {{{GraphGenerators` class and so accessible like `graphs.QueenGraph(...)`.
+
+APPLY:
+* [attachment: trac_13306-queen-king-knight-graphs-v2.patch](https://github.com/sagemath/sage-prod/files/10656076/trac_13306-queen-king-knight-graphs-v2.patch.gz)
+
Description changed:
---
+++
@@ -2,7 +2,7 @@
These graphs are useful for testing graph coloring algorithms, hamiltonian cycles, etc.
-In addition, this patch creates directory `sage/graphs/generators/` to store new generators. The new functions of this patch are located in file `sage/graphs/generators/chessboard.py}}. The functions are then included inside the {{{GraphGenerators` class and so accessible like `graphs.QueenGraph(...)`.
+In addition, this patch creates directory `sage/graphs/generators/` to store new generators. The new functions of this patch are located in file `sage/graphs/generators/chessboard.py`. The functions are then included inside the `GraphGenerators` class and so accessible like `graphs.QueenGraph(...)`.
APPLY:
* [attachment: trac_13306-queen-king-knight-graphs-v2.patch](https://github.com/sagemath/sage-prod/files/10656076/trac_13306-queen-king-knight-graphs-v2.patch.gz)
Addition of line # This file is not empty !
in file __init__.py
as Nathann told me we should not have empty files.
Could anyone review this patch ? Thanks.
(cc me)
Do we really need to import sage.graphs.generators.chessboard at startup?
Replying to @robertwb:
Do we really need to import sage.graphs.generators.chessboard at startup?
I don't know.
Following Jeroen's suggestion, I have created a new directory to store graph generators instead of continuously increasing the size of sage.graphs.graph_generators.py. Later, we could split the graph_generators file and create smaller files, easier to read, faster to test, etc. in the generators directory.
Now, the question is how to make these functions accessible from graphs (e.g., graphs.QueenGraph()) without importing the file at startup. Is there a way to import them the first time they are used? or any other interesting trick I'm not aware of?
You could try using lazy import. However, ignore that for now, as I think all of graph_generators should be lazily imported. #13562
Mostly looks good, but I would remove the double underscores around __ChessboardGraphGenerator__
Attachment: trac_13306-queen-king-knight-graphs-v2.patch.gz
Done.
Helloooooooooooooooooooooooooooooo !!
Well, that patch was muuuuuuch cleaner than I feared, given its size :-)
Here is a list of comments, and a small innocent reviewer's patch.
dim = list(dim_list)
which is perfect as it is.Nathann
Description changed:
---
+++
@@ -6,4 +6,4 @@
APPLY:
* [attachment: trac_13306-queen-king-knight-graphs-v2.patch](https://github.com/sagemath/sage-prod/files/10656076/trac_13306-queen-king-knight-graphs-v2.patch.gz)
-
+* [attachment: trac_13306-review.patch](https://github.com/sagemath/sage-prod/files/10656077/trac_13306-review.patch.gz)
I'm unable to install the review patch. Have you make it using the file I have uploaded this morning in which I have removed double underscores ?
- Default values : rook = True, bishop = True, knight = False : that's weird. Why not set them all to True or all to False ?
That way the default behavior is QueenGraph, which is the most common chessboard graph. But all default parameters are OK for me.
- dim_list : it takes any iterable as an input, and you say that it takes sets or even dicts ! That's asking for trouble because the order in which the elements are listed in sets and dicts is platform-dependent, but then you specifically SORT the elements by key value when the inout is a dict, and take the VALUES into account. That's not what it is expected. A dict is an iterable, but list(my_dict) lists its keys, not values ! It would make more sense to remove the part of the code that deals with dict (why especially dicts, by the way ? One can make custom iterables !), and just use your
dim = list(dim_list)
which is perfect as it is.
That's right. Can you insert this in the review patch?
- I replaced "at least" or "least" by ">=". This way you know whether ">=" or ">" is intended, which is never clear with "at least" :-P
- Replaced a block of code by itertools.product
I didn't know that command. Very nice.
- Added many "`" for tuples that could appear in LaTeX instead.
I'm unable to install the review patch. Have you make it using the file I have uploaded this morning in which I have removed double underscores ?
O_o
I thought I did. And none of the patch I had applied before changed chessboard.py. Well, I saw the errors when applying the patches and rebased it. Weird, but done.
That way the default behavior is QueenGraph, which is the most common chessboard graph. But all default parameters are OK for me.
Just set them all to True
That's right. Can you insert this in the review patch?
Done.
Patch updated !
Nathann
Attachment: trac_13306-review.patch.gz
Now it's working and the doc is nicer. Thanks.
I didn't know the product
function and the way you use it is really nice.
Well.. Then "if you agree with those changes", let's get this ticket in :-)
Nathann
I agree with your changes. Thanks.
Arf. I thought you would change the ticket's status :-)
Nathann
Changed reviewer from Sebastian Luther to Sebastian Luther, Nathann Cohen
Thanks!
Merged: sage-5.5.beta0
This patch implements generators for multi-dimensional chessboard graphs: Queen, King, Knight, Bishop, and Rook graphs. Variations of these graphs can be constructed changing the radius of the ball in which a chess piece can move.
These graphs are useful for testing graph coloring algorithms, hamiltonian cycles, etc.
In addition, this patch creates directory
sage/graphs/generators/
to store new generators. The new functions of this patch are located in filesage/graphs/generators/chessboard.py
. The functions are then included inside theGraphGenerators
class and so accessible likegraphs.QueenGraph(...)
.APPLY:
Component: graph theory
Keywords: generator
Author: David Coudert
Reviewer: Sebastian Luther, Nathann Cohen
Merged: sage-5.5.beta0
Issue created by migration from https://trac.sagemath.org/ticket/13306