Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modular decomposition bug #25872

Closed
jm58660 mannequin opened this issue Jul 18, 2018 · 44 comments
Closed

Modular decomposition bug #25872

jm58660 mannequin opened this issue Jul 18, 2018 · 44 comments

Comments

@jm58660
Copy link
Mannequin

jm58660 mannequin commented Jul 18, 2018

sage: G1 = Graph('FwA]w')
sage: G2 = Graph('F@Nfg')
sage: G1.modular_decomposition(algorithm='tedder')
(PRIME, [6, 2, 1, 5, 0, (PARALLEL, [3, 4])])
sage: G2.modular_decomposition(algorithm='tedder')
(PRIME, [6, 5, 0, 2, 3, 1, 4])
sage: G1.is_isomorphic(G2)
True

#24898 was not enough.

This ticket removes 'tedder' implementation, as buggy unfixable abandonware (see #33902 for another example of a bug);
the algorithm= option is made into a no-op, to be removed after the deprecation period, as we only have one implementation now.

CC: @lokeshj1703 @dimpase @dcoudert @deinst

Component: graph theory

Author: Dima Pasechnik

Branch: f610e5a

Reviewer: David Coudert, Matthias Koeppe

Issue created by migration from https://trac.sagemath.org/ticket/25872

@jm58660 jm58660 mannequin added this to the sage-8.4 milestone Jul 18, 2018
@jm58660 jm58660 mannequin added c: graph theory labels Jul 18, 2018
@dcoudert
Copy link
Contributor

comment:1

That's certainly not an easy issue to fix. I have not clue what's going on :(

@jm58660
Copy link
Mannequin Author

jm58660 mannequin commented Jul 18, 2018

comment:2

I don't know if this helps, but I was cross-checking #25763 and it seems that the bug is not visible with

P._hasse_diagram.transitive_closure().to_undirected().is_prime()

where P is any poset. In the internal digraph we have consecutive integers as vertices and 0, 1, ..., n-1 is a topological sort of the digraph.

@dcoudert
Copy link
Contributor

comment:3

I tried other labelings of the graph and its working correctly when the first vertex of G.vertex_iterator() is not involved in the parallel node.

sage: G3 = Graph('F|NE?')
sage: G3.modular_decomposition()
(PRIME, [2, (PARALLEL, [5, 6]), 1, 3, 0, 4])

With 'G2', the construction starts from vertex 0 that should be in a parallel node (PARALLEL, [0, 1]). If I add a twin to vertex 4, the new parallel node is detected.

sage: G2.add_edges([(2,7), (3,7)])
sage: G2.modular_decomposition()
(PRIME, [6, 5, 0, 2, 3, 1, (PARALLEL, [4, 7])])

@lokeshj1703
Copy link

Branch: u/jlokesh/modular_decomposition_bug

@lokeshj1703
Copy link

Commit: b71307d

@lokeshj1703
Copy link

comment:5

I have pushed the changes which were required to fix the bug. The change required was to remove the is_separated field from Node class in modular_decomposition.py. It removes the optimization which was causing the bug.


New commits:

b71307dtrac #25872: Remove is_separated instance variable from Node class in modular_decomposition.py

@dcoudert
Copy link
Contributor

dcoudert commented Oct 7, 2018

comment:6

Thank you Lokesh.

You must add the following tests to the TESTS block of method modular_decomposition to show that the issue is fixed.

Ticket :trac:`25872` is fixed::

    sage: G1 = Graph('FwA]w')
    sage: G2 = Graph('F@Nfg')
    sage: G1.is_isomorphic(G2)
    True
    sage: G1.modular_decomposition()
    (PRIME, [6, 2, 1, 5, 0, (PARALLEL, [3, 4])])
    sage: G2.modular_decomposition()
    (PRIME, [6, 5, (PARALLEL, [0, 1]), 2, 3, 4])
    sage: G2.add_edges([(2,7), (3,7)])
    sage: G2.modular_decomposition()
    (PRIME, [6, 5, (PARALLEL, [0, 1]), 2, 3, (PARALLEL, [4, 7])])

@jm58660
Copy link
Mannequin Author

jm58660 mannequin commented Oct 8, 2018

comment:7

Still doesn't work.

sage: a = Graph('PdDoIHG?o@OeC?_BsWCSsI?c')
sage: b = a.canonical_label()
sage: a.is_prime(), b.is_prime()
(True, False)

Found by

set_random_seed(0)
for i in xrange(10^3):
    G1 = graphs.RandomGNP(17, 0.3)
    G2 = G1.canonical_label()
    if G1.is_prime() != G2.is_prime():
        print(i)
        G1.show()
        break
else:
    print("OK")

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Oct 8, 2018

Branch pushed to git repo; I updated commit sha1. New commits:

672a110trac #25872: Added tests in graph.py#modular_decomposition

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Oct 8, 2018

Changed commit from b71307d to 672a110

@lokeshj1703
Copy link

comment:9

Replying to @jm58660:

Still doesn't work.

Thanks for posting the example. Let me take a look.

@deinst
Copy link
Contributor

deinst commented Oct 16, 2018

comment:10

A few questions.

Would it be of use to add an algorithm parameter to modular_decomposition and is_prime? I have code for the O(n3) algorithm of [Habib and Maurer 1979] that is probably slower than the current code, but seems to work. Should I attempt to integrate it, and if so should I do it in this ticket or start a new one?

Should we move modular_decomposition.py into the src/sage/graphs/graph_decompositions directory?

In the testing section of modular_decomposition.py the function children_node_type is used to flag an error if all of the children of a SERIES or PARALLEL node are of the same type as their parent. I think that this is too loose and an error should be noted if any of the children have the same type as their parents, otherwise the condition that nodes in the tree represent maximal modules is violated.

@dcoudert
Copy link
Contributor

comment:11

This is a very good idea to add another algorithm and the parameter algorithm if it helps checking the validity of both algorithms. A slow algorithm is OK in such case.
However, it should be done in a separate ticket.

It is possible to move the file to src/sage/graphs/graph_decompositions while working on the new ticket.

@deinst
Copy link
Contributor

deinst commented Oct 16, 2018

comment:12

I added trac #26496. The code there should be functional if you add algorithm='habib' to each call to modular_decomposition or is_prime.

@dimpase
Copy link
Member

dimpase commented May 25, 2022

comment:13

see also #33902

How about removing 'tedder' completely?

@dimpase

This comment has been minimized.

@dimpase dimpase modified the milestones: sage-8.4, sage-9.7 May 25, 2022
@dcoudert
Copy link
Contributor

comment:14

I can only agree with that. The code is buggy and I don't know how to fix that.

@dimpase
Copy link
Member

dimpase commented May 25, 2022

comment:15

OK, I'll try doing this.

@dcoudert
Copy link
Contributor

comment:16

We can at least start with a deprecation warning.

@dimpase
Copy link
Member

dimpase commented May 25, 2022

@dimpase
Copy link
Member

dimpase commented May 25, 2022

Changed commit from 672a110 to c7e8063

@dimpase
Copy link
Member

dimpase commented May 25, 2022

Author: Dima Pasechnik

@dimpase
Copy link
Member

dimpase commented May 25, 2022

New commits:

c7e8063remove buggy 'tedder' modular decomposition

@dcoudert
Copy link
Contributor

comment:23

We should certainly update the ticket description to reflect the removal.

@dimpase

This comment has been minimized.

@mkoeppe
Copy link
Contributor

mkoeppe commented May 26, 2022

comment:25

the algorithm= option is removed, as we only have one implementation now.

This breaks existing code

@dcoudert
Copy link
Contributor

comment:26

So what should we do ? deprecate this option before removing tedder in a year ? remove tedder now and let this parameter even if unused with a deprecation ? something else ?

@mkoeppe
Copy link
Contributor

mkoeppe commented May 26, 2022

comment:27

Just make it so that passing algorithm='habib' does not become an error

@dimpase
Copy link
Member

dimpase commented May 26, 2022

comment:28

algorithm='tedder' should be an error now.

The problem is, however, not limited to this, as there is also a modular_decomposition(foo) function, which was equivalent to foo.modular_decomposition(algorithm='tedder'). In the present branch modular_decomposition(foo) became
equivalent to the (old) foo.modular_decomposition(algorithm='habib'), because, what else?

I think it's too much fuss to fiddle around with deprecations here.

@mkoeppe
Copy link
Contributor

mkoeppe commented May 26, 2022

comment:29

Just don't make these breaking API changes:

--- a/src/sage/graphs/graph.py
+++ b/src/sage/graphs/graph.py
@@ -7574,7 +7574,7 @@ class Graph(GenericGraph):
             return list(core.values())
 
     @doc_index("Leftovers")
-    def modular_decomposition(self, algorithm='habib', style='tuple'):
+    def modular_decomposition(self, style='tuple'):
         r"""
         Return the modular decomposition of the current graph.
 
@@ -8035,23 +8014,13 @@ class Graph(GenericGraph):
         return self.planar_dual().is_circumscribable(solver=solver, verbose=verbose)
 
     @doc_index("Graph properties")
-    def is_prime(self, algorithm='habib'):
+    def is_prime(self):
         r"""
         Test whether the current graph is prime.
 

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented May 26, 2022

Branch pushed to git repo; I updated commit sha1. New commits:

f610e5aretained 'algorithm=' with deprecation

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented May 26, 2022

Changed commit from 22f15f5 to f610e5a

@mkoeppe
Copy link
Contributor

mkoeppe commented May 26, 2022

Changed reviewer from David Coudert to David Coudert, Matthias Koeppe

@mkoeppe
Copy link
Contributor

mkoeppe commented May 26, 2022

comment:32

LGTM, thanks.

@vbraun
Copy link
Member

vbraun commented May 29, 2022

Changed branch from u/dimpase/graphs/remove_tedder_modular_decomposition to f610e5a

@dimpase
Copy link
Member

dimpase commented Jun 9, 2022

Changed commit from f610e5a to none

@dimpase

This comment has been minimized.

vbraun pushed a commit to vbraun/sage that referenced this issue Dec 11, 2024
… modular decomposition

    
<!-- ^ Please provide a concise and informative title. -->
<!-- ^ Don't put issue numbers in the title, do this in the PR
description below. -->
<!-- ^ For example, instead of "Fixes sagemath#12345" use "Introduce new method
to calculate 1 + 2". -->
<!-- v Describe your changes below in detail. -->
<!-- v Why is this change required? What problem does it solve? -->
<!-- v If this PR resolves an open issue, please link to it here. For
example, "Fixes sagemath#12345". -->

This PR implements the recursive, linear-time algorithm to compute the
modular decomposition of simple undirected graphs from
[TCHP2008](https://arxiv.org/pdf/0710.3901).

A previous implementation was introduced in version 9.7 but was removed
after some bugs were discovered (see sagemath#25872 for exemple).

This implementation is based on an updated version of the article and is
intensively tested.

This PR contains:
- a implementation in C++ of the algorithm (in the file
`graph_decompositions/modular_decomposition.hpp`) and the corresponding
interface file `graph_decompositions/modular_decomposition.pxd`
- a small reorganization of the method `modular_decomposition` of the
class Graph: this method now accept a parameter `algorithm` (that can be
'habib_maurer' for the previous algorithm, or
'corneil_habib_paul_tedder' for the new one, which is the default
value), it then call the function `modular_decomposition` from
`graph_decompositions/modular_decomposition.pyx` which dispatch the call
to the correct function (`habib_maurer_algorithm` or `
corneil_habib_paul_tedder_algorithm`)
- a new parameter `algorithm` for the `is_prime` method (which is passed
directly to the `modular_decomposition` method)
- a new `is_module` method for the Graph class
- a small clean up of the file
`graph_decompositions/modular_decomposition.pyx` to remove unused field
of the `Node` class and useless functions.
- a new `prime_node_generator` parameter for the `md_tree_to_graph`
(used for generating modular decomposition tree for tests)

In this PR, I did not change the output of the `modular_decomposition`
method to keep the changes to a minimum.
If this PR is accepted, I intend to do it in another PR. The goal would
be to return a object that contains all the information of the modular
decomposition tree: currently the two formats for the output have no
information for the prime graph corresponding to prime nodes. It can be
computed from the output of the new algorithm but this information is
lost during the conversion to one of the output format of the method
`modular_decomposition`.


### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->

- [x] The title is concise and informative.
- [x] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.
- [x] I have created tests covering the changes.
- [x] I have updated the documentation and checked the documentation
preview.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on. For example,
-->
<!-- - sagemath#12345: short description why this is a dependency -->
<!-- - sagemath#34567: ... -->
    
URL: sagemath#39038
Reported by: cyrilbouvier
Reviewer(s): cyrilbouvier, David Coudert
vbraun pushed a commit to vbraun/sage that referenced this issue Dec 12, 2024
… modular decomposition

    
<!-- ^ Please provide a concise and informative title. -->
<!-- ^ Don't put issue numbers in the title, do this in the PR
description below. -->
<!-- ^ For example, instead of "Fixes sagemath#12345" use "Introduce new method
to calculate 1 + 2". -->
<!-- v Describe your changes below in detail. -->
<!-- v Why is this change required? What problem does it solve? -->
<!-- v If this PR resolves an open issue, please link to it here. For
example, "Fixes sagemath#12345". -->

This PR implements the recursive, linear-time algorithm to compute the
modular decomposition of simple undirected graphs from
[TCHP2008](https://arxiv.org/pdf/0710.3901).

A previous implementation was introduced in version 9.7 but was removed
after some bugs were discovered (see sagemath#25872 for exemple).

This implementation is based on an updated version of the article and is
intensively tested.

This PR contains:
- a implementation in C++ of the algorithm (in the file
`graph_decompositions/modular_decomposition.hpp`) and the corresponding
interface file `graph_decompositions/modular_decomposition.pxd`
- a small reorganization of the method `modular_decomposition` of the
class Graph: this method now accept a parameter `algorithm` (that can be
'habib_maurer' for the previous algorithm, or
'corneil_habib_paul_tedder' for the new one, which is the default
value), it then call the function `modular_decomposition` from
`graph_decompositions/modular_decomposition.pyx` which dispatch the call
to the correct function (`habib_maurer_algorithm` or `
corneil_habib_paul_tedder_algorithm`)
- a new parameter `algorithm` for the `is_prime` method (which is passed
directly to the `modular_decomposition` method)
- a new `is_module` method for the Graph class
- a small clean up of the file
`graph_decompositions/modular_decomposition.pyx` to remove unused field
of the `Node` class and useless functions.
- a new `prime_node_generator` parameter for the `md_tree_to_graph`
(used for generating modular decomposition tree for tests)

In this PR, I did not change the output of the `modular_decomposition`
method to keep the changes to a minimum.
If this PR is accepted, I intend to do it in another PR. The goal would
be to return a object that contains all the information of the modular
decomposition tree: currently the two formats for the output have no
information for the prime graph corresponding to prime nodes. It can be
computed from the output of the new algorithm but this information is
lost during the conversion to one of the output format of the method
`modular_decomposition`.


### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->

- [x] The title is concise and informative.
- [x] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.
- [x] I have created tests covering the changes.
- [x] I have updated the documentation and checked the documentation
preview.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on. For example,
-->
<!-- - sagemath#12345: short description why this is a dependency -->
<!-- - sagemath#34567: ... -->
    
URL: sagemath#39038
Reported by: cyrilbouvier
Reviewer(s): cyrilbouvier, David Coudert
vbraun pushed a commit to vbraun/sage that referenced this issue Dec 13, 2024
… modular decomposition

    
<!-- ^ Please provide a concise and informative title. -->
<!-- ^ Don't put issue numbers in the title, do this in the PR
description below. -->
<!-- ^ For example, instead of "Fixes sagemath#12345" use "Introduce new method
to calculate 1 + 2". -->
<!-- v Describe your changes below in detail. -->
<!-- v Why is this change required? What problem does it solve? -->
<!-- v If this PR resolves an open issue, please link to it here. For
example, "Fixes sagemath#12345". -->

This PR implements the recursive, linear-time algorithm to compute the
modular decomposition of simple undirected graphs from
[TCHP2008](https://arxiv.org/pdf/0710.3901).

A previous implementation was introduced in version 9.7 but was removed
after some bugs were discovered (see sagemath#25872 for exemple).

This implementation is based on an updated version of the article and is
intensively tested.

This PR contains:
- a implementation in C++ of the algorithm (in the file
`graph_decompositions/modular_decomposition.hpp`) and the corresponding
interface file `graph_decompositions/modular_decomposition.pxd`
- a small reorganization of the method `modular_decomposition` of the
class Graph: this method now accept a parameter `algorithm` (that can be
'habib_maurer' for the previous algorithm, or
'corneil_habib_paul_tedder' for the new one, which is the default
value), it then call the function `modular_decomposition` from
`graph_decompositions/modular_decomposition.pyx` which dispatch the call
to the correct function (`habib_maurer_algorithm` or `
corneil_habib_paul_tedder_algorithm`)
- a new parameter `algorithm` for the `is_prime` method (which is passed
directly to the `modular_decomposition` method)
- a new `is_module` method for the Graph class
- a small clean up of the file
`graph_decompositions/modular_decomposition.pyx` to remove unused field
of the `Node` class and useless functions.
- a new `prime_node_generator` parameter for the `md_tree_to_graph`
(used for generating modular decomposition tree for tests)

In this PR, I did not change the output of the `modular_decomposition`
method to keep the changes to a minimum.
If this PR is accepted, I intend to do it in another PR. The goal would
be to return a object that contains all the information of the modular
decomposition tree: currently the two formats for the output have no
information for the prime graph corresponding to prime nodes. It can be
computed from the output of the new algorithm but this information is
lost during the conversion to one of the output format of the method
`modular_decomposition`.


### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->

- [x] The title is concise and informative.
- [x] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.
- [x] I have created tests covering the changes.
- [x] I have updated the documentation and checked the documentation
preview.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on. For example,
-->
<!-- - sagemath#12345: short description why this is a dependency -->
<!-- - sagemath#34567: ... -->
    
URL: sagemath#39038
Reported by: cyrilbouvier
Reviewer(s): cyrilbouvier, David Coudert
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants