Skip to content

Commit e3dff82

Browse files
committed
added Caterpillar()
1 parent 5c8d9e9 commit e3dff82

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

src/sage/graphs/generators/trees.pyx

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,102 @@ def FibonacciTree(n):
274274
return T
275275

276276

277+
def Caterpillar(spine):
278+
r"""
279+
Return the caterpillar tree with given spine sequence.
280+
281+
A caterpillar tree consists of leaves attached to a path (the "spine").
282+
283+
INPUT:
284+
285+
- ``spine`` -- list of nonnegative integers in the form
286+
`[a_1, a_2, \dots, a_n]`, where `a_i` is the number of leaves adjacent
287+
to the `i`-th vertex on the spine (except for the first and last vertex,
288+
which have `a_1 + 1` and `a_n + 1` leaf-neighbors, respectively)
289+
290+
OUTPUT:
291+
292+
A caterpillar tree of diameter `n+1` on `n + 2 + \sum_{i=1}^n a_i` vertices,
293+
`n` of which are not leaves.
294+
295+
PLOTTING: Upon construction, the position dictionary is filled to override
296+
the spring-layout algorithm if the returned graph does not have too many
297+
vertices. The spine vertices are positioned on a straight line together
298+
with two leaves at its ends. Every edge in the drawing has unit length.
299+
300+
EXAMPLES:
301+
302+
Caterpillars with all-zero spine sequence are paths::
303+
304+
sage: graphs.Caterpillar([]).is_isomorphic(graphs.PathGraph(2))
305+
True
306+
sage: graphs.Caterpillar([0]).is_isomorphic(graphs.PathGraph(3))
307+
True
308+
sage: graphs.Caterpillar([0, 0]).is_isomorphic(graphs.PathGraph(4))
309+
True
310+
311+
Caterpillars with singleton spine are stars::
312+
313+
sage: graphs.Caterpillar([1]).is_isomorphic(graphs.StarGraph(3))
314+
True
315+
sage: graphs.Caterpillar([2]).is_isomorphic(graphs.StarGraph(4))
316+
True
317+
sage: graphs.Caterpillar([3]).is_isomorphic(graphs.StarGraph(5))
318+
True
319+
320+
Distinct spine sequences can yield isomorphic caterpillars::
321+
322+
sage: graphs.Caterpillar([1,1,2]).is_isomorphic(graphs.Caterpillar([2,1,1]))
323+
True
324+
325+
TESTS:
326+
327+
Generated graphs have diameter ``len(spine) + 1``::
328+
329+
sage: graphs.Caterpillar([7]).diameter()
330+
2
331+
sage: graphs.Caterpillar([2,2,2,2]).diameter()
332+
5
333+
sage: graphs.Caterpillar([0,1,1,0]).diameter()
334+
5
335+
"""
336+
spine = list(spine)
337+
cdef int spine_len = len(spine)
338+
cdef int n_vertices = spine_len + 2 + sum(spine)
339+
T = Graph(n_vertices, name=f"Caterpillar({','.join(map(str, spine))})")
340+
341+
# add spine
342+
for i in range(spine_len - 1):
343+
T._backend.add_edge(i, i + 1, None, False)
344+
345+
# add a leaf at both ends of the spine
346+
T._backend.add_edge(spine_len + 1, 0, None, False)
347+
if spine:
348+
T._backend.add_edge(spine_len - 1, spine_len, None, False)
349+
350+
# add leaves
351+
cdef int v = spine_len + 2
352+
for i, d in enumerate(spine):
353+
for j in range(d):
354+
T._backend.add_edge(i, v + j, None, False)
355+
v += d
356+
357+
# add embedding
358+
cdef int max_leaves = max(spine, default=0)
359+
if (spine_len < 10 and max_leaves < 3) or (spine_len < 6 and max_leaves < 7):
360+
T._pos = {spine_len + 1: (-1, 0), spine_len: (spine_len, 0)}
361+
radius = 0.3
362+
v = spine_len + 2
363+
for x, d in enumerate(spine):
364+
T._pos[x] = (x, 0)
365+
mid = v + d // 2
366+
T._line_embedding(range(v, mid), first=(x - radius, 1), last=(x + radius, 1))
367+
T._line_embedding(range(mid, v + d), first=(x - radius, -1), last=(x + radius, -1))
368+
v += d
369+
370+
return T
371+
372+
277373
def RandomLobster(n, p, q, seed=None):
278374
r"""
279375
Return a random lobster.

src/sage/graphs/graph_generators.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ def wrap_name(x):
383383
__append_to_doc(
384384
["BalancedTree",
385385
"FibonacciTree",
386+
"Caterpillar",
386387
"RandomLobster",
387388
"RandomTree",
388389
"RandomTreePowerlaw",
@@ -2872,6 +2873,7 @@ def quadrangulations(self, order, minimum_degree=None, minimum_connectivity=None
28722873
BalancedTree = staticmethod(gen_trees.BalancedTree)
28732874
FibonacciTree = staticmethod(gen_trees.FibonacciTree)
28742875
nauty_gentreeg = staticmethod(gen_trees.nauty_gentreeg)
2876+
Caterpillar = staticmethod(gen_trees.Caterpillar)
28752877
RandomLobster = staticmethod(gen_trees.RandomLobster)
28762878
RandomTreePowerlaw = staticmethod(gen_trees.RandomTreePowerlaw)
28772879
RandomTree = staticmethod(gen_trees.RandomTree)

0 commit comments

Comments
 (0)