diff --git a/.gitignore b/.gitignore index 349eecb..ff145ef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -/cliquer-*.tar.gz +/cliquer-1.21.tar.gz /cliquer.pdf /cliquer_bm.pdf /cliquer_fm.pdf diff --git a/README.md b/README.md deleted file mode 100644 index 2144f2f..0000000 --- a/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# cliquer - -[Cliquer](https://users.aalto.fi/~pat/cliquer.html) is a set of C routines for -finding cliques in an arbitrary weighted graph. It uses an exact -branch-and-bound algorithm developed by Patric Östergård. It is designed with -the aim of being efficient while still being flexible and easy to use. diff --git a/basic.c b/basic.c new file mode 100644 index 0000000..54c455f --- /dev/null +++ b/basic.c @@ -0,0 +1,24 @@ + +#include +#include "cliquer.h" + +int main(int argc, char *argv[]) { + graph_t *g; + set_t s; + + if (argc!=2) { + fprintf(stderr,"%s \n",argv[0]); + return 1; + } + g=graph_read_dimacs_file(argv[1]); + if (g==NULL) + return 1; + + ASSERT(graph_test(g,stderr)); + + s=clique_find_single(g,0,0,FALSE,NULL); + set_print(s); + + return 0; +} + diff --git a/changelog b/changelog deleted file mode 100644 index 2695ffc..0000000 --- a/changelog +++ /dev/null @@ -1,102 +0,0 @@ -* Wed Jul 23 2025 Fedora Release Engineering - 1.22-11 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild - -* Thu Jan 16 2025 Fedora Release Engineering - 1.22-10 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild - -* Wed Jul 17 2024 Fedora Release Engineering - 1.22-9 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild - -* Wed Jan 24 2024 Fedora Release Engineering - 1.22-8 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - -* Fri Jan 19 2024 Fedora Release Engineering - 1.22-7 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - -* Wed Jul 19 2023 Fedora Release Engineering - 1.22-6 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild - -* Thu Jan 19 2023 Fedora Release Engineering - 1.22-5 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild - -* Tue Dec 20 2022 Jerry James - 1.22-4 -- Convert License tag to SPDX - -* Wed Jul 20 2022 Fedora Release Engineering - 1.22-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild - -* Wed Jan 19 2022 Fedora Release Engineering - 1.22-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild - -* Wed Jul 21 2021 Fedora Release Engineering - 1.22-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild - -* Thu Jun 17 2021 Jerry James - 1.22-1 -- Version 1.22 -- New URLs -- Drop upstreamed -sagemath patch -- Use autotools to build - -* Tue Jan 26 2021 Fedora Release Engineering - 1.21-20 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild - -* Mon Jul 27 2020 Fedora Release Engineering - 1.21-19 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild - -* Tue Jan 28 2020 Fedora Release Engineering - 1.21-18 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild - -* Wed Jul 24 2019 Fedora Release Engineering - 1.21-17 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild - -* Thu Jan 31 2019 Fedora Release Engineering - 1.21-16 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild - -* Thu Jul 12 2018 Fedora Release Engineering - 1.21-15 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild - -* Wed Feb 07 2018 Fedora Release Engineering - 1.21-14 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild - -* Wed Aug 02 2017 Fedora Release Engineering - 1.21-13 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild - -* Wed Jul 26 2017 Fedora Release Engineering - 1.21-12 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild - -* Fri Feb 10 2017 Fedora Release Engineering - 1.21-11 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild - -* Wed Feb 03 2016 Fedora Release Engineering - 1.21-10 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild - -* Wed Jun 17 2015 Fedora Release Engineering - 1.21-9 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild - -* Sat Aug 16 2014 Fedora Release Engineering - 1.21-8 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild - -* Sat Jun 07 2014 Fedora Release Engineering - 1.21-7 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild - -* Sat Aug 03 2013 Fedora Release Engineering - 1.21-6 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild - -* Wed Feb 13 2013 Fedora Release Engineering - 1.21-5 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild - -* Wed Aug 15 2012 pcpa - 1.21-4 -- Do not hardcode version in shell commands (#825494) -- Correct permission of generated library and binary (#825494) - -* Tue Aug 14 2012 pcpa - 1.21-3 -- Remove %%defattr from spec (#825494) -- Correct mixed spaces and tabs in spec (#825494) -- Correct FSF address (#825494) -- Update information about sagemath patches to upstream cliquer (#825494) - -* Sat May 26 2012 pcpa - 1.21-2 -- Add sagemath patch interface - -* Wed Nov 16 2011 Jerry James - 1.21-1 -- Initial RPM diff --git a/cl.h b/cl.h new file mode 100644 index 0000000..cd08505 --- /dev/null +++ b/cl.h @@ -0,0 +1,33 @@ + +#include +#include +#include + +#ifdef ENABLE_LONG_OPTIONS +#include +#endif + +#include "cliquer.h" + + +#define TRYFORHELP "Try `%s -h' for more information.\n",argv[0] + +void printhelp(char *prog); +void read_options(int argc, char **argv); +void print_search(graph_t *g); +boolean record_clique_func(set_t s,graph_t *g,clique_options *opts); +boolean print_clique_func(set_t s,graph_t *g,clique_options *opts); +void print_clique(set_t s,graph_t *g); + +// As the global variables remain between two SAGE call, they +// have to be reset each time +void sage_reset_global_variables(); +// The opt structure has to be initialised in each SAGE function +clique_options * sage_init_clique_opt(); +// Computes a maximum clique of the graph g and return its size +// The table list contains the ID of the vertices +int sage_clique_max(graph_t *g,int **list); +int sage_all_clique_max(graph_t *g,int **list); +int sage_clique_number(graph_t *g); + + diff --git a/cliquer-sagemath.patch b/cliquer-sagemath.patch new file mode 100644 index 0000000..aea47f9 --- /dev/null +++ b/cliquer-sagemath.patch @@ -0,0 +1,178 @@ +diff -up cliquer-1.21/cl.c.orig cliquer-1.21/cl.c +--- cliquer-1.21/cl.c.orig 2012-05-09 01:22:23.361598133 -0300 ++++ cliquer-1.21/cl.c 2012-05-09 01:26:12.768606918 -0300 +@@ -3,17 +3,21 @@ + #include + #include + ++#ifdef MAIN + #ifdef ENABLE_LONG_OPTIONS + #include + #endif ++#endif + + #include "cliquer.h" + + + #define TRYFORHELP "Try `%s -h' for more information.\n",argv[0] + ++#ifdef MAIN + void printhelp(char *prog); + void read_options(int argc, char **argv); ++#endif + void print_search(graph_t *g); + boolean record_clique_func(set_t s,graph_t *g,clique_options *opts); + boolean print_clique_func(set_t s,graph_t *g,clique_options *opts); +@@ -39,7 +43,131 @@ static set_t *clique_list; + static int clique_count=0; + static int clique_list_size=0; + ++// As the global variables remain between two SAGE call, they ++// have to be reset each time ++void sage_reset_global_variables(){ ++ find_all=FALSE; ++ min_weight=0; ++ min_weight_set=FALSE; ++ max_weight=0; ++ max_weight_set=FALSE; ++ maximal=FALSE; ++ unweighted=FALSE; ++ number1=TRUE; ++ quiet=0; ++ only_weight=FALSE; ++ clique_count=0; ++ clique_list_size=0; ++} ++ ++ ++// The opt structure has to be initialised in each SAGE function ++clique_options * sage_init_clique_opt(){ ++ sage_reset_global_variables(); ++ clique_options *opts; ++ quiet++; ++ opts=malloc(sizeof(clique_options)); ++ if (quiet) ++ opts->time_function=NULL; ++ else ++ opts->time_function=clique_print_time; ++ opts->output=stderr; ++ opts->reorder_function=reorder; ++ opts->reorder_map=NULL; ++ // Without commenting these lines the sage_all_clique_max ++ // function does not work correctly ++ ++ /* ++ if (quiet) ++ opts->user_function=print_clique_func; ++ else ++ */ ++ opts->user_function=record_clique_func; ++ opts->user_data=NULL; ++ opts->clique_list=NULL; ++ opts->clique_list_length=0; ++ return opts; ++} ++ ++ ++// Computes a maximum clique of the graph g and return its size ++// The table list contains the ID of the vertices ++int sage_clique_max(graph_t *g,int **list){ ++ sage_reset_global_variables(); ++ quiet++; ++ find_all=FALSE; ++ maximal=TRUE; ++ number1=FALSE; ++ set_t s; ++ int i,l; ++ s=clique_unweighted_find_single(g,min_weight, ++ max_weight,maximal, ++ sage_init_clique_opt()); ++ ++ // Writing the answer into a int [] to be read by Sage ++ int size=set_size(s); ++ *list=malloc(sizeof(int)*size); ++ l=0; ++ for (i=0; i|' %{SOURCE4} > example/basic.c +sed 's|"cliquer.h"||' %{SOURCE5} > example/hamming.c +sed 's|"cliquer.h"||' %{SOURCE6} > example/poly.c +cp -p %{SOURCE7} example -%conf sed -i \ 's/59 Temple Place, Suite 330, Boston, MA 02111-1307/51 Franklin Street, Suite 500, Boston, MA 02110-1335/' \ - COPYING + LICENSE %build -%configure --disable-static --disable-silent-rules +# The distributed Makefile just builds a binary named "cl". However, the +# examples show that the internal code is clearly meant to be used as a +# library. So we build a library by hand. +gcc ${RPM_OPT_FLAGS} -fPIC -c cl.c +gcc ${RPM_OPT_FLAGS} -fPIC -c cliquer.c +gcc ${RPM_OPT_FLAGS} -fPIC -c graph.c +gcc ${RPM_OPT_FLAGS} -fPIC -c reorder.c +gcc ${RPM_OPT_FLAGS} -fPIC -shared -o libcliquer.so.%{version} \ + -Wl,-soname=libcliquer.so.1 cl.o cliquer.o graph.o reorder.o +ln -s libcliquer.so.%{version} libcliquer.so.1 +ln -s libcliquer.so.1 libcliquer.so -# Get rid of undesirable hardcoded rpaths; workaround libtool reordering -# -Wl,--as-needed after all the libraries. -sed -e 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' \ - -e 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' \ - -e 's|CC="\(.*g..\)"|CC="\1 -Wl,--as-needed"|' \ - -i libtool - -%make_build +# Now build the binary +gcc ${RPM_OPT_FLAGS} -DENABLE_LONG_OPTIONS -DMAIN -c cl.c +gcc ${RPM_OPT_FLAGS} -o cliquer cl.o -L. -lcliquer %install -%make_install +# Install the library +mkdir -p $RPM_BUILD_ROOT%{_libdir} +cp -pP libcliquer.so* $RPM_BUILD_ROOT%{_libdir} +chmod 0755 $RPM_BUILD_ROOT%{_libdir}/libcliquer.so.%{version} -# Add missing executable bit -chmod 0755 %{buildroot}%{_libdir}/libcliquer.so.1.* +# Install the binary +mkdir -p $RPM_BUILD_ROOT%{_bindir} +install -m 0755 -p cliquer $RPM_BUILD_ROOT%{_bindir}/cliquer -# We do not want to install the examples -rm -fr %{buildroot}%{_datadir}/%{name} - -# The name "cl" is very short and ambiguous -mv %{buildroot}%{_bindir}/cl %{buildroot}%{_bindir}/%{name} +# Install the header file +mkdir -p $RPM_BUILD_ROOT%{_includedir}/cliquer +cp -p %{SOURCE9} cliquer.h cliquerconf.h graph.h misc.h reorder.h set.h $RPM_BUILD_ROOT%{_includedir}/cliquer # Install the man page -mkdir -p %{buildroot}%{_mandir}/man1 -cp -p %{SOURCE4} %{buildroot}%{_mandir}/man1 +mkdir -p $RPM_BUILD_ROOT%{_mandir}/man1 +cp -p %{SOURCE8} $RPM_BUILD_ROOT%{_mandir}/man1 %check -LD_LIBRARY_PATH=$PWD make test +LD_LIBRARY_PATH=. make test CFLAGS="${RPM_OPT_FLAGS}" + +%post libs -p /sbin/ldconfig + +%postun libs -p /sbin/ldconfig %files %doc cliquer*.pdf @@ -84,14 +112,44 @@ LD_LIBRARY_PATH=$PWD make test %{_mandir}/man1/* %files libs -%doc ChangeLog README -%license COPYING -%{_libdir}/libcliquer.so.1{,.*} +%doc ChangeLog LICENSE README example +%{_libdir}/libcliquer.so.* %files devel %{_includedir}/%{name}/ %{_libdir}/libcliquer.so -%{_libdir}/pkgconfig/libcliquer.pc %changelog -%autochangelog +* Wed Feb 03 2016 Fedora Release Engineering - 1.21-10 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Wed Jun 17 2015 Fedora Release Engineering - 1.21-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Sat Aug 16 2014 Fedora Release Engineering - 1.21-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Sat Jun 07 2014 Fedora Release Engineering - 1.21-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Sat Aug 03 2013 Fedora Release Engineering - 1.21-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Wed Feb 13 2013 Fedora Release Engineering - 1.21-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Wed Aug 15 2012 pcpa - 1.21-4 +- Do not hardcode version in shell commands (#825494) +- Correct permission of generated library and binary (#825494) + +* Tue Aug 14 2012 pcpa - 1.21-3 +- Remove %%defattr from spec (#825494) +- Correct mixed spaces and tabs in spec (#825494) +- Correct FSF address (#825494) +- Update information about sagemath patches to upstream cliquer (#825494) + +* Sat May 26 2012 pcpa - 1.21-2 +- Add sagemath patch interface + +* Wed Nov 16 2011 Jerry James - 1.21-1 +- Initial RPM diff --git a/hamming.c b/hamming.c new file mode 100644 index 0000000..11ab412 --- /dev/null +++ b/hamming.c @@ -0,0 +1,46 @@ +#include +#include "cliquer.h" + +/* Function for determining the Hamming distance between + two words, c1 and c2, of length n */ +int distance(int c1, int c2, int n) { + int i, c, d; + + d = 0; + c = c1 ^ c2; + + for (i = 0; i < n; i++) { + if(c & 1) d++; + c >>= 1; + } + return d; +} + +int main(int argc, char *argv[]) { + int i, j; + int n, M, d; + int order; + int nr; + graph_t *g; + + if (argc!=4) { + fprintf(stderr,"%s \n",argv[0]); + return 1; + } + n = atoi(argv[1]); + M = atoi(argv[2]); + d = atoi(argv[3]); + + /* no timer */ + clique_default_options->time_function = NULL; + + order = 1 << n; + g = graph_new(order); + for (i = 0; i < order; i++) + for (j = i+1; j < order; j++) + if(distance(i,j,n) >= d) + GRAPH_ADD_EDGE(g,i,j); + nr = clique_find_all(g,M,M,FALSE,clique_default_options); + printf("Number of codes: %d\n",nr); + return 0; +} diff --git a/poly.c b/poly.c new file mode 100644 index 0000000..cc7c881 --- /dev/null +++ b/poly.c @@ -0,0 +1,169 @@ +/* poly.c (needs tetromino.h) +This program demonstrates packing +tetrominoes (pieces made of four squares of equal size arranged +with coincident sides) on an n x m board so that no more tetrominoes +can fit. It takes four command-line arguments: +poly n m min max +where n and m are the dimensions of the board and min and max are +passed to clique_find_all as the number of pieces to fit on the +board. For example, +poly 5 5 3 3 +prints all the ways to fit three tetrominoes on a 5 x 5 board so that +no other tetrominoes could fit, and +poly 6 5 0 0 +finds all the ways to fit as many pieces as possible on a 6 x 5 board. +This program was inspired by Solomon W. Golomb's Puzzle Column +"Placing Pentominoes on Boards" in the IEEE Information Theory Society +Newsletter, Vol. 52, No. 2, June 2002, p. 7. */ + +#include +#include +#include "cliquer.h" + +#define POLYSIZE 4 + +struct polynomino { + char *name; + int sizex, sizey; + char block[POLYSIZE*POLYSIZE+1]; +}; + +#include "tetromino.h" + +#define VALUE(p,x,y) ((p)*boardsize+(y)*boardx+(x)) +#define PIECE(p) ((p)/(boardsize)) +#define POSX(p) ((p)%boardx) +#define POSY(p) (((p)%(boardsize))/boardx) + +static int boardx,boardy; +static int boardsize; +static int minpieces; +static int maxpieces; + +static graph_t *generate_graph(void); +static boolean print_clique(set_t s, graph_t *g, clique_options *opts); + +int main(int argc, char *argv[]) { + graph_t *g; + + if (argc!=5) { + fprintf(stderr,"%s " + "\n",argv[0]); + return 1; + } + boardx=atoi(argv[1]); + boardy=atoi(argv[2]); + boardsize=boardx*boardy; + minpieces=atoi(argv[3]); + maxpieces=atoi(argv[4]); + if ((boardx <= 0) || (boardy <= 0) || (maxpieces<0) || (minpieces<0)) { + fprintf(stderr,"Illegal arguments.\n"); + return 1; + } + + printf("Gen graph...\n"); + g=generate_graph(); + printf("Testing...\n"); + graph_test(g,stdout); + + clique_default_options->output=stderr; + clique_default_options->user_function=print_clique; + clique_find_all(g,minpieces,maxpieces,TRUE,NULL); + + return 0; +} + + +static boolean collides(int t1, int x1, int y1, int t2, int x2, int y2) { + int x,y; + + for (x=MAX(x1,x2); x boardx) + break; + for (y1=0; y1 boardy) + break; + for (t2=0; t2 boardx) + break; + for (y2=0; y2 boardy) + break; + if (!collides(t1,x1,y1,t2,x2,y2)) + GRAPH_ADD_EDGE(g, + VALUE(t1,x1,y1), + VALUE(t2,x2,y2)); + } + } + } + } + } + } + return g; +} + + + +static boolean print_clique(set_t s, graph_t *g, clique_options *opts) { + static char *buf=NULL; + int i,j,c,n; + int t,x,y; + + if (buf==NULL) { + buf=malloc((boardx*2+1)*boardy+10); + } + + c=0; + for (i=0; i= 0) { + t=PIECE(n); + x=POSX(n); + y=POSY(n); + + if (x+tetromino[t].sizex > boardx) + return TRUE; + if (y+tetromino[t].sizey > boardy) + return TRUE; + + for (i=0; i