Skip to content

Commit d8c07d3

Browse files
committed
Fixed changes
1 parent f4906a8 commit d8c07d3

File tree

7 files changed

+94
-160
lines changed

7 files changed

+94
-160
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,4 @@ retworkx/*pyd
2222
*.jpg
2323
**/*.so
2424
retworkx-core/Cargo.lock
25-
.DS_Store
2625
**/.DS_Store

degree_centrality_implementation_rustworkx.md

Lines changed: 0 additions & 149 deletions
This file was deleted.

rustworkx-core/src/centrality.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use petgraph::visit::{
3232
Reversed,
3333
Visitable,
3434
};
35+
use petgraph::Direction;
3536
use rayon_cond::CondIterator;
3637

3738
/// Compute the betweenness centrality of all nodes in a graph.
@@ -362,7 +363,7 @@ fn accumulate_edges<G>(
362363
/// }
363364
/// ```
364365
365-
pub fn degree_centrality<G>(graph: G) -> Vec<f64>
366+
pub fn graph_degree_centrality<G>(graph: G) -> Vec<f64>
366367
where
367368
G: IntoNodeIdentifiers + NodeCount + IntoNeighbors + NodeIndexable,
368369
{
@@ -377,6 +378,29 @@ where
377378
centrality
378379
}
379380

381+
pub fn digraph_degree_centrality<G>(graph: G, direction: Option<Direction>) -> Vec<f64>
382+
where
383+
G: IntoNodeIdentifiers + NodeCount + IntoNeighborsDirected + NodeIndexable,
384+
{
385+
let node_count = graph.node_count() as f64;
386+
let mut centrality = vec![0.0; graph.node_bound()];
387+
388+
for node in graph.node_identifiers() {
389+
let degree = match direction {
390+
Some(Direction::Incoming) => {
391+
graph.neighbors_directed(node, Direction::Incoming).count() as f64
392+
}
393+
Some(Direction::Outgoing) => {
394+
graph.neighbors_directed(node, Direction::Outgoing).count() as f64
395+
}
396+
_ => graph.neighbors(node).count() as f64,
397+
};
398+
centrality[graph.to_index(node)] = degree / (node_count - 1.0);
399+
}
400+
401+
centrality
402+
}
403+
380404
struct ShortestPathData<G>
381405
where
382406
G: GraphBase,

rustworkx/__init__.pyi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ from .rustworkx import digraph_closeness_centrality as digraph_closeness_central
5050
from .rustworkx import graph_closeness_centrality as graph_closeness_centrality
5151
from .rustworkx import digraph_katz_centrality as digraph_katz_centrality
5252
from .rustworkx import graph_katz_centrality as graph_katz_centrality
53-
from .rustworkx import degree_centrality as degree_centrality
53+
from .rustworkx import graph_degree_centrality as graph_degree_centrality
54+
from .rustworkx import digraph_degree_centrality as digraph_degree_centrality
5455
from .rustworkx import graph_greedy_color as graph_greedy_color
5556
from .rustworkx import graph_greedy_edge_color as graph_greedy_edge_color
5657
from .rustworkx import graph_is_bipartite as graph_is_bipartite

src/centrality.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,22 @@ pub fn digraph_betweenness_centrality(
176176
/// :rtype: CentralityMapping
177177
#[pyfunction]
178178
#[pyo3(text_signature = "(graph, /)")]
179-
pub fn degree_centrality_py(graph: &graph::PyGraph) -> PyResult<CentralityMapping> {
180-
let centrality = centrality::degree_centrality(&graph.graph);
179+
pub fn graph_degree_centrality(graph: &graph::PyGraph) -> PyResult<CentralityMapping> {
180+
let centrality = centrality::graph_degree_centrality(&graph.graph);
181+
182+
Ok(CentralityMapping {
183+
centralities: centrality
184+
.into_iter()
185+
.enumerate()
186+
.map(|(i, v)| (i, v))
187+
.collect(),
188+
})
189+
}
190+
191+
#[pyfunction]
192+
#[pyo3(text_signature = "(graph, /)")]
193+
pub fn digraph_degree_centrality(graph: &digraph::PyDiGraph) -> PyResult<CentralityMapping> {
194+
let centrality = centrality::digraph_degree_centrality(&graph.graph, None);
181195

182196
Ok(CentralityMapping {
183197
centralities: centrality

src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,8 @@ fn rustworkx(py: Python<'_>, m: &Bound<PyModule>) -> PyResult<()> {
533533
m.add_wrapped(wrap_pyfunction!(digraph_eigenvector_centrality))?;
534534
m.add_wrapped(wrap_pyfunction!(graph_katz_centrality))?;
535535
m.add_wrapped(wrap_pyfunction!(digraph_katz_centrality))?;
536-
m.add_wrapped(wrap_pyfunction!(degree_centrality_py))?;
536+
m.add_wrapped(wrap_pyfunction!(graph_degree_centrality))?;
537+
m.add_wrapped(wrap_pyfunction!(digraph_degree_centrality))?;
537538
m.add_wrapped(wrap_pyfunction!(graph_astar_shortest_path))?;
538539
m.add_wrapped(wrap_pyfunction!(digraph_astar_shortest_path))?;
539540
m.add_wrapped(wrap_pyfunction!(graph_greedy_color))?;

tests/graph/test_centrality.py

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ def test_custom_graph_unnormalized(self):
232232
self.assertAlmostEqual(v, expected[k])
233233

234234

235-
class TestDegreeCentrality(unittest.TestCase):
235+
class TestGraphDegreeCentrality(unittest.TestCase):
236236
def setUp(self):
237237
self.graph = rustworkx.PyGraph()
238238
self.a = self.graph.add_node("A")
@@ -247,7 +247,7 @@ def setUp(self):
247247
self.graph.add_edges_from(edge_list)
248248

249249
def test_degree_centrality(self):
250-
centrality = rustworkx.degree_centrality_py(self.graph)
250+
centrality = rustworkx.graph_degree_centrality(self.graph)
251251
expected = {
252252
0: 1 / 3, # Node A has 1 edge, normalized by (n-1) = 3
253253
1: 2 / 3, # Node B has 2 edges
@@ -258,18 +258,62 @@ def test_degree_centrality(self):
258258

259259
def test_degree_centrality_complete_graph(self):
260260
graph = rustworkx.generators.complete_graph(5)
261-
centrality = rustworkx.degree_centrality_py(graph)
261+
centrality = rustworkx.graph_degree_centrality(graph)
262262
expected = {0: 1.0, 1: 1.0, 2: 1.0, 3: 1.0, 4: 1.0}
263263
self.assertEqual(expected, centrality)
264264

265265
def test_degree_centrality_star_graph(self):
266266
graph = rustworkx.generators.star_graph(5)
267-
centrality = rustworkx.degree_centrality_py(graph)
267+
centrality = rustworkx.graph_degree_centrality(graph)
268268
expected = {0: 1.0, 1: 0.25, 2: 0.25, 3: 0.25, 4: 0.25}
269269
self.assertEqual(expected, centrality)
270270

271271
def test_degree_centrality_empty_graph(self):
272272
graph = rustworkx.PyGraph()
273-
centrality = rustworkx.degree_centrality_py(graph)
273+
centrality = rustworkx.graph_degree_centrality(graph)
274274
expected = {}
275275
self.assertEqual(expected, centrality)
276+
277+
class TestDiGraphDegreeCentrality(unittest.TestCase):
278+
def setUp(self):
279+
self.digraph = rustworkx.PyDiGraph()
280+
self.a = self.digraph.add_node("A")
281+
self.b = self.digraph.add_node("B")
282+
self.c = self.digraph.add_node("C")
283+
self.d = self.digraph.add_node("D")
284+
edge_list = [
285+
(self.a, self.b, 1),
286+
(self.b, self.c, 1),
287+
(self.c, self.d, 1),
288+
]
289+
self.digraph.add_edges_from(edge_list)
290+
291+
def test_digraph_degree_centrality(self):
292+
centrality = rustworkx.digraph_degree_centrality(self.digraph)
293+
expected = {
294+
0: 1 / 3, # Node A has 1 outgoing edge
295+
1: 2 / 3, # Node B has 1 incoming and 1 outgoing edge
296+
2: 2 / 3, # Node C has 1 incoming and 1 outgoing edge
297+
3: 1 / 3, # Node D has 1 incoming edge
298+
}
299+
self.assertEqual(expected, centrality)
300+
301+
def test_digraph_degree_centrality_with_direction(self):
302+
centrality_incoming = rustworkx.digraph_degree_centrality(self.digraph, direction=rustworkx.Direction.Incoming)
303+
expected_incoming = {
304+
0: 0.0, # Node A has 0 incoming edges
305+
1: 1 / 3, # Node B has 1 incoming edge
306+
2: 1 / 3, # Node C has 1 incoming edge
307+
3: 1 / 3, # Node D has 1 incoming edge
308+
}
309+
self.assertEqual(expected_incoming, centrality_incoming)
310+
311+
centrality_outgoing = rustworkx.digraph_degree_centrality(self.digraph, direction=rustworkx.Direction.Outgoing)
312+
expected_outgoing = {
313+
0: 1 / 3, # Node A has 1 outgoing edge
314+
1: 1 / 3, # Node B has 1 outgoing edge
315+
2: 1 / 3, # Node C has 1 outgoing edge
316+
3: 0.0, # Node D has 0 outgoing edges
317+
}
318+
self.assertEqual(expected_outgoing, centrality_outgoing)
319+

0 commit comments

Comments
 (0)