@@ -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, \d ots, 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 + \s um_{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+
277373def RandomLobster (n , p , q , seed = None ):
278374 r """
279375 Return a random lobster.
0 commit comments