Skip to content

Commit

Permalink
chore: Update vendored sources to igraph/igraph@bd9306d
Browse files Browse the repository at this point in the history
chore: improve changelog
fix: eigenvector centralization now always assumes scaled vertex-level centrality scores
doc: more cross-linking for harmonic centrality
doc: add reference to betweenness docs
ci: apt-get update to work around outdated index
ci: test with clang 20
doc: doc cleanup in centralization functions
refactor: minor cleanup / IDE-friendliness for community_to_membership()
ci: re-enable travis on ppc64 / s390x
  • Loading branch information
szhorvat authored and krlmlr committed Sep 18, 2024
1 parent 52a0bfc commit f4b1736
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 73 deletions.
20 changes: 10 additions & 10 deletions src/vendor/cigraph/.travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,17 +76,17 @@ jobs:
- mkdir build && cd build
- cmake .. -DIGRAPH_USE_INTERNAL_BLAS=OFF -DIGRAPH_USE_INTERNAL_LAPACK=OFF -DIGRAPH_USE_INTERNAL_ARPACK=OFF -DIGRAPH_USE_INTERNAL_GLPK=OFF -DIGRAPH_USE_INTERNAL_GMP=OFF -DIGRAPH_VERIFY_FINALLY_STACK=OFF -DCMAKE_BUILD_TYPE=Debug -DIGRAPH_PRINT_ARITH_HEADER=ON -DUSE_SANITIZER=Address

# - name: "Linux ppc64"
# os: linux
# arch: ppc64le
- name: "Linux ppc64"
os: linux
arch: ppc64le

# - name: "Linux s390x"
# os: linux
# arch: s390x
# # Do not enable ASan, as it leads to linking errors.
# before_script:
# - mkdir build && cd build
# - cmake .. -DIGRAPH_USE_INTERNAL_BLAS=ON -DIGRAPH_USE_INTERNAL_LAPACK=ON -DIGRAPH_USE_INTERNAL_ARPACK=ON -DIGRAPH_USE_INTERNAL_GLPK=ON -DIGRAPH_USE_INTERNAL_GMP=ON -DIGRAPH_VERIFY_FINALLY_STACK=ON -DCMAKE_BUILD_TYPE=Debug -DIGRAPH_PRINT_ARITH_HEADER=ON
- name: "Linux s390x"
os: linux
arch: s390x
# Do not enable ASan, as it leads to linking errors.
before_script:
- mkdir build && cd build
- cmake .. -DIGRAPH_USE_INTERNAL_BLAS=ON -DIGRAPH_USE_INTERNAL_LAPACK=ON -DIGRAPH_USE_INTERNAL_ARPACK=ON -DIGRAPH_USE_INTERNAL_GLPK=ON -DIGRAPH_USE_INTERNAL_GMP=ON -DIGRAPH_VERIFY_FINALLY_STACK=ON -DCMAKE_BUILD_TYPE=Debug -DIGRAPH_PRINT_ARITH_HEADER=ON

#notifications:
# email:
Expand Down
1 change: 1 addition & 0 deletions src/vendor/cigraph/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

- `igraph_feedback_arc_set()` uses a much faster method for solving the exact minimum feedback arc set problem. The new method (`IGRAPH_FAS_EXACT_IP_CG`) is used by default (i.e. with `IGRAPH_FAS_EXACT_IP`), but the previous method is also kept available (`IGRAPH_FAS_EXACT_IP_TI`).
- `igraph_motifs_randesu()`, `igraph_motifs_randesu_callback()`, `igraph_motifs_randesu_estimate()` and `igraph_motifs_randesu_no()` now accept `NULL` for their `cut_prob` parameter, signifying that a complete search should be performed.
- `igraph_centralization_eigenvector_centrality_tmax()` and `igraph_centralization_eigenvector_centrality()` cannot produce meaningful results without normalizing vertex-level eigenvector centrality in a well-defined way. This was not the case when using `scale=false`. These functions now ignore the value of the `scale` parameter and always scale vertex-level centrality scores to have a maximum of 1. If you require a different type of normalization for the vertex-level eigenvector centrality scores, perform this normalization manually, and call `igraph_centralization()` to compute the centralization.

### Fixed

Expand Down
10 changes: 6 additions & 4 deletions src/vendor/cigraph/azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ jobs:
# In this test we install and generate locales so that igraph_enter/exit_safelocale() can be tested
- job: linux_static_vendored
steps:
- script: sudo apt-get install ninja-build ccache language-pack-de -y
- script: |
sudo apt-get update
sudo apt-get install ninja-build ccache language-pack-de -y
displayName: Install dependencies
- script: |
Expand Down Expand Up @@ -75,19 +77,19 @@ jobs:
extra_cmake_args: '-DBLA_VENDOR=OpenBLAS'
build_shared: true

- job: linux_clang_19
- job: linux_clang_20
steps:
- script: |
sudo apt-get install ninja-build ccache -y
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 19
sudo ./llvm.sh 20
displayName: Install dependencies
- template: .azure/build.yml
parameters:
build_type: Debug
extra_cmake_args: '-DUSE_SANITIZER=Address\;Undefined -DCMAKE_C_FLAGS="-Og -fno-sanitize-recover=undefined -fno-sanitize=float-divide-by-zero" -DCMAKE_CXX_FLAGS="-Og -fno-sanitize-recover=undefined -fno-sanitize=float-divide-by-zero" -DCMAKE_C_COMPILER=clang-19 -DCMAKE_CXX_COMPILER=clang++-19'
extra_cmake_args: '-DUSE_SANITIZER=Address\;Undefined -DCMAKE_C_FLAGS="-Og -fno-sanitize-recover=undefined -fno-sanitize=float-divide-by-zero" -DCMAKE_CXX_FLAGS="-Og -fno-sanitize-recover=undefined -fno-sanitize=float-divide-by-zero" -DCMAKE_C_COMPILER=clang-20 -DCMAKE_CXX_COMPILER=clang++-20'

- job: linux_x87
steps:
Expand Down
16 changes: 16 additions & 0 deletions src/vendor/cigraph/src/centrality/betweenness.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,14 @@ static igraph_error_t igraph_i_betweenness_check_weights(
* vertices, the value of these geodesics are weighted by one over the
* number of geodesics.
*
* </para><para>
* Reference:
*
* </para><para>
* Ulrik Brandes: A faster algorithm for betweenness centrality.
* The Journal of Mathematical Sociology, 25(2), 163–177 (2001).
* https://doi.org/10.1080/0022250X.2001.9990249
*
* \param graph The graph object.
* \param res The result of the computation, a vector containing the
* betweenness scores for the specified vertices.
Expand Down Expand Up @@ -695,6 +703,14 @@ igraph_error_t igraph_betweenness_cutoff(const igraph_t *graph, igraph_vector_t
* vertices, the value of these geodesics are weighted by one over the
* number of geodesics.
*
* </para><para>
* Reference:
*
* </para><para>
* Ulrik Brandes: A faster algorithm for betweenness centrality.
* The Journal of Mathematical Sociology, 25(2), 163–177 (2001).
* https://doi.org/10.1080/0022250X.2001.9990249
*
* \param graph The graph object.
* \param result The result of the computation, vector containing the
* betweenness scores for the edges.
Expand Down
115 changes: 80 additions & 35 deletions src/vendor/cigraph/src/centrality/centralization.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,15 +168,15 @@ igraph_error_t igraph_centralization_degree(const igraph_t *graph, igraph_vector
*
* </para><para>
* There are two ways to call this function, the first is to supply a
* graph as the <code>graph</code> argument, and then the number of
* graph as the \p graph argument, and then the number of
* vertices is taken from this object, and its directedness is
* considered as well. The <code>nodes</code> argument is ignored in
* this case. The <code>mode</code> argument is also ignored if the
* considered as well. The \p nodes argument is ignored in
* this case. The \p mode argument is also ignored if the
* supplied graph is undirected.
*
* </para><para>
* The other way is to supply a null pointer as the <code>graph</code>
* argument. In this case the <code>nodes</code> and <code>mode</code>
* The other way is to supply a null pointer as the \p graph
* argument. In this case the \p nodes and \p mode
* arguments are considered.
*
* </para><para>
Expand All @@ -187,11 +187,11 @@ igraph_error_t igraph_centralization_degree(const igraph_t *graph, igraph_vector
* \param graph A graph object or a null pointer, see the description
* above.
* \param nodes The number of nodes. This is ignored if the
* <code>graph</code> argument is not a null pointer.
* \p graph argument is not a null pointer.
* \param mode Constant, whether the calculation is based on in-degree
* (<code>IGRAPH_IN</code>), out-degree (<code>IGRAPH_OUT</code>)
* or total degree (<code>IGRAPH_ALL</code>). This is ignored if
* the <code>graph</code> argument is not a null pointer and the
* (\c IGRAPH_IN), out-degree (\c IGRAPH_OUT)
* or total degree (\c IGRAPH_ALL). This is ignored if
* the \p graph argument is not a null pointer and the
* given graph is undirected.
* \param loops Boolean scalar, whether to consider loop edges in the
* calculation.
Expand Down Expand Up @@ -324,15 +324,15 @@ igraph_error_t igraph_centralization_betweenness(const igraph_t *graph,
*
* </para><para>
* There are two ways to call this function, the first is to supply a
* graph as the <code>graph</code> argument, and then the number of
* graph as the \p graph argument, and then the number of
* vertices is taken from this object, and its directedness is
* considered as well. The <code>nodes</code> argument is ignored in
* this case. The <code>directed</code> argument is also ignored if the
* considered as well. The \p nodes argument is ignored in
* this case. The \p directed argument is also ignored if the
* supplied graph is undirected.
*
* </para><para>
* The other way is to supply a null pointer as the <code>graph</code>
* argument. In this case the <code>nodes</code> and <code>directed</code>
* The other way is to supply a null pointer as the \p graph
* argument. In this case the \p nodes and \p directed
* arguments are considered.
*
* </para><para>
Expand All @@ -341,10 +341,10 @@ igraph_error_t igraph_centralization_betweenness(const igraph_t *graph,
* \param graph A graph object or a null pointer, see the description
* above.
* \param nodes The number of nodes. This is ignored if the
* <code>graph</code> argument is not a null pointer.
* \p graph argument is not a null pointer.
* \param directed Boolean scalar, whether to use directed paths in
* the betweenness calculation. This argument is ignored if
* <code>graph</code> is not a null pointer and it is undirected.
* \p graph is not a null pointer and it is undirected.
* \param res Pointer to a real variable, the result is stored here.
* \return Error code.
*
Expand Down Expand Up @@ -455,27 +455,28 @@ igraph_error_t igraph_centralization_closeness(const igraph_t *graph,
*
* </para><para>
* There are two ways to call this function, the first is to supply a
* graph as the <code>graph</code> argument, and then the number of
* graph as the \p graph argument, and then the number of
* vertices is taken from this object, and its directedness is
* considered as well. The <code>nodes</code> argument is ignored in
* this case. The <code>mode</code> argument is also ignored if the
* considered as well. The \p nodes argument is ignored in
* this case. The \p mode argument is also ignored if the
* supplied graph is undirected.
*
* </para><para>
* The other way is to supply a null pointer as the <code>graph</code>
* argument. In this case the <code>nodes</code> and <code>mode</code>
* The other way is to supply a null pointer as the \p graph
* argument. In this case the \p nodes and \p mode
* arguments are considered.
*
* </para><para>
* The most centralized structure is the star.
*
* \param graph A graph object or a null pointer, see the description
* above.
* \param nodes The number of nodes. This is ignored if the
* <code>graph</code> argument is not a null pointer.
* \param mode Constant, specifies what kinf of distances to consider
* to calculate closeness. See the <code>mode</code> argument of
* \p graph argument is not a null pointer.
* \param mode Constant, specifies what kind of distances to consider
* to calculate closeness. See the \p mode argument of
* \ref igraph_closeness() for details. This argument is ignored
* if <code>graph</code> is not a null pointer and it is
* if \p graph is not a null pointer and it is
* undirected.
* \param res Pointer to a real variable, the result is stored here.
* \return Error code.
Expand Down Expand Up @@ -518,13 +519,26 @@ igraph_error_t igraph_centralization_closeness_tmax(const igraph_t *graph,
* by passing its arguments to \ref igraph_eigenvector_centrality);
* and it calculates the graph level centralization index based on the
* results by calling \ref igraph_centralization().
*
* </para><para>
* Note that vertex-level eigenvector centrality scores do not have
* a natural scale. As with any eigenvector, their interpretation is
* invariant to scaling by a constant factor. However, due to how
* graph-level \em centralization is defined, its value depends on the
* specific scale/normalization used for vertex-level scores. This is
* true even when the graph-level centralization itself is normalized
* by its theoretical maximum value. This function makes the specific
* choice of scaling vertex-level centrality scores by their maximum
* (i.e. it uses the ∞-norm). Other normalization choices, such as the
* 1-norm or 2-norm are not currently implemented.
*
* \param graph The input graph.
* \param vector A vector if you need the node-level eigenvector
* centrality scores, or a null pointer otherwise.
* \param value If not a null pointer, then the leading eigenvalue is
* stored here.
* \param scale If not zero then the result will be scaled, such that
* the absolute value of the maximum centrality is one.
* \param scale This parameter is deprecated and ignored since igraph 0.10.14.
* Vertex-level centrality scores are always scaled to have a maximum of one.
* \param options Options to ARPACK. See \ref igraph_arpack_options_t
* for details. Note that the function overwrites the
* <code>n</code> (number of vertices) parameter and
Expand Down Expand Up @@ -564,6 +578,14 @@ igraph_error_t igraph_centralization_eigenvector_centrality(
igraph_real_t realvalue, *myvalue = value;
igraph_real_t *tmax = theoretical_max, mytmax;

if (! scale) {
scale = true;
IGRAPH_WARNING("Computing eigenvector centralization requires normalized "
"eigenvector centrality scores. Normalizing eigenvector centralities "
"by their maximum even though 'scale=false' was requested. The 'scale' "
"parameter will be removed in the future.");
}

if (!tmax) {
tmax = &mytmax;
}
Expand Down Expand Up @@ -604,28 +626,42 @@ igraph_error_t igraph_centralization_eigenvector_centrality(
*
* </para><para>
* There are two ways to call this function, the first is to supply a
* graph as the <code>graph</code> argument, and then the number of
* graph as the \p graph argument, and then the number of
* vertices is taken from this object, and its directedness is
* considered as well. The <code>nodes</code> argument is ignored in
* this case. The <code>directed</code> argument is also ignored if the
* considered as well. The \p nodes argument is ignored in
* this case. The \p directed argument is also ignored if the
* supplied graph is undirected.
*
* </para><para>
* The other way is to supply a null pointer as the <code>graph</code>
* argument. In this case the <code>nodes</code> and <code>directed</code>
* The other way is to supply a null pointer as the \p graph
* argument. In this case the \p nodes and \p directed
* arguments are considered.
*
* </para><para>
* The most centralized directed structure is the in-star. The most
* centralized undirected structure is the graph with a single edge.
*
* </para><para>
* Note that vertex-level eigenvector centrality scores do not have
* a natural scale. As with any eigenvector, their interpretation is
* invariant to scaling by a constant factor. However, due to how
* graph-level \em centralization is defined, its value depends on the
* specific scale/normalization used for vertex-level scores. This is
* true even when the graph-level centralization itself is normalized
* by its theoretical maximum value. This function makes the specific
* choice of scaling vertex-level centrality scores by their maximum
* (i.e. it uses the ∞-norm). Other normalization choices, such as the
* 1-norm or 2-norm are not currently implemented.
*
* \param graph A graph object or a null pointer, see the description
* above.
* \param nodes The number of nodes. This is ignored if the
* <code>graph</code> argument is not a null pointer.
* \p graph argument is not a null pointer.
* \param directed Boolean scalar, whether to consider edge
* directions. This argument is ignored if
* <code>graph</code> is not a null pointer and it is undirected.
* \param scale Whether to rescale the node-level centrality scores to
* \p graph is not a null pointer and it is undirected.
* \param scale This parameter is deprecated and ignored since igraph 0.10.14.
* Vertex-level centrality scores are always assumed to be scaled to
* have a maximum of one.
* \param res Pointer to a real variable, the result is stored here.
* \return Error code.
Expand All @@ -643,6 +679,15 @@ igraph_error_t igraph_centralization_eigenvector_centrality_tmax(
igraph_bool_t scale,
igraph_real_t *res) {

if (! scale) {
scale = true;
IGRAPH_WARNING("Theoretical maximum for eigenvector centralization can "
"only be computed with normalized eigenvector centrality "
"scores. Assuming that eigenvector centralities are normalized "
"by their maximum even though 'scale=false' was passed. The 'scale' "
"parameter will be removed in the future.");
}

if (graph) {
nodes = igraph_vcount(graph);
directed = directed && igraph_is_directed(graph);
Expand Down
3 changes: 2 additions & 1 deletion src/vendor/cigraph/src/centrality/closeness.c
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,8 @@ static igraph_error_t igraph_i_harmonic_centrality_weighted(const igraph_t *grap
* and |E| is the number of edges in the graph. The timing decreases with smaller
* cutoffs in a way that depends on the graph structure.
*
* \sa Other centrality types: \ref igraph_closeness(), \ref igraph_betweenness().
* \sa \ref igraph_harmonic_centrality() to calculate the exact harmonic centrality.
* Other centrality types: \ref igraph_closeness(), \ref igraph_betweenness().
*/

igraph_error_t igraph_harmonic_centrality_cutoff(const igraph_t *graph, igraph_vector_t *res,
Expand Down
Loading

0 comments on commit f4b1736

Please sign in to comment.