Skip to content

Commit

Permalink
gh-36584: implemented power of graph function under basic methods
Browse files Browse the repository at this point in the history
    
### Description

This PR introduces a new function, `power_of_graph`, to compute the kth
power of an undirected, unweighted graph efficiently using the shortest
distances method. The proposed function leverages Breadth-First Search
(BFS) to calculate the power graph, providing a practical and scalable
solution.

### Why is this change required?

The change is required to address the need for efficiently calculating
the kth power of a graph, a fundamental operation in graph theory. The
PR aims to incorporate this feature into the SageMath library.

Fixes #36582

### Checklist

- [x] The title is concise, informative, and self-explanatory.
- [x] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion (if applicable).
- [x] I have created tests covering the changes.
- [x] I have updated the documentation accordingly.

### ⌛ Dependencies

#36582 : To implement power of graph
    
URL: #36584
Reported by: saatvikraoIITGN
Reviewer(s): David Coudert, saatvikraoIITGN
  • Loading branch information
Release Manager committed Dec 4, 2023
2 parents 8801f6e + e0dc49d commit caa1068
Showing 1 changed file with 89 additions and 0 deletions.
89 changes: 89 additions & 0 deletions src/sage/graphs/generic_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -15785,6 +15785,95 @@ def distance_all_pairs(self, by_weight=False, algorithm=None,
weight_function=weight_function,
check_weight=check_weight)[0]

def power(self, k):
r"""
Return the `k`-th power graph of ``self``.

In the `k`-th power graph of a graph `G`, there is an edge between
any pair of vertices at distance at most `k` in `G`, where the
distance is considered in the unweighted graph. In a directed graph,
there is an arc from a vertex `u` to a vertex `v` if there is a path
of length at most `k` in `G` from `u` to `v`.

INPUT:

- ``k`` -- integer; the maximum path length for considering edges in
the power graph.

OUTPUT:

- The kth power graph based on shortest distances between nodes.

EXAMPLES:

Testing on undirected graphs::

sage: G = Graph([(0, 1), (1, 2), (2, 3), (3, 0), (2, 4), (4, 5)])
sage: PG = G.power(2)
sage: PG.edges(sort=True, labels=False)
[(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (2, 5), (3, 4), (4, 5)]

Testing on directed graphs::

sage: G = DiGraph([(0, 1), (1, 2), (2, 3), (3, 0), (2, 4), (4, 5)])
sage: PG = G.power(3)
sage: PG.edges(sort=True, labels=False)
[(0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 2), (1, 3), (1, 4), (1, 5), (2, 0), (2, 1), (2, 3), (2, 4), (2, 5), (3, 0), (3, 1), (3, 2), (4, 5)]

TESTS:

Testing when k < 0::

sage: G = Graph([(0, 1), (1, 2), (2, 3), (3, 0), (2, 4), (4, 5)])
sage: PG = G.power(-2)
Traceback (most recent call last):
...
ValueError: distance must be a non-negative integer, not -2

Testing when k = 0::

sage: G = Graph([(0, 1), (1, 2), (2, 3), (3, 0), (2, 4), (4, 5)])
sage: PG = G.power(0)
sage: PG.edges(sort=True, labels=False)
[]

Testing when k = 1::

sage: G = Graph([(0, 1), (1, 2), (2, 3), (3, 0), (2, 4), (4, 5)])
sage: PG = G.power(1)
sage: PG.edges(sort=True, labels=False)
[(0, 1), (0, 3), (1, 2), (2, 3), (2, 4), (4, 5)]

Testing when k = Infinity::

sage: G = Graph([(0, 1), (1, 2), (2, 3), (3, 0), (2, 4), (4, 5)])
sage: PG = G.power(Infinity)
Traceback (most recent call last):
...
ValueError: distance must be a non-negative integer, not +Infinity

Testing on graph with multiple edges::

sage: G = DiGraph([(0, 1), (0, 1), (1, 2), (2, 3), (3, 0), (2, 4), (4, 5)], multiedges=True)
sage: PG = G.power(3)
sage: PG.edges(sort=True, labels=False)
[(0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 2), (1, 3), (1, 4), (1, 5), (2, 0), (2, 1), (2, 3), (2, 4), (2, 5), (3, 0), (3, 1), (3, 2), (4, 5)]
"""
from sage.graphs.digraph import DiGraph
from sage.graphs.graph import Graph

power_of_graph = DiGraph() if self.is_directed() else Graph()

for u in self:
for v in self.breadth_first_search(u, distance=k):
if u != v:
power_of_graph.add_edge(u, v)

if self.name():
power_of_graph.name("power({})".format(self.name()))

return power_of_graph

def girth(self, certificate=False):
"""
Return the girth of the graph.
Expand Down

0 comments on commit caa1068

Please sign in to comment.