Skip to content

Commit

Permalink
sagemathgh-37956: faster implementation of method `sage.graphs.genera…
Browse files Browse the repository at this point in the history
…tors.families.BalancedTree`

    
We propose a direct implementation of the graph generator `BalancedTree`
that is faster than the previous method using networkx.

Before (using networkx)
```
sage: %timeit G = graphs.BalancedTree(3, 5)
550 µs ± 1.17 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
sage: %timeit G = graphs.BalancedTree(3, 7)
5.33 ms ± 37.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
sage: %timeit G = graphs.BalancedTree(4, 5)
2.13 ms ± 18.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
sage: %timeit G = graphs.BalancedTree(4, 7)
54.5 ms ± 278 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
```

With this PR
```
sage: %timeit G = graphs.BalancedTree(3, 5)
157 µs ± 809 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
sage: %timeit G = graphs.BalancedTree(3, 7)
1.44 ms ± 4.94 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops
each)
sage: %timeit G = graphs.BalancedTree(4, 5)
569 µs ± 6.78 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
sage: %timeit G = graphs.BalancedTree(4, 7)
9.52 ms ± 61.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
```


### 📝 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#37956
Reported by: David Coudert
Reviewer(s): David Coudert, Travis Scrimshaw
  • Loading branch information
Release Manager committed May 11, 2024
2 parents 78727d3 + e8f0782 commit 538c8b3
Showing 1 changed file with 35 additions and 16 deletions.
51 changes: 35 additions & 16 deletions src/sage/graphs/generators/families.py
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ def HammingGraph(n, q, X=None):

def BalancedTree(r, h):
r"""
Returns the perfectly balanced tree of height `h \geq 1`,
Return the perfectly balanced tree of height `h \geq 1`,
whose root has degree `r \geq 2`.
The number of vertices of this graph is
Expand All @@ -513,23 +513,18 @@ def BalancedTree(r, h):
OUTPUT:
The perfectly balanced tree of height `h \geq 1` and whose root has
degree `r \geq 2`. A :exc:`~networkx.exception.NetworkXError` is raised
if `r < 2` or `h < 1`.
ALGORITHM:
Uses the :ref:`NetworkX <spkg_networkx>` function
:func:`~networkx.generators.classic.balanced_tree`.
degree `r \geq 2`.
EXAMPLES:
A balanced tree whose root node has degree `r = 2`, and of height
`h = 1`, has order 3 and size 2::
sage: G = graphs.BalancedTree(2, 1); G # needs networkx
sage: G = graphs.BalancedTree(2, 1); G
Balanced tree: Graph on 3 vertices
sage: G.order(); G.size() # needs networkx
sage: G.order()
3
sage: G.size()
2
sage: r = 2; h = 1
sage: v = 1 + r
Expand All @@ -539,8 +534,9 @@ def BalancedTree(r, h):
Plot a balanced tree of height 5, whose root node has degree `r = 3`::
sage: G = graphs.BalancedTree(3, 5) # needs networkx
sage: G.show() # long time # needs networkx sage.plot
sage: G = graphs.BalancedTree(3, 5)
sage: G.plot() # long time # needs sage.plot
Graphics object consisting of 728 graphics primitives
A tree is bipartite. If its vertex set is finite, then it is planar. ::
Expand All @@ -563,17 +559,40 @@ def BalancedTree(r, h):
has degree `r \geq 2`, but the construction degenerates
gracefully::
sage: graphs.BalancedTree(1, 10) # needs networkx
sage: graphs.BalancedTree(1, 10)
Balanced tree: Graph on 11 vertices
Similarly, we usually want the tree must have height `h \geq 1`
but the algorithm also degenerates gracefully here::
sage: graphs.BalancedTree(3, 0) # needs networkx
sage: graphs.BalancedTree(3, 0)
Balanced tree: Graph on 1 vertex
The construction is the same as the one of networkx::
sage: # needs networkx
sage: import networkx
sage: r = randint(2, 4); h = randint(1, 5)
sage: T = graphs.BalancedTree(r, h)
sage: N = Graph(networkx.balanced_tree(r, h), name="Balanced tree")
sage: T.is_isomorphic(N)
True
"""
import networkx
return Graph(networkx.balanced_tree(r, h), name="Balanced tree")
# Compute the number of vertices per level of the tree
order = [r**l for l in range(h + 1)]
# Compute the first index of the vertices of a level
begin = [0]
begin.extend(begin[-1] + val for val in order)
# The number of vertices of the tree is the first index of level h + 1
T = Graph(begin[-1], name="Balanced tree")

# Add edges of the r-ary tree
for level in range(h):
start = begin[level + 1]
for u in range(begin[level], begin[level + 1]):
T.add_edges((u, v) for v in range(start, start + r))
start += r
return T


def BarbellGraph(n1, n2):
Expand Down

0 comments on commit 538c8b3

Please sign in to comment.