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

graphs: add implementation of slice decomposition via an extended LexBFS algorithm #38299

Merged

Conversation

cyrilbouvier
Copy link
Contributor

This PR implements a new graph decomposition: slice decomposition. Precise definition and a description of the algorithm can be found in TCHP2008 (section 3.2 & 3.3).

I implemented a new method (only for undirected graphs) called slice_decomposition. It returns a new class SliceDecompostion, with methods to retrieve the information about the computed slice decomposition.
The code is in a new file: graph_decompositions/slice_decomposition.pyx.

The actual computation is done with a new function called extended_lex_BFS which only works for undirected graphs. It is very close to the previous lex_BFS_fast_short_digraph from traversals.pyx, the difference being that the new function works with the CGraph directly (no conversion needed to short_digraph anymore) and it computes more information (lexicographic labels and length of x-slices). The complexity of the two algorithms are the same.
So I removed lex_BFS_fast_short_digraph from traversals.pyx and used extended_lex_BFS instead for the "fast" version of the lex_BFS method.

I took the opportunity to factorize the code between lex_BFS ("slow" version), lex_DFS, lex_UP and lex_DOWN
in traversals.pyx: there is no more conversion to short_digraph and they all call the same common function
(remark: i was not able to put the doc in common, so there is still some repetition between the doc of these methods)

📝 Checklist

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

⌛ Dependencies

Copy link

github-actions bot commented Jun 28, 2024

Documentation preview for this PR (built with commit 0d26f30; changes) is ready! 🎉
This preview will update shortly after each push to this PR.

Copy link
Contributor

@dcoudert dcoudert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not easy to review (large PR) but I like it. Thank you. I have a few minor comments.

src/sage/graphs/traversals.pyx Outdated Show resolved Hide resolved
src/sage/graphs/traversals.pyx Outdated Show resolved Hide resolved
src/sage/graphs/traversals.pyx Outdated Show resolved Hide resolved
Copy link
Contributor

@dcoudert dcoudert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like what you did in traversals.pyx.
I just have a few more minor remarks.

src/sage/graphs/traversals.pyx Outdated Show resolved Hide resolved
src/sage/graphs/traversals.pyx Outdated Show resolved Hide resolved
src/sage/graphs/traversals.pyx Outdated Show resolved Hide resolved
src/sage/graphs/traversals.pyx Outdated Show resolved Hide resolved
@cyrilbouvier
Copy link
Contributor Author

you should rebase on last beta.

done

Copy link
Contributor

@dcoudert dcoudert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@cyrilbouvier
Copy link
Contributor Author

I found a bug in the _latex_ method this morning, I fix it in 7f6cc5e: some $ are needed to represent the latex repr of the vertices (for simple types like integer, it is not needed, but for "complex" types like tuple it is)

Copy link
Contributor

@dcoudert dcoudert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch. LGTM.

vbraun pushed a commit to vbraun/sage that referenced this pull request Sep 6, 2024
…ia an extended LexBFS algorithm

    
<!-- ^ 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 a new graph decomposition: slice decomposition.
Precise definition and a description of the algorithm can be found in
[TCHP2008 (section 3.2 & 3.3)](https://arxiv.org/pdf/0710.3901v3).

I implemented a new method (only for undirected graphs) called
`slice_decomposition`. It returns a new class `SliceDecompostion`, with
methods to retrieve the information about the computed slice
decomposition.
The code is in a new file:
`graph_decompositions/slice_decomposition.pyx`.

 The actual computation is done with a new function called
`extended_lex_BFS` which only works for undirected graphs. It is very
close to the previous `lex_BFS_fast_short_digraph` from
`traversals.pyx`, the difference being that the new function works with
the `CGraph` directly (no conversion needed to `short_digraph` anymore)
and it computes more information (lexicographic labels and length of
x-slices). The complexity of the two algorithms are the same.
 So I removed `lex_BFS_fast_short_digraph` from `traversals.pyx` and
used `extended_lex_BFS` instead for the "fast" version of the `lex_BFS`
method.

I took the opportunity to factorize the code between `lex_BFS` ("slow"
version), `lex_DFS`, `lex_UP` and `lex_DOWN`
in `traversals.pyx`: there is no more conversion to `short_digraph` and
they all call the same common function
(remark: i was not able to put the doc in common, so there is still some
repetition between the doc of these methods)


### 📝 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.
- [ ] 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#38299
Reported by: cyrilbouvier
Reviewer(s): cyrilbouvier, David Coudert
@vbraun
Copy link
Member

vbraun commented Sep 7, 2024

On 32-bit:

**********************************************************************
File "src/sage/graphs/graph_decompositions/slice_decomposition.pyx", line 462, in sage.graphs.graph_decompositions.slice_decomposition.SliceDecomposition.__hash__
Failed example:
    hash(P3.slice_decomposition(initial_vertex=0))
Expected:
    -7313201005658437102
Got:
    1036537127
**********************************************************************
File "src/sage/graphs/graph_decompositions/slice_decomposition.pyx", line 464, in sage.graphs.graph_decompositions.slice_decomposition.SliceDecomposition.__hash__
Failed example:
    hash(P3.slice_decomposition(initial_vertex=2))
Expected:
    1181676064626878036
Got:
    440136178
**********************************************************************
File "src/sage/graphs/graph_decompositions/slice_decomposition.pyx", line 466, in sage.graphs.graph_decompositions.slice_decomposition.SliceDecomposition.__hash__
Failed example:
    hash(graphs.CompleteGraph(3).slice_decomposition())
Expected:
    6162668211142297415
Got:
    151055093
**********************************************************************
File "src/sage/graphs/graph_decompositions/slice_decomposition.pyx", line 468, in sage.graphs.graph_decompositions.slice_decomposition.SliceDecomposition.__hash__
Failed example:
    hash(Graph([(0,1), (0,2)]).slice_decomposition())
Expected:
    2898184589667302557
Got:
    -1278831260
**********************************************************************
1 item had failures:
   4 of   6 in sage.graphs.graph_decompositions.slice_decomposition.SliceDecomposition.__hash__
    [132 tests, 4 failures, 0.14 s]
----------------------------------------------------------------------
sage -t --long --random-seed=0 src/sage/graphs/graph_decompositions/slice_decomposition.pyx  # 4 doctests failed
----------------------------------------------------------------------

@cyrilbouvier
Copy link
Contributor Author

On 32-bit:

**********************************************************************
File "src/sage/graphs/graph_decompositions/slice_decomposition.pyx", line 462, in sage.graphs.graph_decompositions.slice_decomposition.SliceDecomposition.__hash__
Failed example:
    hash(P3.slice_decomposition(initial_vertex=0))
Expected:
    -7313201005658437102
Got:
    1036537127
**********************************************************************
File "src/sage/graphs/graph_decompositions/slice_decomposition.pyx", line 464, in sage.graphs.graph_decompositions.slice_decomposition.SliceDecomposition.__hash__
Failed example:
    hash(P3.slice_decomposition(initial_vertex=2))
Expected:
    1181676064626878036
Got:
    440136178
**********************************************************************
File "src/sage/graphs/graph_decompositions/slice_decomposition.pyx", line 466, in sage.graphs.graph_decompositions.slice_decomposition.SliceDecomposition.__hash__
Failed example:
    hash(graphs.CompleteGraph(3).slice_decomposition())
Expected:
    6162668211142297415
Got:
    151055093
**********************************************************************
File "src/sage/graphs/graph_decompositions/slice_decomposition.pyx", line 468, in sage.graphs.graph_decompositions.slice_decomposition.SliceDecomposition.__hash__
Failed example:
    hash(Graph([(0,1), (0,2)]).slice_decomposition())
Expected:
    2898184589667302557
Got:
    -1278831260
**********************************************************************
1 item had failures:
   4 of   6 in sage.graphs.graph_decompositions.slice_decomposition.SliceDecomposition.__hash__
    [132 tests, 4 failures, 0.14 s]
----------------------------------------------------------------------
sage -t --long --random-seed=0 src/sage/graphs/graph_decompositions/slice_decomposition.pyx  # 4 doctests failed
----------------------------------------------------------------------

Should be fixed by 0d26f30
I remove the hardcoded values from the tests and add a indirect doctest

sage: P3 = graphs.PathGraph(3)
sage: SD1 = P3.slice_decomposition(initial_vertex=0)
sage: SD2 = P3.slice_decomposition(initial_vertex=2)
sage: len({SD1: 1, SD2: 2}) # indirect doctest
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems ok, but why not simply hash(SD1) != hash(SD2) ?

Copy link
Contributor Author

@cyrilbouvier cyrilbouvier Sep 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got the idea by looking at other doctests for other __hash__ methods.
By thinking a little about it, there is a nonzero probability that there exists an architecture where the hashes could be equal. But as keys of a dict are compare via __eq__ if they have the same hashes, even in this (very very) improbable case the test should pass.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. Thank you for the clarification.

Copy link
Contributor

@dcoudert dcoudert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

vbraun pushed a commit to vbraun/sage that referenced this pull request Sep 8, 2024
…ia an extended LexBFS algorithm

    
<!-- ^ 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 a new graph decomposition: slice decomposition.
Precise definition and a description of the algorithm can be found in
[TCHP2008 (section 3.2 & 3.3)](https://arxiv.org/pdf/0710.3901v3).

I implemented a new method (only for undirected graphs) called
`slice_decomposition`. It returns a new class `SliceDecompostion`, with
methods to retrieve the information about the computed slice
decomposition.
The code is in a new file:
`graph_decompositions/slice_decomposition.pyx`.

 The actual computation is done with a new function called
`extended_lex_BFS` which only works for undirected graphs. It is very
close to the previous `lex_BFS_fast_short_digraph` from
`traversals.pyx`, the difference being that the new function works with
the `CGraph` directly (no conversion needed to `short_digraph` anymore)
and it computes more information (lexicographic labels and length of
x-slices). The complexity of the two algorithms are the same.
 So I removed `lex_BFS_fast_short_digraph` from `traversals.pyx` and
used `extended_lex_BFS` instead for the "fast" version of the `lex_BFS`
method.

I took the opportunity to factorize the code between `lex_BFS` ("slow"
version), `lex_DFS`, `lex_UP` and `lex_DOWN`
in `traversals.pyx`: there is no more conversion to `short_digraph` and
they all call the same common function
(remark: i was not able to put the doc in common, so there is still some
repetition between the doc of these methods)


### 📝 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.
- [ ] 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#38299
Reported by: cyrilbouvier
Reviewer(s): cyrilbouvier, David Coudert
vbraun pushed a commit to vbraun/sage that referenced this pull request Sep 10, 2024
…ia an extended LexBFS algorithm

    
<!-- ^ 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 a new graph decomposition: slice decomposition.
Precise definition and a description of the algorithm can be found in
[TCHP2008 (section 3.2 & 3.3)](https://arxiv.org/pdf/0710.3901v3).

I implemented a new method (only for undirected graphs) called
`slice_decomposition`. It returns a new class `SliceDecompostion`, with
methods to retrieve the information about the computed slice
decomposition.
The code is in a new file:
`graph_decompositions/slice_decomposition.pyx`.

 The actual computation is done with a new function called
`extended_lex_BFS` which only works for undirected graphs. It is very
close to the previous `lex_BFS_fast_short_digraph` from
`traversals.pyx`, the difference being that the new function works with
the `CGraph` directly (no conversion needed to `short_digraph` anymore)
and it computes more information (lexicographic labels and length of
x-slices). The complexity of the two algorithms are the same.
 So I removed `lex_BFS_fast_short_digraph` from `traversals.pyx` and
used `extended_lex_BFS` instead for the "fast" version of the `lex_BFS`
method.

I took the opportunity to factorize the code between `lex_BFS` ("slow"
version), `lex_DFS`, `lex_UP` and `lex_DOWN`
in `traversals.pyx`: there is no more conversion to `short_digraph` and
they all call the same common function
(remark: i was not able to put the doc in common, so there is still some
repetition between the doc of these methods)


### 📝 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.
- [ ] 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#38299
Reported by: cyrilbouvier
Reviewer(s): cyrilbouvier, David Coudert
vbraun pushed a commit to vbraun/sage that referenced this pull request Sep 12, 2024
…ia an extended LexBFS algorithm

    
<!-- ^ 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 a new graph decomposition: slice decomposition.
Precise definition and a description of the algorithm can be found in
[TCHP2008 (section 3.2 & 3.3)](https://arxiv.org/pdf/0710.3901v3).

I implemented a new method (only for undirected graphs) called
`slice_decomposition`. It returns a new class `SliceDecompostion`, with
methods to retrieve the information about the computed slice
decomposition.
The code is in a new file:
`graph_decompositions/slice_decomposition.pyx`.

 The actual computation is done with a new function called
`extended_lex_BFS` which only works for undirected graphs. It is very
close to the previous `lex_BFS_fast_short_digraph` from
`traversals.pyx`, the difference being that the new function works with
the `CGraph` directly (no conversion needed to `short_digraph` anymore)
and it computes more information (lexicographic labels and length of
x-slices). The complexity of the two algorithms are the same.
 So I removed `lex_BFS_fast_short_digraph` from `traversals.pyx` and
used `extended_lex_BFS` instead for the "fast" version of the `lex_BFS`
method.

I took the opportunity to factorize the code between `lex_BFS` ("slow"
version), `lex_DFS`, `lex_UP` and `lex_DOWN`
in `traversals.pyx`: there is no more conversion to `short_digraph` and
they all call the same common function
(remark: i was not able to put the doc in common, so there is still some
repetition between the doc of these methods)


### 📝 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.
- [ ] 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#38299
Reported by: cyrilbouvier
Reviewer(s): cyrilbouvier, David Coudert
@vbraun vbraun merged commit 2270e23 into sagemath:develop Sep 15, 2024
18 of 21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants