Skip to content

Commit 9ec10e8

Browse files
authored
Merge pull request #579 from sakirr05/week5-coreNumbers
week 5: coreNumbers
2 parents ca64db4 + 1d6252b commit 9ec10e8

3 files changed

Lines changed: 192 additions & 25 deletions

File tree

doc/metrics/pgr_coreNumbers.rst

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,35 @@ graph using k-core decomposition.
2020

2121
.. rubric:: Availability
2222

23-
.. rubric:: Version 4.1.0
23+
* Version 4.1.0
2424

25-
* New experimental function.
25+
* New experimental function.
2626

2727
Description
2828
-------------------------------------------------------------------------------
2929

3030
The **core number** of a vertex is the largest value :math:`k` such that the
3131
vertex belongs to the :math:`k`-core of the graph.
3232

33-
**The main characteristics are:**
33+
The :math:`k`-core of a graph is the maximal subgraph in which every vertex has
34+
degree at least :math:`k`. K-core decomposition assigns one core number to each
35+
vertex and is widely used in network analysis to identify densely connected
36+
regions and hierarchical structure.
3437

35-
- Works for **undirected** graphs.
36-
- Each vertex has **exactly one** core number.
37-
- **All vertices** in the graph are returned.
38-
- The number of result rows is :math:`|V|`.
39-
- Two or more vertices can share the same core number.
40-
- The result is ordered by ``node`` ascending.
38+
This implementation works for **undirected** graphs. Each vertex has exactly one
39+
core number, all vertices in the graph are returned, and the number of result
40+
rows is :math:`|V|`. Two or more vertices can share the same core number. The
41+
result is ordered by ``node`` ascending.
4142

4243
- Running time: :math:`O(m)`
4344

45+
|Boost| Boost Graph Inside
46+
47+
.. rubric:: References
48+
49+
* Batagelj, V. and Zaversnik, M. (2003). An O(m) Algorithm for Cores Decomposition
50+
of Networks. arXiv:cs/0310049.
51+
4452
Signatures
4553
-------------------------------------------------------------------------------
4654

@@ -80,27 +88,28 @@ Result columns
8088
-------------------------------------------------------------------------------
8189

8290
.. list-table::
83-
:width: 81
84-
:widths: auto
85-
:header-rows: 1
86-
87-
* - Column
88-
- Type
89-
- Description
90-
* - ``seq``
91-
- ``BIGINT``
92-
- Sequential value starting from 1.
93-
* - ``node``
94-
- ``BIGINT``
95-
- Identifier of the vertex.
96-
* - ``core``
97-
- ``BIGINT``
98-
- Core number of the vertex.
91+
:width: 81
92+
:widths: auto
93+
:header-rows: 1
94+
95+
* - Column
96+
- Type
97+
- Description
98+
* - ``seq``
99+
- ``BIGINT``
100+
- Sequential value starting from 1.
101+
* - ``node``
102+
- ``BIGINT``
103+
- Identifier of the vertex.
104+
* - ``core``
105+
- ``BIGINT``
106+
- Core number of the vertex.
99107

100108
See Also
101109
-------------------------------------------------------------------------------
102110

103111
* :doc:`sampledata`
112+
* :doc:`pgr_betweennessCentrality`
104113
* :doc:`metrics-family`
105114

106115
.. rubric:: Indices and tables
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/* :file: This file is part of the pgRouting project.
2+
:copyright: Copyright (c) 2026-2026 pgRouting developers
3+
:license: Creative Commons Attribution-Share Alike 3.0 https://creativecommons.org/licenses/by-sa/3.0 */
4+
5+
6+
BEGIN;
7+
8+
UPDATE edges SET cost = sign(cost), reverse_cost = sign(reverse_cost);
9+
SELECT CASE WHEN NOT min_version('4.1.0') THEN plan(1) ELSE plan(9) END;
10+
11+
CREATE OR REPLACE FUNCTION edge_cases()
12+
RETURNS SETOF TEXT AS
13+
$BODY$
14+
BEGIN
15+
16+
IF NOT min_version('4.1.0') THEN
17+
RETURN QUERY
18+
SELECT skip(1, 'Function is new on 4.1.0');
19+
RETURN;
20+
END IF;
21+
22+
PREPARE idless2_q AS
23+
SELECT node, core FROM pgr_coreNumbers(
24+
'SELECT id, source, target, cost, reverse_cost
25+
FROM edges WHERE id < 2'
26+
) ORDER BY node;
27+
28+
PREPARE idless2_r AS
29+
SELECT * FROM (VALUES
30+
(5::BIGINT, 1::BIGINT),
31+
(6, 1))
32+
AS t(node, core);
33+
34+
RETURN QUERY
35+
SELECT lives_ok('idless2_q');
36+
37+
RETURN QUERY
38+
SELECT results_eq('idless2_q', 'idless2_r');
39+
40+
41+
PREPARE idless4_q AS
42+
SELECT node, core FROM pgr_coreNumbers(
43+
'SELECT id, source, target, cost, reverse_cost
44+
FROM edges WHERE id < 4'
45+
) ORDER BY node;
46+
47+
PREPARE idless4_r AS
48+
SELECT * FROM (VALUES
49+
(5::BIGINT, 1::BIGINT),
50+
(6, 1),
51+
(10, 1),
52+
(15, 1))
53+
AS t(node, core);
54+
55+
RETURN QUERY
56+
SELECT lives_ok('idless4_q');
57+
58+
RETURN QUERY
59+
SELECT results_eq('idless4_q', 'idless4_r', 'test 4');
60+
61+
62+
PREPARE idless5_q AS
63+
SELECT node, core FROM pgr_coreNumbers(
64+
'SELECT id, source, target, cost, reverse_cost
65+
FROM edges WHERE id < 5'
66+
) ORDER BY node;
67+
68+
PREPARE idless5_r AS
69+
SELECT * FROM (VALUES
70+
(5::BIGINT, 1::BIGINT),
71+
(6, 1),
72+
(7, 1),
73+
(10, 1),
74+
(15, 1))
75+
AS t(node, core);
76+
77+
RETURN QUERY
78+
SELECT lives_ok('idless5_q');
79+
80+
RETURN QUERY
81+
SELECT results_eq('idless5_q', 'idless5_r', 'test 6');
82+
83+
84+
PREPARE idless10_q AS
85+
SELECT node, core FROM pgr_coreNumbers(
86+
'SELECT id, source, target, cost, reverse_cost
87+
FROM edges WHERE id < 10'
88+
) ORDER BY node;
89+
90+
PREPARE idless10_r AS
91+
SELECT * FROM (VALUES
92+
(1::BIGINT, 1::BIGINT),
93+
(3, 1),
94+
(5, 1),
95+
(6, 2),
96+
(7, 2),
97+
(10, 2),
98+
(11, 2),
99+
(15, 1),
100+
(16, 1))
101+
AS t(node, core);
102+
103+
RETURN QUERY
104+
SELECT lives_ok('idless10_q');
105+
106+
RETURN QUERY
107+
SELECT results_eq('idless10_q', 'idless10_r', 'test 8');
108+
109+
110+
PREPARE empty_q AS
111+
SELECT node, core FROM pgr_coreNumbers(
112+
'SELECT id, source, target, cost, reverse_cost
113+
FROM edges WHERE id < 0'
114+
) ORDER BY node;
115+
116+
RETURN QUERY
117+
SELECT is_empty('empty_q', 'Empty graph returns no rows');
118+
119+
END;
120+
$BODY$
121+
LANGUAGE plpgsql;
122+
123+
SELECT edge_cases();
124+
125+
SELECT finish();
126+
ROLLBACK;
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* :file: This file is part of the pgRouting project.
2+
:copyright: Copyright (c) 2026-2026 pgRouting developers
3+
:license: Creative Commons Attribution-Share Alike 3.0 https://creativecommons.org/licenses/by-sa/3.0 */
4+
5+
6+
BEGIN;
7+
8+
UPDATE edges SET cost = sign(cost), reverse_cost = sign(reverse_cost);
9+
SELECT CASE WHEN NOT min_version('4.1.0') THEN plan(1) ELSE plan(54) END;
10+
11+
CREATE OR REPLACE FUNCTION inner_query()
12+
RETURNS SETOF TEXT AS
13+
$BODY$
14+
BEGIN
15+
16+
IF NOT min_version('4.1.0') THEN
17+
RETURN QUERY
18+
SELECT skip(1, 'Function is new on 4.1.0');
19+
RETURN;
20+
END IF;
21+
22+
RETURN QUERY
23+
SELECT style_dijkstra('pgr_coreNumbers(', ')');
24+
25+
END;
26+
$BODY$
27+
LANGUAGE plpgsql;
28+
29+
SELECT inner_query();
30+
31+
SELECT finish();
32+
ROLLBACK;

0 commit comments

Comments
 (0)