Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/graphs/graph_decompositions/rankwidth_c/rw.c
8819 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
uint_fast8_t cut_rank(const subset_t s)
25
{
26
subset_t am[num_vertices];
27
subset_t x, y;
28
uint_fast8_t i, j;
29
uint_fast8_t rank = 0;
30
31
for(i = 0; i < num_vertices; i++)
32
am[i] = (s & (1ul << i)) ? 0 : (adjacency_matrix[i] & s);
33
34
for(i = 0; i < num_vertices; i++)
35
{
36
y = 0;
37
for(j = rank; j < num_vertices; j++)
38
{
39
x = am[j];
40
if(x & 1)
41
{
42
if(!y)
43
{
44
y = x;
45
am[j] = am[rank++];
46
continue;
47
}
48
x ^= y;
49
}
50
am[j] = x >> 1;
51
}
52
}
53
54
return(rank);
55
}
56
57
// Compute the binomial coefficient C(n, k).
58
// Time complexity: O(n) * complexity of integer division.
59
// Could be replaced by a lookup table of size O(n^2), but since this is not the bopttleneck, it doesn't matter.
60
subset_t binomial_coefficient(uint_fast8_t n, uint_fast8_t k)
61
{
62
uint_fast8_t i, delta, max;
63
subset_t c;
64
65
if(n < k)
66
return(0);
67
68
if(n == k)
69
return(1);
70
71
if(k < n - k)
72
{
73
delta = n - k;
74
max = k;
75
}
76
else
77
{
78
delta = k;
79
max = n - k;
80
}
81
82
c = delta + 1;
83
84
for(i = 2; i <= max; i++)
85
c = (c * (delta + i)) / i;
86
87
return(c);
88
}
89
90
// Convert unsigned integer from combinadic to machine representation.
91
subset_t comb_to_int(subset_t c)
92
{
93
uint_fast8_t k, n;
94
subset_t i;
95
96
i = 0;
97
for(k = 0, n = 1; k < num_vertices; k++, c >>= 1)
98
if(c & 1)
99
i += binomial_coefficient(k, n++);
100
return(i);
101
}
102
103
// Return largest value v where v < a and Choose(v,b) <= x.
104
static uint_fast8_t largest_v(uint_fast8_t a, uint_fast8_t b, subset_t x)
105
{
106
uint_fast8_t v = a - 1;
107
108
while(binomial_coefficient(v,b) > x)
109
v--;
110
111
return(v);
112
}
113
114
// Convert unsigned integer from machine representation to combinadic.
115
static subset_t int_to_comb(subset_t i)
116
{
117
uint_fast8_t j, v;
118
uint_fast8_t a = num_vertices;
119
uint_fast8_t b = subset_size;
120
subset_t c = 0;
121
122
for(j = 0; j < subset_size; j++, b--)
123
{
124
v = largest_v(a, b, i);
125
i = i - binomial_coefficient(v, b);
126
a = v;
127
c |= (1ul << v);
128
}
129
130
return(c);
131
}
132
133
// Masked increment.
134
static subset_t subset_inc(subset_t v, subset_t mask)
135
{
136
return((v - mask) & mask);
137
}
138
139
// 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.
140
// This is where most of the time is spent.
141
uint_fast8_t width(subset_t s)
142
{
143
uint_fast8_t w = UINT_FAST8_MAX, v, v1, v2;
144
subset_t ss;
145
subset_t cs;
146
for(ss = subset_inc(0, s); ss != s; ss = subset_inc(ss, s))
147
{
148
v1 = slots[ss];
149
v2 = slots[s & ~ss];
150
v = v1 > v2 ? v1 : v2;
151
if(v < w)
152
{
153
w = v;
154
cs = ss;
155
}
156
}
157
cslots[s] = cs;
158
return(w);
159
}
160
161
void fill_slot(subset_t i)
162
{
163
uint_fast8_t v, w;
164
subset_t s = int_to_comb(i);
165
v = cut_rank(s);
166
w = width(s);
167
slots[s] = v > w ? v : w;
168
}
169
170
void calculate_level(uint_fast8_t ss)
171
{
172
uint_fast8_t i;
173
174
subset_size = ss;
175
176
if(subset_size == 0)
177
slots[0] = 0;
178
else if(subset_size == 1)
179
for(i = 0; i < num_vertices; i++)
180
{
181
slots[1ul << i] = cut_rank(1ul << i);
182
cslots[1ul << i] = 0x0;
183
}
184
else
185
{
186
subset_t i;
187
const subset_t end = binomial_coefficient(num_vertices, subset_size);
188
for(i = 0; i < end; i++)
189
fill_slot(i);
190
}
191
}
192
193
void calculate_all(void)
194
{
195
uint_fast8_t i;
196
197
for(i = 0; i < num_vertices; i++)
198
{
199
slots[1ul << i] = cut_rank(1ul << i);
200
cslots[1ul << i] = 0x0;
201
}
202
203
for(subset_size = 2; subset_size <= num_vertices; subset_size++)
204
{
205
subset_t i;
206
const subset_t end = binomial_coefficient(num_vertices, subset_size);
207
for(i = 0; i < end; i++)
208
fill_slot(i);
209
}
210
}
211
212
int init_rw(uint_fast8_t n)
213
{
214
// If sizeof(uint_fast8_t) * (1ul << n) overflows, it wraps around to 0, since size_t and unsigned long are unsigned integer types.
215
if( (n > MAX_VERTICES) || ( (n>0) && !(sizeof(uint_fast8_t) * (1ul << n)) ) )
216
return(-1);
217
218
num_vertices = n;
219
adjacency_matrix = malloc(sizeof(subset_t) * n);
220
slots = malloc(sizeof(uint_fast8_t) * (1ul << n));
221
cslots = 0;
222
return((adjacency_matrix && slots) ? 0 : -1);
223
}
224
225
int init_rw_dec(uint_fast8_t n)
226
{
227
// If sizeof(subset_t) * (1ul << n) overflows, it wraps around to 0, since size_t and unsigned long are unsigned integer types.
228
if(n && !(sizeof(subset_t) * (1ul << n)))
229
return(-1);
230
231
if(init_rw(n))
232
return(-1);
233
cslots = malloc(sizeof(subset_t) * (1ul << n));
234
return(cslots ? 0 : -1);
235
}
236
237
void destroy_rw(void)
238
{
239
free(cslots);
240
free(slots);
241
free(adjacency_matrix);
242
}
243
244
uint_fast8_t get_rw(void)
245
{
246
return(slots[0xfffffffful >> (32 - num_vertices)]);
247
}
248
249
250