Skip to content

Commit e4ca583

Browse files
authored
Merge pull request #477 from wifiBlack/week-10-king-minimum-ordering
Week 10 king minimum ordering
2 parents 34f970b + 3b26627 commit e4ca583

File tree

5 files changed

+190
-16
lines changed

5 files changed

+190
-16
lines changed

doc/ordering/pgr_kingOrdering.rst

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,26 @@
3232
Description
3333
-------------------------------------------------------------------------------
3434

35-
TBD
35+
In numerical linear algebra and graph theory, the King ordering algorithm
36+
is a heuristic designed to reorder the vertices of a graph so as to reduce
37+
its bandwidth.
38+
39+
The method follows a breadth-first search (BFS) traversal,but with a refinement:
40+
at each step, the unvisited neighbors of the current vertex are inserted into
41+
the queue in ascending order of their pseudo-degree, where the pseudo-degree of
42+
a vertex is the number of edges connecting it to yet-unvisited vertices. This
43+
prioritization often yields a smaller bandwidth compared to simpler BFS orderings.
44+
45+
**The main characteristics are:**
46+
47+
- The implementation targets undirected graphs.
48+
- Bandwidth minimization is an NP-complete problem; King ordering provides a practical local minimization approach.
49+
- The time complexity is: :math:`O(m^2 \log(m)|E|)`
50+
51+
- where :math:`|E|` is the number of edges,
52+
- :math:`m` is the maximum degree among all vertices.
53+
54+
|Boost| Boost Graph Inside
3655

3756
Signatures
3857
------------------------------------------------------------------------------
@@ -78,6 +97,37 @@ Result columns
7897
:start-after: node_ordering_start
7998
:end-before: node_ordering_end
8099

100+
Additional Examples
101+
-------------------------------------------------------------------------------
102+
103+
.. graphviz::
104+
105+
graph G {
106+
node [shape=circle, style=filled, fillcolor=white, color=black, fontcolor=black, fontsize=10];
107+
edge [color=black, penwidth=1];
108+
109+
4 -- 7;
110+
7 -- 9;
111+
7 -- 0;
112+
0 -- 2;
113+
2 -- 5;
114+
5 -- 9;
115+
9 -- 8;
116+
9 -- 1;
117+
5 -- 1;
118+
9 -- 6;
119+
6 -- 3;
120+
1 -- 3;
121+
122+
{rank=same; 4; 8; 6;}
123+
{rank=same; 7; 9; 3;}
124+
{rank=same; 0; 2; 5; 1;}
125+
}
126+
127+
.. literalinclude:: kingOrdering.queries
128+
:start-after: -- q2
129+
:end-before: -- q3
130+
81131
See Also
82132
-------------------------------------------------------------------------------
83133

doc/ordering/pgr_minDegreeOrdering.rst

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,27 @@
3232
Description
3333
-------------------------------------------------------------------------------
3434

35-
TBD
35+
In numerical linear algebra, the MinDegree ordering is a heuristic used to
36+
reduce the amount of fill-in during sparse matrix factorization, such as
37+
Cholesky decomposition for symmetric matrices.
38+
39+
When eliminating variables in a sparse system, new nonzero entries—called
40+
fill-ins—can appear in positions that were originally zero, increasing storage
41+
and computation costs. The minimum degree approach attempts to reorder the
42+
vertices (or equivalently, the rows and columns of the matrix) so that,
43+
at each elimination step, the vertex with the smallest degree is removed first,
44+
thereby reducing potential fill-in.
45+
46+
The main characteristics are:
47+
48+
- The implementation works on undirected graphs.
49+
- The algorithm is a heuristic; finding the true optimal ordering is NP-complete.
50+
- The time complexity is: :math:`O(|V| \log |V| + |E|)`
51+
52+
- where :math:`|V|` is the number of vertices,
53+
- :math:`|E|` is the number of edges.
54+
55+
|Boost| Boost Graph Inside
3656

3757
Signatures
3858
------------------------------------------------------------------------------

docqueries/ordering/kingOrdering.pg

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,44 @@
44
SELECT * FROM pgr_kingOrdering(
55
'SELECT id, source, target, cost, reverse_cost FROM edges'
66
);
7+
78
/* -- q2 */
9+
CREATE TABLE additional_sample_1(
10+
id SERIAL PRIMARY KEY,
11+
source INTEGER,
12+
target INTEGER,
13+
cost DOUBLE PRECISION,
14+
reverse_cost DOUBLE PRECISION
15+
);
16+
17+
INSERT INTO additional_sample_1 (source, target, cost, reverse_cost) VALUES
18+
(4, 7, 1, 1),
19+
(7, 4, 1, 1),
20+
(7, 9, 1, 1),
21+
(9, 7, 1, 1),
22+
(7, 0, 1, 1),
23+
(0, 7, 1, 1),
24+
(0, 2, 1, 1),
25+
(2, 0, 1, 1),
26+
(2, 5, 1, 1),
27+
(5, 2, 1, 1),
28+
(5, 9, 1, 1),
29+
(9, 5, 1, 1),
30+
(9, 8, 1, 1),
31+
(8, 9, 1, 1),
32+
(9, 1, 1, 1),
33+
(1, 9, 1, 1),
34+
(5, 1, 1, 1),
35+
(1, 5, 1, 1),
36+
(9, 6, 1, 1),
37+
(6, 9, 1, 1),
38+
(6, 3, 1, 1),
39+
(3, 6, 1, 1),
40+
(1, 3, 1, 1),
41+
(3, 1, 1, 1);
42+
43+
SELECT * FROM pgr_kingOrdering(
44+
'SELECT id, source, target, cost, reverse_cost FROM additional_sample_1'
45+
);
46+
47+
/* -- q3 */

docqueries/ordering/kingOrdering.result

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,57 @@ SELECT * FROM pgr_kingOrdering(
2828
(17 rows)
2929

3030
/* -- q2 */
31+
CREATE TABLE additional_sample_1(
32+
id SERIAL PRIMARY KEY,
33+
source INTEGER,
34+
target INTEGER,
35+
cost DOUBLE PRECISION,
36+
reverse_cost DOUBLE PRECISION
37+
);
38+
CREATE TABLE
39+
INSERT INTO additional_sample_1 (source, target, cost, reverse_cost) VALUES
40+
(4, 7, 1, 1),
41+
(7, 4, 1, 1),
42+
(7, 9, 1, 1),
43+
(9, 7, 1, 1),
44+
(7, 0, 1, 1),
45+
(0, 7, 1, 1),
46+
(0, 2, 1, 1),
47+
(2, 0, 1, 1),
48+
(2, 5, 1, 1),
49+
(5, 2, 1, 1),
50+
(5, 9, 1, 1),
51+
(9, 5, 1, 1),
52+
(9, 8, 1, 1),
53+
(8, 9, 1, 1),
54+
(9, 1, 1, 1),
55+
(1, 9, 1, 1),
56+
(5, 1, 1, 1),
57+
(1, 5, 1, 1),
58+
(9, 6, 1, 1),
59+
(6, 9, 1, 1),
60+
(6, 3, 1, 1),
61+
(3, 6, 1, 1),
62+
(1, 3, 1, 1),
63+
(3, 1, 1, 1);
64+
INSERT 0 24
65+
SELECT * FROM pgr_kingOrdering(
66+
'SELECT id, source, target, cost, reverse_cost FROM additional_sample_1'
67+
);
68+
seq | node
69+
-----+------
70+
1 | 0
71+
2 | 4
72+
3 | 2
73+
4 | 7
74+
5 | 8
75+
6 | 5
76+
7 | 9
77+
8 | 1
78+
9 | 6
79+
10 | 3
80+
(10 rows)
81+
82+
/* -- q3 */
3183
ROLLBACK;
3284
ROLLBACK

include/ordering/ordering.hpp

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,21 +53,27 @@ namespace pgrouting {
5353
template <class G>
5454
std::vector<int64_t>
5555
kingOrdering(G &graph) {
56-
using V = typename G::V;
5756
using B_G = typename G::B_G;
58-
using vertices_size_type = typename boost::graph_traits<B_G>::vertices_size_type;
57+
using V = typename G::V;
5958

6059
size_t n = boost::num_vertices(graph.graph);
6160
std::vector<int64_t> results(n);
6261

6362
auto index_map = boost::get(boost::vertex_index, graph.graph);
64-
std::vector<vertices_size_type> colors(n);
63+
64+
std::vector<V> colors(n);
6565
auto color_map = boost::make_iterator_property_map(colors.begin(), index_map);
6666
auto degree_map = boost::make_degree_map(graph.graph);
6767
std::vector<V> inv_perm(n);
6868

6969
CHECK_FOR_INTERRUPTS();
70-
boost::king_ordering(graph.graph, inv_perm. rbegin(), color_map, degree_map, index_map);
70+
boost::king_ordering(
71+
graph.graph,
72+
inv_perm.rbegin(),
73+
color_map,
74+
degree_map,
75+
index_map);
76+
7177
size_t j = 0;
7278
for (auto i = inv_perm.begin(); i != inv_perm.end(); ++i, ++j) {
7379
results[j] = static_cast<int64_t>(graph.graph[index_map[*i]].id);
@@ -80,35 +86,41 @@ template <class G>
8086
std::vector<int64_t>
8187
minDegreeOrdering(G &graph) {
8288
using B_G = typename G::B_G;
83-
using vertices_size_type = typename boost::graph_traits<B_G>::vertices_size_type;
89+
using V = typename G::V;
8490

8591
size_t n = boost::num_vertices(graph.graph);
8692
std::vector<int64_t> results(n);
8793

8894
auto index_map = boost::get(boost::vertex_index, graph.graph);
8995

90-
std::vector<vertices_size_type> degree(n, 0);
91-
auto degree_map = boost::make_iterator_property_map(degree.begin(), index_map);
96+
std::vector<V> degrees(n);
97+
auto degree_map = boost::make_iterator_property_map(degrees.begin(), index_map);
9298

93-
std::vector<vertices_size_type> supernode_sizes(n, 1);
99+
std::vector<V> supernode_sizes(n, 1);
94100
auto supernode_map = boost::make_iterator_property_map(supernode_sizes.begin(), index_map);
95101

96-
std::vector<vertices_size_type> perm(n);
97-
std::vector<vertices_size_type> inv_perm(n);
102+
std::vector<V> perm(n);
103+
std::vector<V> inv_perm(n);
104+
105+
auto [vi, vi_end] = boost::vertices(graph.graph);
106+
for (; vi != vi_end; ++vi) {
107+
degree_map[*vi] = boost::degree(*vi, graph.graph);
108+
}
98109

99110
CHECK_FOR_INTERRUPTS();
100111

101112
boost::minimum_degree_ordering(
102113
graph.graph,
103114
degree_map,
104-
inv_perm.data(),
105-
perm.data(),
115+
inv_perm.begin(),
116+
perm.begin(),
106117
supernode_map,
107118
0,
108119
index_map);
109120

110-
for (size_t i = 0; i < n; ++i) {
111-
results[i] = static_cast<int64_t>(graph.graph[inv_perm[i]].id);
121+
size_t j = 0;
122+
for (auto i = inv_perm.begin(); i != inv_perm.end(); ++i, ++j) {
123+
results[j] = static_cast<int64_t>(graph.graph[index_map[*i]].id);
112124
}
113125

114126
return results;

0 commit comments

Comments
 (0)