[bliss] Initial import.
Jerry James
jjames at fedoraproject.org
Tue Nov 15 21:15:15 UTC 2011
commit 24330fbd1af6c27659841336668fd5d98670afbd
Author: Jerry James <loganjerry at gmail.com>
Date: Tue Nov 15 14:15:04 2011 -0700
Initial import.
.gitignore | 1 +
bliss-error.patch | 511 +++++++++++++++++++++++++++++++++++++++++++++++++++++
bliss.1 | 55 ++++++
bliss.spec | 107 +++++++++++
sources | 1 +
5 files changed, 675 insertions(+), 0 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index e69de29..8a01871 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/bliss-0.72.zip
diff --git a/bliss-error.patch b/bliss-error.patch
new file mode 100644
index 0000000..efd77c5
--- /dev/null
+++ b/bliss-error.patch
@@ -0,0 +1,511 @@
+--- ./graph.cc.orig 2011-05-12 06:29:46.000000000 -0600
++++ ./graph.cc 2011-10-28 21:22:57.464203395 -0600
+@@ -34,7 +34,10 @@
+ namespace bliss {
+
+ #define _INTERNAL_ERROR() fatal_error("%s:%d: internal error",__FILE__,__LINE__)
+-#define _OUT_OF_MEMORY() fatal_error("%s:%d: out of memory",__FILE__,__LINE__)
++#define _OUT_OF_MEMORY(label) do { \
++ fatal_error("%s:%d: out of memory",__FILE__,__LINE__); \
++ goto label; \
++ } while (0)
+
+ /*-------------------------------------------------------------------------
+ *
+@@ -279,20 +282,6 @@
+ *perm = i;
+ }
+
+-bool
+-AbstractGraph::is_automorphism(unsigned int* const perm)
+-{
+- _INTERNAL_ERROR();
+- return false;
+-}
+-
+-bool
+-AbstractGraph::is_automorphism(const std::vector<unsigned int>& perm) const
+-{
+- _INTERNAL_ERROR();
+- return false;
+-}
+-
+
+
+
+@@ -618,7 +607,7 @@
+ } PathInfo;
+
+
+-void
++bool
+ AbstractGraph::search(const bool canonical, Stats& stats)
+ {
+ const unsigned int N = get_nof_vertices();
+@@ -658,7 +647,7 @@
+ if(N == 0)
+ {
+ /* Nothing to do, return... */
+- return;
++ return true;
+ }
+
+ /* Initialize the partition ... */
+@@ -696,10 +685,10 @@
+ */
+ if(first_path_labeling) free(first_path_labeling);
+ first_path_labeling = (unsigned int*)calloc(N, sizeof(unsigned int));
+- if(!first_path_labeling) _OUT_OF_MEMORY();
++ if(!first_path_labeling) _OUT_OF_MEMORY(oom1);
+ if(best_path_labeling) free(best_path_labeling);
+ best_path_labeling = (unsigned int*)calloc(N, sizeof(unsigned int));
+- if(!best_path_labeling) _OUT_OF_MEMORY();
++ if(!best_path_labeling) _OUT_OF_MEMORY(oom2);
+
+ /*
+ * Is the initial partition discrete?
+@@ -710,7 +699,7 @@
+ update_labeling(best_path_labeling);
+ /* Update statistics */
+ stats.nof_leaf_nodes = 1;
+- return;
++ return true;
+ }
+
+ /*
+@@ -718,20 +707,39 @@
+ */
+ if(first_path_labeling_inv) free(first_path_labeling_inv);
+ first_path_labeling_inv = (unsigned int*)calloc(N, sizeof(unsigned int));
+- if(!first_path_labeling_inv) _OUT_OF_MEMORY();
++ if(!first_path_labeling_inv) _OUT_OF_MEMORY(oom3);
+ if(best_path_labeling_inv) free(best_path_labeling_inv);
+ best_path_labeling_inv = (unsigned int*)calloc(N, sizeof(unsigned int));
+- if(!best_path_labeling_inv) _OUT_OF_MEMORY();
++ if(!best_path_labeling_inv) _OUT_OF_MEMORY(oom4);
+
+ /*
+ * Allocate space for the automorphisms
+ */
+ if(first_path_automorphism) free(first_path_automorphism);
+ first_path_automorphism = (unsigned int*)malloc(N * sizeof(unsigned int));
+- if(!first_path_automorphism) _OUT_OF_MEMORY();
++ if(!first_path_automorphism) _OUT_OF_MEMORY(oom5);
+ if(best_path_automorphism) free(best_path_automorphism);
+ best_path_automorphism = (unsigned int*)malloc(N * sizeof(unsigned int));
+- if(!best_path_automorphism) _OUT_OF_MEMORY();
++ if(!best_path_automorphism) {
++ _OUT_OF_MEMORY(oom6);
++ oom6:
++ free(first_path_automorphism);
++ first_path_automorphism = NULL;
++ oom5:
++ free(best_path_labeling_inv);
++ best_path_labeling_inv = NULL;
++ oom4:
++ free(first_path_labeling_inv);
++ first_path_labeling_inv = NULL;
++ oom3:
++ free(best_path_labeling);
++ best_path_labeling = NULL;
++ oom2:
++ free(first_path_labeling);
++ first_path_labeling = NULL;
++ oom1:
++ return false;
++ }
+
+ /*
+ * Initialize orbit information so that all vertices are in their own orbits
+@@ -974,7 +982,6 @@
+ */
+ {
+ unsigned int next_split_element = UINT_MAX;
+- unsigned int* next_split_element_pos = 0;
+ unsigned int* ep = p.elements + cell->first;
+ if(current_node.fp_on)
+ {
+@@ -985,7 +992,6 @@
+ *ep < next_split_element and
+ first_path_orbits.is_minimal_representative(*ep)) {
+ next_split_element = *ep;
+- next_split_element_pos = ep;
+ }
+ }
+ }
+@@ -1001,7 +1007,6 @@
+ current_node.long_prune_redundant.find(*ep) ==
+ current_node.long_prune_redundant.end())) {
+ next_split_element = *ep;
+- next_split_element_pos = ep;
+ }
+ }
+ }
+@@ -1015,7 +1020,6 @@
+ current_node.long_prune_redundant.find(*ep) ==
+ current_node.long_prune_redundant.end())) {
+ next_split_element = *ep;
+- next_split_element_pos = ep;
+ }
+ }
+ }
+@@ -1203,8 +1207,10 @@
+
+ #if defined(BLISS_VERIFY_EQUITABLEDNESS)
+ /* The new partition should be equitable */
+- if(!is_equitable())
++ if(!is_equitable()) {
+ fatal_error("consistency check failed - partition after refinement is not equitable");
++ return false;
++ }
+ #endif
+
+ /*
+@@ -1366,6 +1372,7 @@
+ goto handle_first_path_automorphism;
+ /* Should never get here because of CR:FP */
+ _INTERNAL_ERROR();
++ return false;
+ }
+ }
+
+@@ -1598,8 +1605,10 @@
+
+ #if defined(BLISS_VERIFY_AUTOMORPHISMS)
+ /* Verify that it really is an automorphism */
+- if(!is_automorphism(best_path_automorphism))
++ if(!is_automorphism(best_path_automorphism)) {
+ fatal_error("Best path automorhism validation check failed");
++ return false;
++ }
+ #endif
+
+ unsigned int gca_level_with_first = 0;
+@@ -1666,6 +1675,7 @@
+
+
+ _INTERNAL_ERROR();
++ return false;
+
+
+ handle_first_path_automorphism:
+@@ -1701,8 +1711,10 @@
+
+ #if defined(BLISS_VERIFY_AUTOMORPHISMS)
+ /* Verify that it really is an automorphism */
+- if(!is_automorphism(first_path_automorphism))
++ if(!is_automorphism(first_path_automorphism)) {
+ fatal_error("First path automorphism validation check failed");
++ return false;
++ }
+ #endif
+
+ if(opt_use_long_prune)
+@@ -1749,12 +1761,13 @@
+ /* Release component recursion data in partition */
+ if(opt_use_comprec)
+ p.cr_free();
++ return true;
+ }
+
+
+
+
+-void
++bool
+ AbstractGraph::find_automorphisms(Stats& stats,
+ void (*hook)(void *user_param,
+ unsigned int n,
+@@ -1764,7 +1777,8 @@
+ report_hook = hook;
+ report_user_param = user_param;
+
+- search(false, stats);
++ if (!search(false, stats))
++ return false;
+
+ if(first_path_labeling)
+ {
+@@ -1776,6 +1790,7 @@
+ free(best_path_labeling);
+ best_path_labeling = 0;
+ }
++ return true;
+ }
+
+
+@@ -1790,7 +1805,8 @@
+ report_hook = hook;
+ report_user_param = user_param;
+
+- search(true, stats);
++ if (!search(true, stats))
++ return NULL;
+
+ return best_path_labeling;
+ }
+@@ -3480,15 +3496,17 @@
+ * Check whether perm is an automorphism.
+ * Slow, mainly for debugging and validation purposes.
+ */
+-bool
++int
+ Digraph::is_automorphism(unsigned int* const perm)
+ {
+ std::set<unsigned int, std::less<unsigned int> > edges1;
+ std::set<unsigned int, std::less<unsigned int> > edges2;
+
+ #if defined(BLISS_CONSISTENCY_CHECKS)
+- if(!is_permutation(get_nof_vertices(), perm))
++ if(!is_permutation(get_nof_vertices(), perm)) {
+ _INTERNAL_ERROR();
++ return -1;
++ }
+ #endif
+
+ for(unsigned int i = 0; i < get_nof_vertices(); i++)
+@@ -3507,7 +3525,7 @@
+ ei++)
+ edges2.insert(*ei);
+ if(!(edges1 == edges2))
+- return false;
++ return 0;
+
+ edges1.clear();
+ for(std::vector<unsigned int>::iterator ei = v1.edges_out.begin();
+@@ -3520,10 +3538,10 @@
+ ei++)
+ edges2.insert(*ei);
+ if(!(edges1 == edges2))
+- return false;
++ return 0;
+ }
+
+- return true;
++ return 1;
+ }
+
+ bool
+@@ -4330,8 +4348,10 @@
+ Graph::permute(const unsigned int* perm) const
+ {
+ #if defined(BLISS_CONSISTENCY_CHECKS)
+- if(!is_permutation(get_nof_vertices(), perm))
++ if(!is_permutation(get_nof_vertices(), perm)) {
+ _INTERNAL_ERROR();
++ return NULL;
++ }
+ #endif
+
+ Graph* const g = new Graph(get_nof_vertices());
+@@ -5270,15 +5290,17 @@
+ *
+ *-------------------------------------------------------------------------*/
+
+-bool
++int
+ Graph::is_automorphism(unsigned int* const perm)
+ {
+ std::set<unsigned int, std::less<unsigned int> > edges1;
+ std::set<unsigned int, std::less<unsigned int> > edges2;
+
+ #if defined(BLISS_CONSISTENCY_CHECKS)
+- if(!is_permutation(get_nof_vertices(), perm))
++ if(!is_permutation(get_nof_vertices(), perm)) {
+ _INTERNAL_ERROR();
++ return -1;
++ }
+ #endif
+
+ for(unsigned int i = 0; i < get_nof_vertices(); i++)
+@@ -5298,10 +5320,10 @@
+ edges2.insert(*ei);
+
+ if(!(edges1 == edges2))
+- return false;
++ return 0;
+ }
+
+- return true;
++ return 1;
+ }
+
+
+--- ./bliss_C.cc.orig 2011-05-12 06:29:46.000000000 -0600
++++ ./bliss_C.cc 2011-10-28 21:22:39.428577545 -0600
+@@ -131,7 +131,7 @@
+ }
+
+ extern "C"
+-void
++int
+ bliss_find_automorphisms(BlissGraph *graph,
+ void (*hook)(void *user_param,
+ unsigned int n,
+@@ -142,7 +142,8 @@
+ bliss::Stats s;
+ assert(graph);
+ assert(graph->g);
+- graph->g->find_automorphisms(s, hook, hook_user_param);
++ if (!graph->g->find_automorphisms(s, hook, hook_user_param))
++ return 0;
+
+ if(stats)
+ {
+@@ -154,6 +155,7 @@
+ stats->nof_generators = s.get_nof_generators();
+ stats->max_level = s.get_max_level();
+ }
++ return 1;
+ }
+
+
+@@ -173,7 +175,7 @@
+
+ canonical_labeling = graph->g->canonical_form(s, hook, hook_user_param);
+
+- if(stats)
++ if(canonical_labeling && stats)
+ {
+ stats->group_size_approx = s.get_group_size_approx();
+ stats->nof_nodes = s.get_nof_nodes();
+--- ./bliss.cc.orig 2011-05-12 06:29:46.000000000 -0600
++++ ./bliss.cc 2011-10-28 21:22:39.429577524 -0600
+@@ -276,13 +276,16 @@
+ if(opt_canonize == false)
+ {
+ /* No canonical labeling, only automorphism group */
+- g->find_automorphisms(stats, &report_aut, stdout);
++ if (!g->find_automorphisms(stats, &report_aut, stdout))
++ exit(1);
+ }
+ else
+ {
+ /* Canonical labeling and automorphism group */
+ const unsigned int* cl = g->canonical_form(stats, &report_aut, stdout);
+
++ if (!cl)
++ exit(1);
+ fprintf(stdout, "Canonical labeling: ");
+ bliss::print_permutation(stdout, g->get_nof_vertices(), cl, 1);
+ fprintf(stdout, "\n");
+@@ -290,6 +293,8 @@
+ if(opt_output_can_file)
+ {
+ bliss::AbstractGraph* cf = g->permute(cl);
++ if (!cf)
++ exit(1);
+ FILE* const fp = fopen(opt_output_can_file, "w");
+ if(!fp)
+ _fatal("Cannot open '%s' for outputting the canonical form, aborting", opt_output_can_file);
+--- ./defs.cc.orig 2011-05-12 06:29:46.000000000 -0600
++++ ./defs.cc 2011-10-28 21:22:39.429577524 -0600
+@@ -33,7 +33,6 @@
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\nAborting!\n");
+ va_end(ap);
+- exit(1);
+ }
+
+ }
+--- ./bliss_C.h.orig 2011-05-12 06:29:46.000000000 -0600
++++ ./bliss_C.h 2011-10-28 21:22:39.430577503 -0600
+@@ -156,6 +156,7 @@
+ * The argument \a perm should be an array of
+ * N=bliss::bliss_get_nof_vertices(\a graph) elements describing
+ * a bijection on {0,...,N-1}.
++ * Returns NULL if insufficient memory or internal error.
+ */
+ BlissGraph *bliss_permute(BlissGraph *graph, const unsigned int *perm);
+
+@@ -174,8 +175,9 @@
+ * if you want to use the automorphism later, you have to take a copy of it.
+ * Do not call bliss_* functions in the hook.
+ * If \a stats is non-null, then some search statistics are copied there.
++ * \return nonzero if successful, zero if insufficient memory or internal error
+ */
+-void
++int
+ bliss_find_automorphisms(BlissGraph *graph,
+ void (*hook)(void *user_param,
+ unsigned int N,
+@@ -194,6 +196,7 @@
+ * then bliss_permute() with the returned canonical labeling.
+ * Note that the computed canonical version may depend on the applied version
+ * of bliss.
++ * Returns NULL if insufficient memory or internal error.
+ */
+ const unsigned int *
+ bliss_find_canonical_labeling(BlissGraph *graph,
+--- ./graph.hh.orig 2011-05-12 06:29:46.000000000 -0600
++++ ./graph.hh 2011-10-28 21:27:16.463811606 -0600
+@@ -270,7 +270,7 @@
+ void reset_permutation(unsigned int *perm);
+
+ /* Mainly for debugging purposes */
+- virtual bool is_automorphism(unsigned int* const perm);
++ virtual int is_automorphism(unsigned int* const perm) = 0;
+
+ std::vector<unsigned int> certificate_current_path;
+ std::vector<unsigned int> certificate_first_path;
+@@ -284,7 +284,11 @@
+ virtual Partition::Cell* find_next_cell_to_be_splitted(Partition::Cell *cell) = 0;
+
+
+- void search(const bool canonical, Stats &stats);
++ /**
++ * \return true if successful, false if insufficient memory to complete or
++ * other internal error
++ */
++ bool search(const bool canonical, Stats &stats);
+
+
+ void (*report_hook)(void *user_param,
+@@ -362,7 +366,7 @@
+ * Check whether \a perm is an automorphism of this graph.
+ * Unoptimized, mainly for debugging purposes.
+ */
+- virtual bool is_automorphism(const std::vector<unsigned int>& perm) const;
++ virtual bool is_automorphism(const std::vector<unsigned int>& perm) const = 0;
+
+
+
+@@ -427,8 +431,10 @@
+ * if you want to use the automorphism later, you have to take a copy of it.
+ * Do not call any member functions in the hook.
+ * The search statistics are copied in \a stats.
++ * \return true if successful, false if insufficient memory to search or
++ * other internal error.
+ */
+- void find_automorphisms(Stats& stats,
++ bool find_automorphisms(Stats& stats,
+ void (*hook)(void* user_param,
+ unsigned int n,
+ const unsigned int* aut),
+@@ -448,6 +454,8 @@
+ * Note that the computed canonical version may depend on the applied version
+ * of bliss as well as on some other options (for instance, the splitting
+ * heuristic selected with bliss::Graph::set_splitting_heuristic()).
++ * This function returns NULL if there is insufficient memory, or another
++ * internal error occurs.
+ */
+ const unsigned int* canonical_form(Stats& stats,
+ void (*hook)(void* user_param,
+@@ -615,7 +623,7 @@
+
+ void initialize_certificate();
+
+- bool is_automorphism(unsigned int* const perm);
++ int is_automorphism(unsigned int* const perm);
+
+
+ bool nucr_find_first_component(const unsigned int level);
+@@ -856,7 +864,7 @@
+
+ void initialize_certificate();
+
+- bool is_automorphism(unsigned int* const perm);
++ int is_automorphism(unsigned int* const perm);
+
+ void sort_edges();
+
diff --git a/bliss.1 b/bliss.1
new file mode 100644
index 0000000..f652c3d
--- /dev/null
+++ b/bliss.1
@@ -0,0 +1,55 @@
+.TH "BLISS" "1" "@VERSION@" "Tommi Junttila & Petteri Kaski" "User Commands"
+.SH "NAME"
+bliss \- Compute automorphism groups and canonical labelings of graphs
+.SH "SYNOPSIS"
+.B bliss
+[\fIOPTIONS\fR] [<\fIGRAPH FILE\fR>]
+.SH "DESCRIPTION"
+.PP
+Bliss is an open source tool for computing automorphism groups and
+canonical forms of graphs. The graphs are specified in DIMACS format.
+.TP
+\fB\-directed\fR
+the input graph is directed
+.TP
+\fB\-can\fR
+compute canonical form
+.TP
+\fB\-ocan\fR=\fIf\fR
+compute canonical form and output it in file \fIf\fR
+.TP
+\fB\-v\fR=\fIN\fR
+set verbosity level to N [N >= 0, default: 1]
+.TP
+\fB\-sh\fR=\fIX\fR
+select splitting heuristics, where X is:
+.TS
+tab(;);
+R L.
+f;first non-singleton cell
+fl;first largest non-singleton cell
+fs;first smallest non-singleton cell
+fm;first maximally non-trivially connected non-singleton cell
+flm;first largest maximally non-trivially connected
+;non-singleton cell
+fsm;first smallest maximally non-trivially connected
+;non-singleton cell (default)
+.TE
+.TP
+\fB\-fr\fR=\fIX\fR
+use failure recording? [X=y/n, default: y]
+.TP
+\fB\-cr\fR=\fIX\fR
+use component recursion? [X=y/n, default: y]
+.TP
+\fB\-version\fR
+print the version number and exit
+.TP
+\fB\-help\fR
+print this help and exit
+.SH "AUTHORS"
+Bliss was written by Tommi Junttila <Tommi.Junttila at tkk.fi> and
+Petteri Kaski <petteri.kaski at aalto.fi>.
+.PP
+This man page was written by Jerry James <loganjerry at gmail.com>.
+It is distributed under the same terms as bliss.
diff --git a/bliss.spec b/bliss.spec
new file mode 100644
index 0000000..6f42e0b
--- /dev/null
+++ b/bliss.spec
@@ -0,0 +1,107 @@
+Name: bliss
+Version: 0.72
+Release: 2%{?dist}
+Summary: Compute automorphism groups and canonical labelings of graphs
+
+Group: Applications/Engineering
+License: GPLv3
+URL: http://www.tcs.hut.fi/Software/bliss/
+Source0: http://www.tcs.hut.fi/Software/bliss/%{name}-%{version}.zip
+# Man page written by Jerry James using text borrowed from the sources.
+# The man page therefore has the same copyright and license as the sources.
+Source1: bliss.1
+# Sent upstream 28 Oct 2011. Don't call exit() in library code.
+Patch0: bliss-error.patch
+
+BuildRequires: doxygen
+BuildRequires: gmp-devel
+Requires: %{name}-libs%{?_isa} = %{version}-%{release}
+
+%global sover %(echo %{version} | cut -d. -f1)
+
+%description
+Bliss is an open source tool for computing automorphism groups and
+canonical forms of graphs. It has both a command line user interface as
+well as C++ and C programming language APIs.
+
+%package devel
+Summary: Headers and library files for developing with bliss
+Group: Development/Libraries
+Requires: %{name}-libs%{?_isa} = %{version}-%{release}
+Requires: gmp-devel%{?_isa}
+
+%description devel
+Headers and library files needed to develop applications that use the
+bliss library.
+
+%package libs
+Summary: Compute automorphism groups and canonical labelings of graphs
+Group: Development/Libraries
+
+%description libs
+A command-line bliss tool to access the functionality of the bliss
+library.
+
+%prep
+%setup -q
+%patch0
+
+%build
+# The Makefile creates a static library, so we roll our own shared library
+# here instead. Also, avoid an unused direct dependency on libm.
+g++ $RPM_OPT_FLAGS -DBLISS_USE_GMP -fPIC -shared -o libbliss.so.%{version} \
+ -Wl,-soname,libbliss.so.%{sover} defs.cc graph.cc partition.cc orbit.cc \
+ uintseqhash.cc heap.cc timer.cc utils.cc bliss_C.cc -lgmp -Wl,--as-needed
+ln -s libbliss.so.%{version} libbliss.so.%{sover}
+ln -s libbliss.so.%{sover} libbliss.so
+
+# The Makefile doesn't know how to link the binary against a shared library.
+# Also, once again avoid an unused direct dependency on libm.
+g++ $RPM_OPT_FLAGS -DBLISS_USE_GMP -o bliss bliss.cc -L. -lbliss -lgmp \
+ -Wl,--as-needed
+
+# Build the documentation
+doxygen
+
+%install
+# The Makefile has no install target.
+
+# Install the library
+mkdir -p $RPM_BUILD_ROOT%{_libdir}
+cp -a libbliss.* $RPM_BUILD_ROOT%{_libdir}
+
+# Install the header files
+mkdir -p $RPM_BUILD_ROOT%{_includedir}/bliss
+cp -p *.h *.hh $RPM_BUILD_ROOT%{_includedir}/bliss
+
+# Install the binary
+mkdir -p $RPM_BUILD_ROOT%{_bindir}
+cp -p bliss $RPM_BUILD_ROOT%{_bindir}
+
+# Install the man page
+mkdir -p $RPM_BUILD_ROOT%{_mandir}/man1
+cp -p %{SOURCE1} $RPM_BUILD_ROOT%{_mandir}/man1
+
+%post libs -p /sbin/ldconfig
+
+%postun libs -p /sbin/ldconfig
+
+%files
+%{_bindir}/bliss
+%{_mandir}/man1/bliss.1*
+
+%files devel
+%doc html
+%{_includedir}/bliss
+%{_libdir}/libbliss.so
+
+%files libs
+%doc COPYING.txt
+%{_libdir}/libbliss.so.*
+
+%changelog
+* Tue Nov 15 2011 Jerry James <loganjerry at gmail.com> - 0.72-2
+- Add patch to avoid calling exit() in the library
+
+* Wed Jul 20 2011 Jerry James <loganjerry at gmail.com> - 0.72-1
+- Initial RPM
diff --git a/sources b/sources
index e69de29..e3aca36 100644
--- a/sources
+++ b/sources
@@ -0,0 +1 @@
+6f0e114944fa0863870b7f631850abb2 bliss-0.72.zip
More information about the scm-commits
mailing list