@@ -339,3 +339,123 @@ def is_cartesian_product(g, certificate=False, relabeling=False):
339
339
return factors
340
340
else :
341
341
return True
342
+
343
+
344
+ def rooted_product (G , H , root = None ):
345
+ r """
346
+ Return the rooted product of `G` and `H`.
347
+
348
+ The rooted product of two graphs `G` and `H` is the graph `R` defined as
349
+ follows: take a copy of `G` and `| V( G) | ` copies of `H`, and for every vertex
350
+ `g_i` of `G`, identify `g_i` with the root of the `i`-th copy of `H`.
351
+ Mode formally, let `V( G) = \{ g_1, g_2, \l dots, g_n\} `,
352
+ `V( H) = \{ h_1, h_2, \l dots, h_m\} `, and let `h_1` be the root vertex of `H`.
353
+ The vertex set `V( R) ` is equal to the cartesian product of the sets of
354
+ vertices `V( G) ` and `V( H) `, that is
355
+ `V( R) = \{ ( g_i, h_j) : g_i \i n V( G) , h_j \i n V( H) \} `. The edge set `E( R) `
356
+ is the union of the edges of a copy of `G`, that is
357
+ `\{ (( g_i, h_1) , ( g_j, h_1)) : ( g_i, g_j) \i n E( G) \} `, and the edges of the
358
+ copies of `H` for every `g_i \i n V( G) `, that is
359
+ `\{ (( g_i, h_j) , ( g_i, h_k)) : ( h_j, h_k) \i n V( H) \} `.
360
+
361
+ See :wikipedia:`Rooted_product_of_graphs` for more details.
362
+
363
+ .. SEEALSO::
364
+
365
+ - :meth:`~sage. graphs. generic_graph. cartesian_product`
366
+ -- return the cartesian product of two graphs
367
+
368
+ - :mod:`~sage. graphs. graph_decompositions. graph_products`
369
+ -- a module on graph products
370
+
371
+ EXAMPLES:
372
+
373
+ The rooted product of two trees is a tree::
374
+
375
+ sage: T1 = graphs. RandomTree( 7)
376
+ sage: T2 = graphs. RandomTree( 8)
377
+ sage: T = T1. rooted_product( T2)
378
+ sage: T. is_tree( )
379
+ True
380
+
381
+ The rooted product of `G` and `H` depends on the selected root in `H`::
382
+
383
+ sage: G = graphs. CycleGraph( 4)
384
+ sage: H = graphs. PathGraph( 3)
385
+ sage: R1 = G. rooted_product( H, root=0)
386
+ sage: R2 = G. rooted_product( H, root=1)
387
+ sage: R1. is_isomorphic( R2)
388
+ False
389
+ sage: sorted( R1. degree( ))
390
+ [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 ]
391
+ sage: sorted( R2. degree( ))
392
+ [1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4 ]
393
+
394
+ The domination number of the rooted product of any graph `G` and a path of
395
+ order 2 is the order of `G`::
396
+
397
+ sage: G = graphs. RandomGNP( 20, . 3)
398
+ sage: P = graphs. PathGraph( 2)
399
+ sage: R = G. rooted_product( P)
400
+ sage: len( R. dominating_set( )) == G. order( )
401
+ True
402
+ sage: G = digraphs. RandomDirectedGNP( 20, . 3)
403
+ sage: P = digraphs. Path( 2)
404
+ sage: R = G. rooted_product( P)
405
+ sage: len( R. dominating_set( )) == G. order( )
406
+ True
407
+
408
+ The rooted product of two graphs is a subgraph of the cartesian product of
409
+ the same two graphs::
410
+
411
+ sage: G = graphs. RandomGNP( 6, . 4)
412
+ sage: H = graphs. RandomGNP( 7, . 4)
413
+ sage: R = G. rooted_product( H)
414
+ sage: C = G. cartesian_product( H)
415
+ sage: R. is_subgraph( C, induced=False)
416
+ True
417
+
418
+ Corner cases::
419
+
420
+ sage: Graph( ) . rooted_product( Graph( ))
421
+ Rooted product of Graph on 0 vertices and Graph on 0 vertices: Graph on 0 vertices
422
+ sage: Graph( 1) . rooted_product( Graph( ))
423
+ Rooted product of Graph on 1 vertex and Graph on 0 vertices: Graph on 0 vertices
424
+ sage: Graph( ) . rooted_product( Graph( 1))
425
+ Rooted product of Graph on 0 vertices and Graph on 1 vertex: Graph on 0 vertices
426
+ sage: Graph( 1) . rooted_product( Graph( 1))
427
+ Rooted product of Graph on 1 vertex and Graph on 1 vertex: Graph on 1 vertex
428
+
429
+ TESTS::
430
+
431
+ sage: Graph( ) . rooted_product( DiGraph( ))
432
+ Traceback ( most recent call last) :
433
+ ...
434
+ TypeError: the graphs should be both directed or both undirected
435
+ """
436
+ G._scream_if_not_simple(allow_loops = True )
437
+ if G._directed and H._directed:
438
+ from sage.graphs.digraph import DiGraph
439
+ R = DiGraph(loops = (G.has_loops() or H.has_loops()))
440
+ elif (not G._directed) and (not H._directed):
441
+ from sage.graphs.graph import Graph
442
+ R = Graph(loops = (G.has_loops() or H.has_loops()))
443
+ else :
444
+ raise TypeError (' the graphs should be both directed or both undirected' )
445
+
446
+ R.name(f' Rooted product of {G} and {H}' )
447
+
448
+ if not G or not H:
449
+ return R
450
+ if root is None :
451
+ root = next(H.vertex_iterator())
452
+ elif root not in H:
453
+ raise ValueError (" the specified root is not a vertex of H" )
454
+
455
+ R.add_vertices((u, x) for u in G for x in H)
456
+ for u, v in G.edge_iterator(labels = False ):
457
+ R.add_edge((u, root), (v, root))
458
+ for x, y in H.edge_iterator(labels = False ):
459
+ R.add_edges(((u, x), (u, y)) for u in G)
460
+
461
+ return R
0 commit comments