[med-svn] [Git][med-team/igraph][master] 5 commits: New upstream version 0.9.8
Jérôme Benoit (@calculus)
gitlab at salsa.debian.org
Sat Apr 9 14:48:41 BST 2022
Jérôme Benoit pushed to branch master at Debian Med / igraph
Commits:
fff966a1 by Jerome Benoit at 2022-04-09T15:01:23+02:00
New upstream version 0.9.8
- - - - -
79186c6d by Jerome Benoit at 2022-04-09T15:01:34+02:00
Update upstream source from tag 'upstream/0.9.8'
Update to upstream version '0.9.8'
with Debian dir e198121219d25235c34f8a9704770a32346832a5
- - - - -
51607d74 by Jerome Benoit at 2022-04-09T15:04:46+02:00
New upstream version 0.9.8+ds
- - - - -
4c9f5552 by Jerome Benoit at 2022-04-09T15:04:49+02:00
Update upstream source from tag 'upstream/0.9.8+ds'
Update to upstream version '0.9.8+ds'
with Debian dir e198121219d25235c34f8a9704770a32346832a5
- - - - -
4ed3b6ad by Jerome Benoit at 2022-04-09T15:46:13+02:00
Debian patch 0.9.8+ds-1
- - - - -
29 changed files:
- CHANGELOG.md
- CMakeLists.txt
- IGRAPH_VERSION
- debian/changelog
- debian/libigraph2.symbols
- interfaces/functions.yaml
- src/CMakeLists.txt
- src/cliques/glet.c
- src/community/walktrap/walktrap_communities.cpp
- src/connectivity/components.c
- − src/core/hashtable.c
- − src/core/hashtable.h
- src/graph/adjlist.c
- src/graph/visitors.c
- src/internal/glpk_support.c
- src/internal/glpk_support.h
- src/isomorphism/bliss/graph.cc
- src/misc/bipartite.c
- src/properties/basic_properties.c
- tests/CMakeLists.txt
- tests/unit/bfs.c
- tests/unit/bfs.out
- tests/unit/community_walktrap.c
- tests/unit/community_walktrap.out
- − tests/unit/hashtable.c
- − tests/unit/hashtable.out
- tests/unit/igraph_diversity.c
- tests/unit/igraph_diversity.out
- tests/unit/igraph_hrg3.c
Changes:
=====================================
CHANGELOG.md
=====================================
@@ -1,5 +1,18 @@
# igraph C library changelog
+## [0.9.8] - 2022-04-08
+
+### Fixed
+
+ - Assertion failure in `igraph_bfs()` when an empty `roots` or `restricted` vector was provided.
+ - `igraph_diversity()` now returns 0 for degree-1 vertices. Previously it incorrectly returned NaN or +-Inf depending on roundoff errors.
+ - `igraph_community_walktrap()` does not crash any more when provided with
+ `modularity=NULL` and `membership=NULL`.
+
+### Other
+
+ - Documentation improvements.
+
## [0.9.7] - 2022-03-16
### Changed
@@ -31,7 +44,7 @@
### Other
- The C attribute handler now verifies attribute types when retrieving attributes.
- - Documentation improvements
+ - Documentation improvements.
## [0.9.6] - 2022-01-05
@@ -552,7 +565,8 @@
- Provide proper support for Windows, using `__declspec(dllexport)` and `__declspec(dllimport)` for `DLL`s and static usage by using `#define IGRAPH_STATIC 1`.
- Provided integer versions of `dqueue` and `stack` data types.
-[Unreleased]: https://github.com/igraph/igraph/compare/0.9.7..HEAD
+[Unreleased]: https://github.com/igraph/igraph/compare/0.9.8..HEAD
+[0.9.8]: https://github.com/igraph/igraph/compare/0.9.7...0.9.8
[0.9.7]: https://github.com/igraph/igraph/compare/0.9.6...0.9.7
[0.9.6]: https://github.com/igraph/igraph/compare/0.9.5...0.9.6
[0.9.5]: https://github.com/igraph/igraph/compare/0.9.4...0.9.5
=====================================
CMakeLists.txt
=====================================
@@ -101,7 +101,7 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND IGRAPH_ENABLE_CODE_COVERAGE)
EXECUTABLE "${CMAKE_COMMAND}" "--build" "${PROJECT_BINARY_DIR}" "--target" "check"
# Generated files are excluded; apparently the CodeCoverage script has some
# problems with them. Yes, the exclusion is correct, it refers to a nonexistent
- # directory that somehow gets into the coverage resolts. /Applications is for
+ # directory that somehow gets into the coverage results. /Applications is for
# macOS -- it excludes files from the macOS SDK.
EXCLUDE "io/*.l" "io/parsers/*" "/Applications/Xcode*" "examples/*" "tests/*"
)
=====================================
IGRAPH_VERSION
=====================================
@@ -1 +1 @@
-0.9.7
\ No newline at end of file
+0.9.8
\ No newline at end of file
=====================================
debian/changelog
=====================================
@@ -1,3 +1,11 @@
+igraph (0.9.8+ds-1) unstable; urgency=medium
+
+ * New upstream nano version.
+ * Debianization:
+ - d/libigraph2.symbols, update.
+
+ -- Jerome Benoit <calculus at rezozer.net> Sat, 09 Apr 2022 13:45:34 +0000
+
igraph (0.9.7+ds-1) unstable; urgency=medium
* New upstream nano version.
=====================================
debian/libigraph2.symbols
=====================================
@@ -474,13 +474,6 @@ libigraph.so.2 libigraph2 #MINVER#
igraph_has_attribute_table at Base 0.9.4
igraph_has_loop at Base 0.9.4
igraph_has_multiple at Base 0.9.4
- igraph_hashtable_addset2 at Base 0.9.4
- igraph_hashtable_addset at Base 0.9.4
- igraph_hashtable_destroy at Base 0.9.4
- igraph_hashtable_get at Base 0.9.4
- igraph_hashtable_getkeys at Base 0.9.4
- igraph_hashtable_init at Base 0.9.4
- igraph_hashtable_reset at Base 0.9.4
igraph_heap_char_delete_top at Base 0.9.4
igraph_heap_char_destroy at Base 0.9.4
igraph_heap_char_empty at Base 0.9.4
=====================================
interfaces/functions.yaml
=====================================
@@ -689,14 +689,15 @@ igraph_is_mutual:
DEPS: es ON graph
igraph_maximum_cardinality_search:
- PARAMS: GRAPH graph, OUT VERTEXSET alpha, OUT VECTORM1_OR_0 alpham1
- DEPS: alpha ON graph, alpham1 ON graph
+ PARAMS: GRAPH graph, OPTIONAL OUT VECTORM1 alpha, OPTIONAL OUT VERTEXSET alpham1
+ DEPS: alpham1 ON graph
igraph_is_chordal:
PARAMS: |-
- GRAPH graph, VECTORM1_OR_0 alpha=NULL, VECTORM1_OR_0 alpham1=NULL,
+ GRAPH graph, VECTORM1 alpha=NULL, OPTIONAL VECTORM1 alpham1=NULL,
OPTIONAL OUT BOOLEAN chordal, OUT VECTORM1_OR_0 fillin,
OUT GRAPH_OR_0 newgraph
+ DEPS: alpham1 ON graph
igraph_avg_nearest_neighbor_degree:
PARAMS: |-
@@ -724,9 +725,12 @@ igraph_centralization_degree:
BOOLEAN normalized=True
igraph_centralization_degree_tmax:
+ # The general consensus is that the 'loops' argument of this function
+ # should not have a default value; see this comment from @torfason:
+ # https://github.com/igraph/rigraph/issues/369#issuecomment-939893681
PARAMS: |-
GRAPH_OR_0 graph=NULL, INTEGER nodes=0, NEIMODE mode=ALL,
- BOOLEAN loops=False, OUT REAL res
+ BOOLEAN loops, OUT REAL res
igraph_centralization_betweenness:
PARAMS: |-
@@ -1654,6 +1658,15 @@ igraph_mincut:
GRAPH graph, OUT REAL value, OUT VECTORM1 partition1,
OUT VECTORM1 partition2, OUT VECTORM1 cut, VECTOR_OR_0 capacity
+igraph_st_mincut:
+ PARAMS: |-
+ GRAPH graph, OUT REAL value, OUT VECTORM1_OR_0 cut,
+ OPTIONAL OUT VERTEXSET partition1, OPTIONAL OUT VERTEXSET partition2,
+ VERTEX source, VERTEX target, EDGECAPACITY capacity=NULL
+ DEPS: |-
+ capacity ON graph, source ON graph, target ON graph,
+ partition1 ON graph, partition2 ON graph, cut ON graph
+
igraph_st_vertex_connectivity:
PARAMS: |-
GRAPH graph, OUT INTEGER res, VERTEX source, VERTEX target,
@@ -1690,10 +1703,10 @@ igraph_cohesion:
igraph_dominator_tree:
PARAMS: |-
- GRAPH graph, VERTEX root, OUT VERTEXSET dom,
+ GRAPH graph, VERTEX root, OUT VECTORM1 dom,
OUT GRAPH_OR_0 domtree, OUT VERTEXSET leftout,
NEIMODE mode=OUT
- DEPS: root ON graph, dom ON graph, leftout ON graph
+ DEPS: root ON graph, leftout ON graph
igraph_all_st_cuts:
PARAMS: |-
=====================================
src/CMakeLists.txt
=====================================
@@ -43,7 +43,6 @@ add_library(
core/estack.c
core/fixed_vectorlist.c
core/grid.c
- core/hashtable.c
core/heap.c
core/indheap.c
core/interruption.c
=====================================
src/cliques/glet.c
=====================================
@@ -82,25 +82,19 @@ static void igraph_i_subclique_next_free(void *ptr) {
int i;
if (data->resultids) {
for (i = 0; i < data->nc; i++) {
- if (data->resultids + i) {
- igraph_vector_int_destroy(data->resultids + i);
- }
+ igraph_vector_int_destroy(&data->resultids[i]);
}
IGRAPH_FREE(data->resultids);
}
if (data->result) {
for (i = 0; i < data->nc; i++) {
- if (data->result + i) {
- igraph_destroy(data->result + i);
- }
+ igraph_destroy(&data->result[i]);
}
IGRAPH_FREE(data->result);
}
if (data->resultweights) {
for (i = 0; i < data->nc; i++) {
- if (data->resultweights + i) {
- igraph_vector_destroy(data->resultweights + i);
- }
+ igraph_vector_destroy(&data->resultweights[i]);
}
IGRAPH_FREE(data->resultweights);
}
=====================================
src/community/walktrap/walktrap_communities.cpp
=====================================
@@ -488,7 +488,10 @@ Communities::Communities(Graph* graph, int random_walks_length,
Q += (communities[i].internal_weight - communities[i].total_weight * communities[i].total_weight / G->total_weight) / G->total_weight;
}
}
- VECTOR(*modularity)[mergeidx] = Q;
+
+ if (modularity) {
+ VECTOR(*modularity)[mergeidx] = Q;
+ }
}
Communities::~Communities() {
=====================================
src/connectivity/components.c
=====================================
@@ -345,7 +345,7 @@ static int igraph_is_connected_weak(const igraph_t *graph, igraph_bool_t *res);
* definition. This behaviour changed in igraph 0.9; earlier versions assumed
* that the null graph is connected. See the following issue on Github for the
* argument that led us to change the definition:
- * https://github.com/igraph/igraph/issues/1538
+ * https://github.com/igraph/igraph/issues/1539
*
* \param graph The graph object to analyze.
* \param res Pointer to a logical variable, the result will be stored
@@ -369,7 +369,7 @@ int igraph_is_connected(const igraph_t *graph, igraph_bool_t *res,
long int no_of_nodes = igraph_vcount(graph);
if (no_of_nodes == 0) {
- /* Changed in igraph 0.9; see https://github.com/igraph/igraph/issues/1538
+ /* Changed in igraph 0.9; see https://github.com/igraph/igraph/issues/1539
* for the reasoning behind the change */
*res = 0;
return IGRAPH_SUCCESS;
=====================================
src/core/hashtable.c deleted
=====================================
@@ -1,129 +0,0 @@
-/* -*- mode: C -*- */
-/*
- IGraph library.
- Copyright (C) 2006-2012 Gabor Csardi <csardi.gabor at gmail.com>
- 334 Harvard street, Cambridge, MA 02139 USA
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301 USA
-
-*/
-
-#include "igraph_types.h"
-#include "igraph_memory.h"
-#include "igraph_error.h"
-
-#include "core/hashtable.h"
-
-#include <string.h>
-
-int igraph_hashtable_init(igraph_hashtable_t *ht) {
- IGRAPH_CHECK(igraph_trie_init(&ht->keys, 1));
- IGRAPH_FINALLY(igraph_trie_destroy, &ht->keys);
- IGRAPH_CHECK(igraph_strvector_init(&ht->elements, 0));
- IGRAPH_FINALLY(igraph_strvector_destroy, &ht->elements);
- IGRAPH_CHECK(igraph_strvector_init(&ht->defaults, 0));
-
- IGRAPH_FINALLY_CLEAN(2);
- return 0;
-}
-
-void igraph_hashtable_destroy(igraph_hashtable_t *ht) {
- igraph_trie_destroy(&ht->keys);
- igraph_strvector_destroy(&ht->elements);
- igraph_strvector_destroy(&ht->defaults);
-}
-
-/* Note: may leave the hash table in an inconsistent state if a new
- element is added, but this is not a big problem, since while the
- defaults, or the defaults plus the elements may contain more elements
- than the keys trie, but the data is always retrieved based on the trie
-*/
-
-int igraph_hashtable_addset(igraph_hashtable_t *ht,
- const char *key, const char *def,
- const char *elem) {
- long int size = igraph_trie_size(&ht->keys);
- long int newid;
- IGRAPH_CHECK(igraph_trie_get(&ht->keys, key, &newid));
-
- if (newid == size) {
- /* this is a new element */
- IGRAPH_CHECK(igraph_strvector_resize(&ht->defaults, newid + 1));
- IGRAPH_CHECK(igraph_strvector_resize(&ht->elements, newid + 1));
- IGRAPH_CHECK(igraph_strvector_set(&ht->defaults, newid, def));
- IGRAPH_CHECK(igraph_strvector_set(&ht->elements, newid, elem));
- } else {
- /* set an already existing element */
- IGRAPH_CHECK(igraph_strvector_set(&ht->elements, newid, elem));
- }
-
- return 0;
-}
-
-/* Previous comment also applies here */
-
-int igraph_hashtable_addset2(igraph_hashtable_t *ht,
- const char *key, const char *def,
- const char *elem, int elemlen) {
- long int size = igraph_trie_size(&ht->keys);
- long int newid;
- char *tmp;
-
- IGRAPH_CHECK(igraph_trie_get(&ht->keys, key, &newid));
-
- tmp = IGRAPH_CALLOC(elemlen + 1, char);
- if (tmp == 0) {
- IGRAPH_ERROR("cannot add element to hash table", IGRAPH_ENOMEM);
- }
- IGRAPH_FINALLY(igraph_free, tmp);
- strncpy(tmp, elem, elemlen);
- tmp[elemlen] = '\0';
-
- if (newid == size) {
- IGRAPH_CHECK(igraph_strvector_resize(&ht->defaults, newid + 1));
- IGRAPH_CHECK(igraph_strvector_resize(&ht->elements, newid + 1));
- IGRAPH_CHECK(igraph_strvector_set(&ht->defaults, newid, def));
- IGRAPH_CHECK(igraph_strvector_set(&ht->elements, newid, tmp));
- } else {
- IGRAPH_CHECK(igraph_strvector_set(&ht->elements, newid, tmp));
- }
-
- IGRAPH_FREE(tmp);
- IGRAPH_FINALLY_CLEAN(1);
-
- return 0;
-}
-
-int igraph_hashtable_get(igraph_hashtable_t *ht,
- const char *key, char **elem) {
- long int newid;
- IGRAPH_CHECK(igraph_trie_get(&ht->keys, key, &newid));
-
- igraph_strvector_get(&ht->elements, newid, elem);
-
- return 0;
-}
-
-int igraph_hashtable_reset(igraph_hashtable_t *ht) {
- igraph_strvector_destroy(&ht->elements);
- IGRAPH_CHECK(igraph_strvector_copy(&ht->elements, &ht->defaults));
- return 0;
-}
-
-int igraph_hashtable_getkeys(igraph_hashtable_t *ht,
- const igraph_strvector_t **sv) {
- return igraph_trie_getkeys(&ht->keys, sv);
-}
=====================================
src/core/hashtable.h deleted
=====================================
@@ -1,58 +0,0 @@
-/* -*- mode: C -*- */
-/*
- IGraph library.
- Copyright (C) 2009-2020 The igraph development team
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301 USA
-
-*/
-
-#ifndef IGRAPH_CORE_HASHTABLE_H
-#define IGRAPH_CORE_HASHTABLE_H
-
-#include "igraph_decls.h"
-#include "igraph_types.h"
-#include "igraph_strvector.h"
-
-#include "core/trie.h"
-
-__BEGIN_DECLS
-
-/* string -> string hash table */
-
-typedef struct igraph_hashtable_t {
- igraph_trie_t keys;
- igraph_strvector_t elements;
- igraph_strvector_t defaults;
-} igraph_hashtable_t;
-
-IGRAPH_PRIVATE_EXPORT int igraph_hashtable_init(igraph_hashtable_t *ht);
-IGRAPH_PRIVATE_EXPORT void igraph_hashtable_destroy(igraph_hashtable_t *ht);
-IGRAPH_PRIVATE_EXPORT int igraph_hashtable_addset(igraph_hashtable_t *ht,
- const char *key, const char *def,
- const char *elem);
-IGRAPH_PRIVATE_EXPORT int igraph_hashtable_addset2(igraph_hashtable_t *ht,
- const char *key, const char *def,
- const char *elem, int elemlen);
-IGRAPH_PRIVATE_EXPORT int igraph_hashtable_get(igraph_hashtable_t *ht,
- const char *key, char **elem);
-IGRAPH_PRIVATE_EXPORT int igraph_hashtable_getkeys(igraph_hashtable_t *ht,
- const igraph_strvector_t **sv);
-IGRAPH_PRIVATE_EXPORT int igraph_hashtable_reset(igraph_hashtable_t *ht);
-
-__END_DECLS
-
-#endif
=====================================
src/graph/adjlist.c
=====================================
@@ -297,9 +297,7 @@ int igraph_adjlist_init_complementer(const igraph_t *graph,
void igraph_adjlist_destroy(igraph_adjlist_t *al) {
long int i;
for (i = 0; i < al->length; i++) {
- if (&al->adjs[i]) {
- igraph_vector_int_destroy(&al->adjs[i]);
- }
+ igraph_vector_int_destroy(&al->adjs[i]);
}
IGRAPH_FREE(al->adjs);
}
=====================================
src/graph/visitors.c
=====================================
@@ -122,7 +122,7 @@ int igraph_bfs(const igraph_t *graph,
IGRAPH_ERROR("Invalid root vertex in BFS", IGRAPH_EINVAL);
}
- if (roots) {
+ if (roots && noroots > 0) {
igraph_real_t min, max;
igraph_vector_minmax(roots, &min, &max);
if (min < 0 || max >= no_of_nodes) {
@@ -130,7 +130,7 @@ int igraph_bfs(const igraph_t *graph,
}
}
- if (restricted) {
+ if (restricted && igraph_vector_size(restricted) > 0) {
igraph_real_t min, max;
igraph_vector_minmax(restricted, &min, &max);
if (min < 0 || max >= no_of_nodes) {
=====================================
src/internal/glpk_support.c
=====================================
@@ -34,6 +34,16 @@
IGRAPH_THREAD_LOCAL igraph_i_glpk_error_info_t igraph_i_glpk_error_info;
+/* glp_at_error() was added in GLPK 4.57. Due to the R interface, we need to
+ * support ancient GLPK versions like GLPK 4.38 so we need to guard the
+ * invocation of glp_at_error(). Note that this is a temporary workaround only
+ * for sake of supporting R 4.1, so it is enabled only if USING_R is defined */
+#ifdef USING_R
+# define HAS_GLP_AT_ERROR (GLP_MAJOR_VERSION > 4 || (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION >= 57))
+#else
+# define HAS_GLP_AT_ERROR 1
+#endif
+
int igraph_i_glpk_terminal_hook(void *info, const char *s) {
IGRAPH_UNUSED(info);
@@ -45,6 +55,7 @@ int igraph_i_glpk_terminal_hook(void *info, const char *s) {
and the error_hook. */
igraph_i_glpk_error_info.is_interrupted = 1;
glp_error("GLPK was interrupted."); /* This dummy message is never printed */
+#if HAS_GLP_AT_ERROR
} else if (glp_at_error()) {
/* Copy the error messages into a buffer for later reporting */
/* We must use glp_at_error() instead of igraph_i_glpk_error_info.is_error
@@ -55,6 +66,7 @@ int igraph_i_glpk_terminal_hook(void *info, const char *s) {
*(igraph_i_glpk_error_info.msg_ptr++) = *(s++);
}
*igraph_i_glpk_error_info.msg_ptr = '\0';
+#endif
}
return 1; /* Non-zero return value signals to GLPK not to print to the terminal */
=====================================
src/internal/glpk_support.h
=====================================
@@ -126,6 +126,10 @@ void igraph_i_glp_delete_prob(glp_prob *p);
} \
*igraph_i_glpk_error_info.msg_ptr = '\0'; \
igraph_error(igraph_i_glpk_error_info.msg, IGRAPH_FILE_BASENAME, __LINE__, IGRAPH_EGLP); \
+ } else if (igraph_i_glpk_error_info.is_error) { \
+ /* This branch can never be reached unless compiled with USING_R and using */ \
+ /* the hack to support pre-4.57 GLPK versions. See comments in glpk_support.c. */ \
+ igraph_error("Error while running GLPK solver.", IGRAPH_FILE_BASENAME, __LINE__, IGRAPH_EGLP); \
} \
return IGRAPH_EGLP; \
} \
=====================================
src/isomorphism/bliss/graph.cc
=====================================
@@ -604,7 +604,7 @@ public:
unsigned int cr_cep_index;
unsigned int cr_level;
- bool needs_long_prune;
+ bool needs_long_prune = false; /* igraph-specific patch: initialize to false to silence UBSan */
unsigned int long_prune_begin;
std::set<unsigned int, std::less<unsigned int> > long_prune_redundant;
@@ -1499,9 +1499,6 @@ AbstractGraph::search(const bool canonical,
child_node.cr_cep_stack_size = cr_cep_stack.size();
child_node.cr_cep_index = cr_cep_index;
- /* Initialize needs_long_prune to prevent a gcc-ubsan warning */
- child_node.needs_long_prune = true;
-
search_stack.push_back(child_node);
continue;
}
=====================================
src/misc/bipartite.c
=====================================
@@ -524,7 +524,7 @@ int igraph_create_bipartite(igraph_t *graph, const igraph_vector_bool_t *types,
igraph_vector_minmax(edges, &min_edge, &max_edge);
}
if (min_edge < 0 || max_edge >= no_of_nodes) {
- IGRAPH_ERROR("Invalid (negative) vertex id", IGRAPH_EINVVID);
+ IGRAPH_ERROR("Invalid (negative or too large) vertex id", IGRAPH_EINVVID);
}
/* Check bipartiteness */
=====================================
src/properties/basic_properties.c
=====================================
@@ -107,7 +107,8 @@ int igraph_density(const igraph_t *graph, igraph_real_t *res,
* where p[i,j]=w[i,j]/sum(w[i,l], l=1..k[i]), k[i] is the (total)
* degree of vertex i, and w[i,j] is the weight of the edge(s) between
* vertex i and j. The diversity of isolated vertices will be NaN
- * (not-a-number).
+ * (not-a-number), while that of vertices with a single connection
+ * will be zero.
*
* </para><para>
* The measure works only if the graph is undirected and has no multiple edges.
@@ -117,7 +118,7 @@ int igraph_density(const igraph_t *graph, igraph_real_t *res,
*
* \param graph The undirected input graph.
* \param weights The edge weights, in the order of the edge ids, must
- * have appropriate length.
+ * have appropriate length. Weights must be non-negative.
* \param res An initialized vector, the results are stored here.
* \param vids Vertex selector that specifies the vertices which to calculate
* the measure.
@@ -129,13 +130,11 @@ int igraph_density(const igraph_t *graph, igraph_real_t *res,
int igraph_diversity(const igraph_t *graph, const igraph_vector_t *weights,
igraph_vector_t *res, const igraph_vs_t vids) {
- int no_of_nodes = igraph_vcount(graph);
- int no_of_edges = igraph_ecount(graph);
+ long int no_of_edges = igraph_ecount(graph);
+ long int k, i;
igraph_vector_t incident;
- igraph_vit_t vit;
- igraph_real_t s, ent, w;
- int i, j, k;
igraph_bool_t has_multiple;
+ igraph_vit_t vit;
if (igraph_is_directed(graph)) {
IGRAPH_ERROR("Diversity measure works with undirected graphs only.", IGRAPH_EINVAL);
@@ -154,48 +153,65 @@ int igraph_diversity(const igraph_t *graph, const igraph_vector_t *weights,
IGRAPH_ERROR("Diversity measure works only if the graph has no multiple edges.", IGRAPH_EINVAL);
}
+ if (no_of_edges > 0) {
+ igraph_real_t minweight = igraph_vector_min(weights);
+ if (minweight < 0) {
+ IGRAPH_ERROR("Weight vector must be non-negative.", IGRAPH_EINVAL);
+ } else if (igraph_is_nan(minweight)) {
+ IGRAPH_ERROR("Weight vector must not contain NaN values.", IGRAPH_EINVAL);
+ }
+ }
+
IGRAPH_VECTOR_INIT_FINALLY(&incident, 10);
- if (igraph_vs_is_all(&vids)) {
- IGRAPH_CHECK(igraph_vector_resize(res, no_of_nodes));
- for (i = 0; i < no_of_nodes; i++) {
- s = ent = 0.0;
- IGRAPH_CHECK(igraph_incident(graph, &incident, i, /*mode=*/ IGRAPH_ALL));
- for (j = 0, k = (int) igraph_vector_size(&incident); j < k; j++) {
- w = VECTOR(*weights)[(long int)VECTOR(incident)[j]];
- s += w;
- ent += (w * log(w));
- }
- VECTOR(*res)[i] = (log(s) - ent / s) / log(k);
- }
- } else {
- IGRAPH_CHECK(igraph_vector_resize(res, 0));
- IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
- IGRAPH_FINALLY(igraph_vit_destroy, &vit);
-
- for (IGRAPH_VIT_RESET(vit), i = 0;
- !IGRAPH_VIT_END(vit);
- IGRAPH_VIT_NEXT(vit), i++) {
- long int v = IGRAPH_VIT_GET(vit);
- s = ent = 0.0;
- IGRAPH_CHECK(igraph_incident(graph, &incident, (igraph_integer_t) v,
- /*mode=*/ IGRAPH_ALL));
- for (j = 0, k = (int) igraph_vector_size(&incident); j < k; j++) {
- w = VECTOR(*weights)[(long int)VECTOR(incident)[j]];
+ IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
+ IGRAPH_FINALLY(igraph_vit_destroy, &vit);
+
+ igraph_vector_clear(res);
+ IGRAPH_CHECK(igraph_vector_reserve(res, IGRAPH_VIT_SIZE(vit)));
+
+ for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) {
+ igraph_real_t d;
+ long int v = IGRAPH_VIT_GET(vit);
+
+ IGRAPH_CHECK(igraph_incident(graph, &incident, v, /*mode=*/ IGRAPH_ALL));
+ k = igraph_vector_size(&incident); /* degree */
+
+ /*
+ * Non-normalized diversity is defined as
+ * d = -sum_i w_i/s log (w_i/s)
+ * where s = sum_i w_i. In order to avoid two passes through the w vector,
+ * we use the equivalent formulation of
+ * d = log s - (sum_i w_i log w_i) / s
+ * However, this formulation may not give an exact 0.0 for some w when k=1,
+ * due to roundoff errors (examples: w=3 or w=7). For this reason, we
+ * special-case the computation for k=1 even for the unnormalized diversity
+ * insted of just setting the normalization factor to 1 for this case.
+ */
+ if (k == 0) {
+ d = IGRAPH_NAN;
+ } else if (k == 1) {
+ if (VECTOR(*weights)[0] > 0) d = 0.0; /* s > 0 */
+ else d = IGRAPH_NAN; /* s == 0 */
+ } else {
+ igraph_real_t s = 0.0, ent = 0.0;
+ for (i = 0; i < k; i++) {
+ igraph_real_t w = VECTOR(*weights)[(long int)VECTOR(incident)[i]];
+ if (w == 0) continue;
s += w;
ent += (w * log(w));
}
- IGRAPH_CHECK(igraph_vector_push_back(res, (log(s) - ent / s) / log(k)));
+ d = (log(s) - ent / s) / log(k);
}
- igraph_vit_destroy(&vit);
- IGRAPH_FINALLY_CLEAN(1);
+ igraph_vector_push_back(res, d); /* reserved */
}
+ igraph_vit_destroy(&vit);
igraph_vector_destroy(&incident);
- IGRAPH_FINALLY_CLEAN(1);
+ IGRAPH_FINALLY_CLEAN(2);
- return 0;
+ return IGRAPH_SUCCESS;
}
/**
=====================================
tests/CMakeLists.txt
=====================================
@@ -113,7 +113,6 @@ add_legacy_tests(
2wheap
cutheap
d_indheap
- hashtable
marked_queue
set
trie
=====================================
tests/unit/bfs.c
=====================================
@@ -127,6 +127,15 @@ int main() {
0, 0, 0, 0, 0, 0, &bfs_callback, 0);
printf(" )\n");
+ /* Empty root vertex vector */
+
+ igraph_vector_clear(&roots);
+ printf("(");
+ igraph_bfs(&graph, /*root=*/ -1, &roots, /*neimode=*/ IGRAPH_OUT,
+ /*unreachable=*/ 0, &restricted,
+ 0, 0, 0, 0, 0, 0, &bfs_callback, 0);
+ printf(" )\n");
+
igraph_vector_destroy(&roots);
igraph_vector_destroy(&restricted);
igraph_destroy(&graph);
=====================================
tests/unit/bfs.out
=====================================
@@ -10,3 +10,4 @@
( 5 6 7 8 9 10 11 19 12 18 13 17 14 16 15 )
( )
( 6 5 7 8 9 )
+( )
=====================================
tests/unit/community_walktrap.c
=====================================
@@ -56,6 +56,17 @@ int main() {
igraph_vector_destroy(&membership);
igraph_vector_destroy(&modularity);
igraph_matrix_destroy(&merges);
+
+ /* Test the case when modularity=0 and membership=0 as this caused a crash in
+ * the R interface, see https://github.com/igraph/rigraph/issues/289 */
+
+ igraph_matrix_init(&merges, 0, 0);
+
+ igraph_community_walktrap(&graph, NULL, 4, &merges, NULL, NULL);
+ printf("Merges:\n");
+ igraph_matrix_print(&merges);
+ igraph_matrix_destroy(&merges);
+
igraph_destroy(&graph);
VERIFY_FINALLY_STACK();
=====================================
tests/unit/community_walktrap.out
=====================================
@@ -3,3 +3,6 @@ Merges:
0 3
Modularity: -0.333333 -0.222222 0
Membership: 0 0 0
+Merges:
+1 2
+0 3
=====================================
tests/unit/hashtable.c deleted
=====================================
@@ -1,133 +0,0 @@
-/* -*- mode: C -*- */
-/*
- IGraph library.
- Copyright (C) 2006-2012 Gabor Csardi <csardi.gabor at gmail.com>
- 334 Harvard st, Cambridge MA, 02139 USA
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301 USA
-
-*/
-
-#include <igraph.h>
-#include "core/hashtable.h"
-
-#include "test_utilities.inc"
-
-int main() {
-
- igraph_hashtable_t ht;
- char *str;
- const igraph_strvector_t *keys;
- long int i;
-
- /* init and destroy */
- igraph_hashtable_init(&ht);
- igraph_hashtable_destroy(&ht);
-
- /* init, add some elements and destroy */
- igraph_hashtable_init(&ht);
- igraph_hashtable_addset(&ht, "color", "green", "red");
- igraph_hashtable_addset(&ht, "size", "", "4");
- igraph_hashtable_addset(&ht, "color", "", "grey");
- igraph_hashtable_addset(&ht, "shape", "", "circle");
- igraph_hashtable_addset(&ht, "shape", "", "diamond");
- igraph_hashtable_destroy(&ht);
-
- /* reset */
- igraph_hashtable_init(&ht);
- igraph_hashtable_addset(&ht, "color", "green", "red");
- igraph_hashtable_addset(&ht, "size", "", "4");
- igraph_hashtable_addset(&ht, "color", "", "grey");
- igraph_hashtable_addset(&ht, "shape", "", "circle");
- igraph_hashtable_addset(&ht, "shape", "", "diamond");
- igraph_hashtable_reset(&ht);
- igraph_hashtable_addset(&ht, "color", "green", "red");
- igraph_hashtable_addset(&ht, "size", "", "4");
- igraph_hashtable_addset(&ht, "color", "", "grey");
- igraph_hashtable_addset(&ht, "shape", "", "circle");
- igraph_hashtable_addset(&ht, "shape", "", "diamond");
- igraph_hashtable_destroy(&ht);
-
- /* Check semantics */
- igraph_hashtable_init(&ht);
- igraph_hashtable_addset(&ht, "color", "green", "red");
- igraph_hashtable_addset(&ht, "size", "", "4");
- igraph_hashtable_addset(&ht, "color", "", "grey");
- igraph_hashtable_addset(&ht, "shape", "", "circle");
- igraph_hashtable_addset(&ht, "shape", "", "diamond");
-
- igraph_hashtable_get(&ht, "color", &str);
- printf("color: %s\n", str);
- igraph_hashtable_get(&ht, "size", &str);
- printf("size: %s\n", str);
- igraph_hashtable_get(&ht, "shape", &str);
- printf("shape: %s\n", str);
-
- igraph_hashtable_reset(&ht);
-
- igraph_hashtable_get(&ht, "color", &str);
- printf("color: %s\n", str);
- igraph_hashtable_get(&ht, "size", &str);
- printf("size: %s\n", str);
- igraph_hashtable_get(&ht, "shape", &str);
- printf("shape: %s\n", str);
-
- igraph_hashtable_getkeys(&ht, &keys);
- for (i = 0; i < igraph_strvector_size(keys); i++) {
- igraph_strvector_get(keys, i, &str);
- printf("%s ", str);
- }
- printf("\n");
-
- igraph_hashtable_destroy(&ht);
-
- /* addset2 */
- igraph_hashtable_init(&ht);
- igraph_hashtable_addset2(&ht, "color", "green", "redddd", 3);
- igraph_hashtable_addset2(&ht, "size", "", "4111", 1);
- igraph_hashtable_addset2(&ht, "color", "", "greysdsdf", 4);
- igraph_hashtable_addset2(&ht, "shape", "", "circle", 6);
- igraph_hashtable_addset(&ht, "shape", "", "diamond");
-
- igraph_hashtable_get(&ht, "color", &str);
- printf("color: %s\n", str);
- igraph_hashtable_get(&ht, "size", &str);
- printf("size: %s\n", str);
- igraph_hashtable_get(&ht, "shape", &str);
- printf("shape: %s\n", str);
-
- igraph_hashtable_reset(&ht);
-
- igraph_hashtable_get(&ht, "color", &str);
- printf("color: %s\n", str);
- igraph_hashtable_get(&ht, "size", &str);
- printf("size: %s\n", str);
- igraph_hashtable_get(&ht, "shape", &str);
- printf("shape: %s\n", str);
-
- igraph_hashtable_getkeys(&ht, &keys);
- for (i = 0; i < igraph_strvector_size(keys); i++) {
- igraph_strvector_get(keys, i, &str);
- printf("%s ", str);
- }
- printf("\n");
-
- igraph_hashtable_destroy(&ht);
-
- VERIFY_FINALLY_STACK();
-
- return 0;
-}
=====================================
tests/unit/hashtable.out deleted
=====================================
@@ -1,14 +0,0 @@
-color: grey
-size: 4
-shape: diamond
-color: green
-size:
-shape:
-color size shape
-color: grey
-size: 4
-shape: diamond
-color: green
-size:
-shape:
-color size shape
=====================================
tests/unit/igraph_diversity.c
=====================================
@@ -44,21 +44,38 @@ int main() {
igraph_vector_destroy(&weights);
igraph_destroy(&g);
+ /* degree-one vertices */
+ igraph_tree(&g, 10, 2, IGRAPH_TREE_UNDIRECTED);
+ igraph_vector_init_seq(&weights, 1, igraph_ecount(&g));
+
+ printf("Tree (having degree-one vertices):\n");
+ igraph_diversity(&g, &weights, &result, igraph_vss_all());
+ print_vector(&result);
+
+ igraph_vector_destroy(&weights);
+ igraph_destroy(&g);
+
/* error conditions are tested from now on */
VERIFY_FINALLY_STACK();
- igraph_set_error_handler(igraph_error_handler_ignore);
/* graph with multiple edges */
igraph_small(&g, 3, IGRAPH_UNDIRECTED, 0,1, 0,2, 2,0, -1);
igraph_vector_init_int_end(&weights, -1, 3, 2, 8, -1);
- IGRAPH_ASSERT(igraph_diversity(&g, &weights, &result, igraph_vss_all()) == IGRAPH_EINVAL);
+ CHECK_ERROR(igraph_diversity(&g, &weights, &result, igraph_vss_all()), IGRAPH_EINVAL);
+ igraph_vector_destroy(&weights);
+ igraph_destroy(&g);
+
+ /* negative weights */
+ igraph_small(&g, 3, IGRAPH_UNDIRECTED, 0,1, 0,2, 2,1, -1);
+ igraph_vector_init_int_end(&weights, -1, 3, -2, 8, -1);
+ CHECK_ERROR(igraph_diversity(&g, &weights, &result, igraph_vss_all()), IGRAPH_EINVAL);
igraph_vector_destroy(&weights);
igraph_destroy(&g);
/* directed graph */
igraph_small(&g, 3, IGRAPH_DIRECTED, 0,1, 0,2, -1);
igraph_vector_init_int_end(&weights, -1, 3, 2, -1);
- IGRAPH_ASSERT(igraph_diversity(&g, &weights, &result, igraph_vss_all()) == IGRAPH_EINVAL);
+ CHECK_ERROR(igraph_diversity(&g, &weights, &result, igraph_vss_all()), IGRAPH_EINVAL);
igraph_vector_destroy(&weights);
igraph_destroy(&g);
=====================================
tests/unit/igraph_diversity.out
=====================================
@@ -4,3 +4,5 @@ Empty graph:
( NaN NaN NaN NaN NaN )
Graph with 4 nodes and 5 edges:
( 0.970951 0.75 0.69137 1 )
+Tree (having degree-one vertices):
+( 0.918296 0.88686 0.921463 0.934206 0.890492 0 0 0 0 0 )
=====================================
tests/unit/igraph_hrg3.c
=====================================
@@ -68,7 +68,7 @@ int main() {
igraph_hrg_predict(&karate, &edges, &prob, /* hrg= */ 0, /* start= */ 0,
/* num_samples= */ 100, /* num_bins= */ 25);
- /* We do some simple validity tests on the resolts only; the exact results
+ /* We do some simple validity tests on the results only; the exact results
* are different on i386 vs other platforms due to numerical inaccuracies */
n = igraph_vector_size(&edges);
for (i = 0; i < n; i++) {
View it on GitLab: https://salsa.debian.org/med-team/igraph/-/compare/959789a3c1833961531675c4c2e3049611865ab9...4ed3b6ad6be1aff62354bf46b8aa7e356deec090
--
View it on GitLab: https://salsa.debian.org/med-team/igraph/-/compare/959789a3c1833961531675c4c2e3049611865ab9...4ed3b6ad6be1aff62354bf46b8aa7e356deec090
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20220409/7fe09d77/attachment-0001.htm>
More information about the debian-med-commit
mailing list