Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/graphs/graph_decompositions/rankwidth_c/rw.c
4099 views
1
// Calculate rank-width and rank-decompositions of graphs.
2
3
// Philipp Klaus Krause, [email protected], [email protected], 2009 - 2012
4
// Copyright (c) 2009-2012 Philipp Klaus Krause
5
6
// This program is free software; you can redistribute it and/or modify
7
// it under the terms of the GNU General Public License as published by
8
// the Free Software Foundation; either version 2 of the License, or
9
// (at your option) any later version.
10
//
11
// This program is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
// GNU General Public License for more details.
15
//
16
// You should have received a copy of the GNU General Public License along
17
// with this program; if not, write to the Free Software Foundation, Inc.,
18
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
#include <stdlib.h>
21
22
#include "rw.h"
23
24
static uint_fast8_t subset_size;
25
26
static uint_fast8_t num_vertices;
27
28
subset_t *adjacency_matrix;
29
30
// This array is meant to contain max{f(Y), w(f, Y)} at the position corresponding to Y.
31
static uint_fast8_t *slots;
32
subset_t *cslots;
33
34
uint_fast8_t cut_rank(const subset_t s)
35
{
36
subset_t am[num_vertices];
37
subset_t x, y;
38
uint_fast8_t i, j;
39
uint_fast8_t rank = 0;
40
41
for(i = 0; i < num_vertices; i++)
42
am[i] = (s & (1ul << i)) ? 0 : (adjacency_matrix[i] & s);
43
44
for(i = 0; i < num_vertices; i++)
45
{
46
y = 0;
47
for(j = rank; j < num_vertices; j++)
48
{
49
x = am[j];
50
if(x & 1)
51
{
52
if(!y)
53
{
54
y = x;
55
am[j] = am[rank++];
56
continue;
57
}
58
x ^= y;
59
}
60
am[j] = x >> 1;
61
}
62
}
63
64
return(rank);
65
}
66
67
// Compute the binomial coefficient C(n, k).
68
// Time complexity: O(n) * complexity of integer division.
69
// Could be replaced by a lookup table of size O(n^2), but since this is not the bopttleneck, it doesn't matter.
70
subset_t binomial_coefficient(uint_fast8_t n, uint_fast8_t k)
71
{
72
uint_fast8_t i, delta, max;
73
subset_t c;
74
75
if(n < k)
76
return(0);
77
78
if(n == k)
79
return(1);
80
81
if(k < n - k)
82
{
83
delta = n - k;
84
max = k;
85
}
86
else
87
{
88
delta = k;
89
max = n - k;
90
}
91
92
c = delta + 1;
93
94
for(i = 2; i <= max; i++)
95
c = (c * (delta + i)) / i;
96
97
return(c);
98
}
99
100
// Convert unsigned integer from combinadic to machine representation.
101
subset_t comb_to_int(subset_t c)
102
{
103
uint_fast8_t k, n;
104
subset_t i;
105
106
i = 0;
107
for(k = 0, n = 1; k < num_vertices; k++, c >>= 1)
108
if(c & 1)
109
i += binomial_coefficient(k, n++);
110
return(i);
111
}
112
113
// Return largest value v where v < a and Choose(v,b) <= x.
114
static uint_fast8_t largest_v(uint_fast8_t a, uint_fast8_t b, subset_t x)
115
{
116
uint_fast8_t v = a - 1;
117
118
while(binomial_coefficient(v,b) > x)
119
v--;
120
121
return(v);
122
}
123
124
// Convert unsigned integer from machine representation to combinadic.
125
static subset_t int_to_comb(subset_t i)
126
{
127
uint_fast8_t j, v;
128
uint_fast8_t a = num_vertices;
129
uint_fast8_t b = subset_size;
130
subset_t c = 0;
131
132
for(j = 0; j < subset_size; j++, b--)
133
{
134
v = largest_v(a, b, i);
135
i = i - binomial_coefficient(v, b);
136
a = v;
137
c |= (1ul << v);
138
}
139
140
return(c);
141
}
142
143
// Masked increment.
144
static subset_t subset_inc(subset_t v, subset_t mask)
145
{
146
return((v - mask) & mask);
147
}
148
149
// Returns rank-width for a subset of size at least 2 given that slots already contains correct values for all nonempty subsets of sizes less than the size of s.
150
// This is where most of the time is spent.
151
uint_fast8_t width(subset_t s)
152
{
153
uint_fast8_t w = UINT_FAST8_MAX, v, v1, v2;
154
subset_t ss;
155
subset_t cs;
156
for(ss = subset_inc(0, s); ss != s; ss = subset_inc(ss, s))
157
{
158
v1 = slots[ss];
159
v2 = slots[s & ~ss];
160
v = v1 > v2 ? v1 : v2;
161
if(v < w)
162
{
163
w = v;
164
cs = ss;
165
}
166
}
167
cslots[s] = cs;
168
return(w);
169
}
170
171
void fill_slot(subset_t i)
172
{
173
uint_fast8_t v, w;
174
subset_t s = int_to_comb(i);
175
v = cut_rank(s);
176
w = width(s);
177
slots[s] = v > w ? v : w;
178
}
179
180
void calculate_level(uint_fast8_t ss)
181
{
182
uint_fast8_t i;
183
184
subset_size = ss;
185
186
if(subset_size == 0)
187
slots[0] = 0;
188
else if(subset_size == 1)
189
for(i = 0; i < num_vertices; i++)
190
{
191
slots[1ul << i] = cut_rank(1ul << i);
192
cslots[1ul << i] = 0x0;
193
}
194
else
195
{
196
subset_t i;
197
const subset_t end = binomial_coefficient(num_vertices, subset_size);
198
for(i = 0; i < end; i++)
199
fill_slot(i);
200
}
201
}
202
203
void calculate_all(void)
204
{
205
uint_fast8_t i;
206
207
for(i = 0; i < num_vertices; i++)
208
{
209
slots[1ul << i] = cut_rank(1ul << i);
210
cslots[1ul << i] = 0x0;
211
}
212
213
for(subset_size = 2; subset_size <= num_vertices; subset_size++)
214
{
215
subset_t i;
216
const subset_t end = binomial_coefficient(num_vertices, subset_size);
217
for(i = 0; i < end; i++)
218
fill_slot(i);
219
}
220
}
221
222
int init_rw(uint_fast8_t n)
223
{
224
// If sizeof(uint_fast8_t) * (1ul << n) overflows, it wraps around to 0, since size_t and unsigned long are unsigned integer types.
225
if( (n > MAX_VERTICES) || ( (n>0) && !(sizeof(uint_fast8_t) * (1ul << n)) ) )
226
return(-1);
227
228
num_vertices = n;
229
adjacency_matrix = malloc(sizeof(subset_t) * n);
230
slots = malloc(sizeof(uint_fast8_t) * (1ul << n));
231
cslots = 0;
232
return((adjacency_matrix && slots) ? 0 : -1);
233
}
234
235
int init_rw_dec(uint_fast8_t n)
236
{
237
// If sizeof(subset_t) * (1ul << n) overflows, it wraps around to 0, since size_t and unsigned long are unsigned integer types.
238
if(n && !(sizeof(subset_t) * (1ul << n)))
239
return(-1);
240
241
if(init_rw(n))
242
return(-1);
243
cslots = malloc(sizeof(subset_t) * (1ul << n));
244
return(cslots ? 0 : -1);
245
}
246
247
void destroy_rw(void)
248
{
249
free(cslots);
250
free(slots);
251
free(adjacency_matrix);
252
}
253
254
uint_fast8_t get_rw(void)
255
{
256
return(slots[0xfffffffful >> (32 - num_vertices)]);
257
}
258
259
260