Path: blob/master/sage/graphs/graph_decompositions/rankwidth_c/rw.c
4099 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"2223static uint_fast8_t subset_size;2425static uint_fast8_t num_vertices;2627subset_t *adjacency_matrix;2829// This array is meant to contain max{f(Y), w(f, Y)} at the position corresponding to Y.30static uint_fast8_t *slots;31subset_t *cslots;3233uint_fast8_t cut_rank(const subset_t s)34{35subset_t am[num_vertices];36subset_t x, y;37uint_fast8_t i, j;38uint_fast8_t rank = 0;3940for(i = 0; i < num_vertices; i++)41am[i] = (s & (1ul << i)) ? 0 : (adjacency_matrix[i] & s);4243for(i = 0; i < num_vertices; i++)44{45y = 0;46for(j = rank; j < num_vertices; j++)47{48x = am[j];49if(x & 1)50{51if(!y)52{53y = x;54am[j] = am[rank++];55continue;56}57x ^= y;58}59am[j] = x >> 1;60}61}6263return(rank);64}6566// Compute the binomial coefficient C(n, k).67// Time complexity: O(n) * complexity of integer division.68// Could be replaced by a lookup table of size O(n^2), but since this is not the bopttleneck, it doesn't matter.69subset_t binomial_coefficient(uint_fast8_t n, uint_fast8_t k)70{71uint_fast8_t i, delta, max;72subset_t c;7374if(n < k)75return(0);7677if(n == k)78return(1);7980if(k < n - k)81{82delta = n - k;83max = k;84}85else86{87delta = k;88max = n - k;89}9091c = delta + 1;9293for(i = 2; i <= max; i++)94c = (c * (delta + i)) / i;9596return(c);97}9899// Convert unsigned integer from combinadic to machine representation.100subset_t comb_to_int(subset_t c)101{102uint_fast8_t k, n;103subset_t i;104105i = 0;106for(k = 0, n = 1; k < num_vertices; k++, c >>= 1)107if(c & 1)108i += binomial_coefficient(k, n++);109return(i);110}111112// Return largest value v where v < a and Choose(v,b) <= x.113static uint_fast8_t largest_v(uint_fast8_t a, uint_fast8_t b, subset_t x)114{115uint_fast8_t v = a - 1;116117while(binomial_coefficient(v,b) > x)118v--;119120return(v);121}122123// Convert unsigned integer from machine representation to combinadic.124static subset_t int_to_comb(subset_t i)125{126uint_fast8_t j, v;127uint_fast8_t a = num_vertices;128uint_fast8_t b = subset_size;129subset_t c = 0;130131for(j = 0; j < subset_size; j++, b--)132{133v = largest_v(a, b, i);134i = i - binomial_coefficient(v, b);135a = v;136c |= (1ul << v);137}138139return(c);140}141142// Masked increment.143static subset_t subset_inc(subset_t v, subset_t mask)144{145return((v - mask) & mask);146}147148// 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.149// This is where most of the time is spent.150uint_fast8_t width(subset_t s)151{152uint_fast8_t w = UINT_FAST8_MAX, v, v1, v2;153subset_t ss;154subset_t cs;155for(ss = subset_inc(0, s); ss != s; ss = subset_inc(ss, s))156{157v1 = slots[ss];158v2 = slots[s & ~ss];159v = v1 > v2 ? v1 : v2;160if(v < w)161{162w = v;163cs = ss;164}165}166cslots[s] = cs;167return(w);168}169170void fill_slot(subset_t i)171{172uint_fast8_t v, w;173subset_t s = int_to_comb(i);174v = cut_rank(s);175w = width(s);176slots[s] = v > w ? v : w;177}178179void calculate_level(uint_fast8_t ss)180{181uint_fast8_t i;182183subset_size = ss;184185if(subset_size == 0)186slots[0] = 0;187else if(subset_size == 1)188for(i = 0; i < num_vertices; i++)189{190slots[1ul << i] = cut_rank(1ul << i);191cslots[1ul << i] = 0x0;192}193else194{195subset_t i;196const subset_t end = binomial_coefficient(num_vertices, subset_size);197for(i = 0; i < end; i++)198fill_slot(i);199}200}201202void calculate_all(void)203{204uint_fast8_t i;205206for(i = 0; i < num_vertices; i++)207{208slots[1ul << i] = cut_rank(1ul << i);209cslots[1ul << i] = 0x0;210}211212for(subset_size = 2; subset_size <= num_vertices; subset_size++)213{214subset_t i;215const subset_t end = binomial_coefficient(num_vertices, subset_size);216for(i = 0; i < end; i++)217fill_slot(i);218}219}220221int init_rw(uint_fast8_t n)222{223// If sizeof(uint_fast8_t) * (1ul << n) overflows, it wraps around to 0, since size_t and unsigned long are unsigned integer types.224if( (n > MAX_VERTICES) || ( (n>0) && !(sizeof(uint_fast8_t) * (1ul << n)) ) )225return(-1);226227num_vertices = n;228adjacency_matrix = malloc(sizeof(subset_t) * n);229slots = malloc(sizeof(uint_fast8_t) * (1ul << n));230cslots = 0;231return((adjacency_matrix && slots) ? 0 : -1);232}233234int init_rw_dec(uint_fast8_t n)235{236// If sizeof(subset_t) * (1ul << n) overflows, it wraps around to 0, since size_t and unsigned long are unsigned integer types.237if(n && !(sizeof(subset_t) * (1ul << n)))238return(-1);239240if(init_rw(n))241return(-1);242cslots = malloc(sizeof(subset_t) * (1ul << n));243return(cslots ? 0 : -1);244}245246void destroy_rw(void)247{248free(cslots);249free(slots);250free(adjacency_matrix);251}252253uint_fast8_t get_rw(void)254{255return(slots[0xfffffffful >> (32 - num_vertices)]);256}257258259260