Path: blob/master/src/sage/graphs/graph_decompositions/rankwidth_c/rw.c
8819 views
// Calculate rank-width and rank-decompositions of graphs.12// Philipp Klaus Krause, [email protected], [email protected], 2009 - 20123// Copyright (c) 2009-2012 Philipp Klaus Krause45// This program is free software; you can redistribute it and/or modify6// it under the terms of the GNU General Public License as published by7// the Free Software Foundation; either version 2 of the License, or8// (at your option) any later version.9//10// This program is distributed in the hope that it will be useful,11// but WITHOUT ANY WARRANTY; without even the implied warranty of12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13// GNU General Public License for more details.14//15// You should have received a copy of the GNU General Public License along16// with this program; if not, write to the Free Software Foundation, Inc.,17// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.1819#include <stdlib.h>2021#include "rw.h"2223uint_fast8_t cut_rank(const subset_t s)24{25subset_t am[num_vertices];26subset_t x, y;27uint_fast8_t i, j;28uint_fast8_t rank = 0;2930for(i = 0; i < num_vertices; i++)31am[i] = (s & (1ul << i)) ? 0 : (adjacency_matrix[i] & s);3233for(i = 0; i < num_vertices; i++)34{35y = 0;36for(j = rank; j < num_vertices; j++)37{38x = am[j];39if(x & 1)40{41if(!y)42{43y = x;44am[j] = am[rank++];45continue;46}47x ^= y;48}49am[j] = x >> 1;50}51}5253return(rank);54}5556// Compute the binomial coefficient C(n, k).57// Time complexity: O(n) * complexity of integer division.58// Could be replaced by a lookup table of size O(n^2), but since this is not the bopttleneck, it doesn't matter.59subset_t binomial_coefficient(uint_fast8_t n, uint_fast8_t k)60{61uint_fast8_t i, delta, max;62subset_t c;6364if(n < k)65return(0);6667if(n == k)68return(1);6970if(k < n - k)71{72delta = n - k;73max = k;74}75else76{77delta = k;78max = n - k;79}8081c = delta + 1;8283for(i = 2; i <= max; i++)84c = (c * (delta + i)) / i;8586return(c);87}8889// Convert unsigned integer from combinadic to machine representation.90subset_t comb_to_int(subset_t c)91{92uint_fast8_t k, n;93subset_t i;9495i = 0;96for(k = 0, n = 1; k < num_vertices; k++, c >>= 1)97if(c & 1)98i += binomial_coefficient(k, n++);99return(i);100}101102// Return largest value v where v < a and Choose(v,b) <= x.103static uint_fast8_t largest_v(uint_fast8_t a, uint_fast8_t b, subset_t x)104{105uint_fast8_t v = a - 1;106107while(binomial_coefficient(v,b) > x)108v--;109110return(v);111}112113// Convert unsigned integer from machine representation to combinadic.114static subset_t int_to_comb(subset_t i)115{116uint_fast8_t j, v;117uint_fast8_t a = num_vertices;118uint_fast8_t b = subset_size;119subset_t c = 0;120121for(j = 0; j < subset_size; j++, b--)122{123v = largest_v(a, b, i);124i = i - binomial_coefficient(v, b);125a = v;126c |= (1ul << v);127}128129return(c);130}131132// Masked increment.133static subset_t subset_inc(subset_t v, subset_t mask)134{135return((v - mask) & mask);136}137138// 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.139// This is where most of the time is spent.140uint_fast8_t width(subset_t s)141{142uint_fast8_t w = UINT_FAST8_MAX, v, v1, v2;143subset_t ss;144subset_t cs;145for(ss = subset_inc(0, s); ss != s; ss = subset_inc(ss, s))146{147v1 = slots[ss];148v2 = slots[s & ~ss];149v = v1 > v2 ? v1 : v2;150if(v < w)151{152w = v;153cs = ss;154}155}156cslots[s] = cs;157return(w);158}159160void fill_slot(subset_t i)161{162uint_fast8_t v, w;163subset_t s = int_to_comb(i);164v = cut_rank(s);165w = width(s);166slots[s] = v > w ? v : w;167}168169void calculate_level(uint_fast8_t ss)170{171uint_fast8_t i;172173subset_size = ss;174175if(subset_size == 0)176slots[0] = 0;177else if(subset_size == 1)178for(i = 0; i < num_vertices; i++)179{180slots[1ul << i] = cut_rank(1ul << i);181cslots[1ul << i] = 0x0;182}183else184{185subset_t i;186const subset_t end = binomial_coefficient(num_vertices, subset_size);187for(i = 0; i < end; i++)188fill_slot(i);189}190}191192void calculate_all(void)193{194uint_fast8_t i;195196for(i = 0; i < num_vertices; i++)197{198slots[1ul << i] = cut_rank(1ul << i);199cslots[1ul << i] = 0x0;200}201202for(subset_size = 2; subset_size <= num_vertices; subset_size++)203{204subset_t i;205const subset_t end = binomial_coefficient(num_vertices, subset_size);206for(i = 0; i < end; i++)207fill_slot(i);208}209}210211int init_rw(uint_fast8_t n)212{213// If sizeof(uint_fast8_t) * (1ul << n) overflows, it wraps around to 0, since size_t and unsigned long are unsigned integer types.214if( (n > MAX_VERTICES) || ( (n>0) && !(sizeof(uint_fast8_t) * (1ul << n)) ) )215return(-1);216217num_vertices = n;218adjacency_matrix = malloc(sizeof(subset_t) * n);219slots = malloc(sizeof(uint_fast8_t) * (1ul << n));220cslots = 0;221return((adjacency_matrix && slots) ? 0 : -1);222}223224int init_rw_dec(uint_fast8_t n)225{226// If sizeof(subset_t) * (1ul << n) overflows, it wraps around to 0, since size_t and unsigned long are unsigned integer types.227if(n && !(sizeof(subset_t) * (1ul << n)))228return(-1);229230if(init_rw(n))231return(-1);232cslots = malloc(sizeof(subset_t) * (1ul << n));233return(cslots ? 0 : -1);234}235236void destroy_rw(void)237{238free(cslots);239free(slots);240free(adjacency_matrix);241}242243uint_fast8_t get_rw(void)244{245return(slots[0xfffffffful >> (32 - num_vertices)]);246}247248249250