[med-svn] [Git][med-team/python-leidenalg][upstream] New upstream version 0.12.0
Étienne Mollier (@emollier)
gitlab at salsa.debian.org
Sun Jun 14 14:57:57 BST 2026
Étienne Mollier pushed to branch upstream at Debian Med / python-leidenalg
Commits:
abac6111 by Étienne Mollier at 2026-06-14T15:41:24+02:00
New upstream version 0.12.0
- - - - -
11 changed files:
- + .github/dependabot.yml
- + .github/workflows/build.yml
- CHANGELOG
- doc/source/advanced.rst
- include/pynterface.h
- include/python_optimiser_interface.h
- scripts/build_libleidenalg.bat
- scripts/build_libleidenalg.sh
- src/leidenalg/Optimiser.py
- src/leidenalg/python_optimiser_interface.cpp
- tests/test_Optimiser.py
Changes:
=====================================
.github/dependabot.yml
=====================================
@@ -0,0 +1,6 @@
+version: 2
+updates:
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
=====================================
.github/workflows/build.yml
=====================================
@@ -0,0 +1,256 @@
+name: Build and test, upload to PyPI on release
+
+on:
+ push:
+ branches:
+ - master
+ - '*'
+ tags:
+ - '*'
+ pull_request:
+ branches:
+ - master
+
+env:
+ CIBW_ENABLE: pypy
+ CIBW_TEST_REQUIRES: ddt
+ CIBW_TEST_COMMAND: "cd {project} && python -m unittest -v"
+ CIBW_PROJECT_REQUIRES_PYTHON: ">=3.9"
+ # Free-threaded builds excluded for Python because they do not support the limited API
+ CIBW_SKIP: "cp3??t-*"
+
+jobs:
+ build_wheel_linux:
+ name: Build wheels on Linux (${{ matrix.wheel_arch }})
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ wheel_arch: [x86_64, i686]
+
+ steps:
+ - uses: actions/checkout at v6
+ with:
+ submodules: true
+ fetch-depth: 0
+
+ - uses: actions/setup-python at v6
+ name: Install Python
+ with:
+ python-version: '3.13'
+
+ - name: Build wheels (manylinux)
+ uses: pypa/cibuildwheel at v3.4.1
+ env:
+ CIBW_BEFORE_BUILD: "yum install -y flex bison &&
+ pip install cmake wheel &&
+ {package}/scripts/build_igraph.sh &&
+ {package}/scripts/build_libleidenalg.sh "
+ CIBW_ARCHS_LINUX: ${{ matrix.wheel_arch }}
+ CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}"
+ CIBW_ENVIRONMENT: >
+ CFLAGS='-I/project/build-deps/install/include/ -L/project/build-deps/install/lib64/ -L/project/build-deps/install/lib/'
+ LD_LIBRARY_PATH='/project/build-deps/install/lib64/:/project/build-deps/install/lib/'
+
+ - name: Build wheels (musllinux)
+ uses: pypa/cibuildwheel at v3.4.1
+ env:
+ CIBW_BEFORE_BUILD: "apk add flex bison zlib-dev &&
+ pip install cmake wheel &&
+ {package}/scripts/build_igraph.sh &&
+ {package}/scripts/build_libleidenalg.sh"
+ CIBW_ARCHS_LINUX: ${{ matrix.wheel_arch }}
+ CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}"
+ CIBW_TEST_EXTRAS: "test-musl"
+ CIBW_ENVIRONMENT: >
+ CFLAGS='-I/project/build-deps/install/include/ -L/project/build-deps/install/lib64/ -L/project/build-deps/install/lib/'
+ LD_LIBRARY_PATH='/project/build-deps/install/lib64/:/project/build-deps/install/lib/'
+
+ - uses: actions/upload-artifact at v7
+ with:
+ name: wheels-linux-${{ matrix.wheel_arch }}
+ path: ./wheelhouse/*.whl
+
+ build_wheel_linux_aarch64:
+ name: Build wheels on Linux (aarch64)
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout at v6
+ with:
+ submodules: true
+ fetch-depth: 0
+
+ - name: Set up QEMU
+ id: qemu
+ uses: docker/setup-qemu-action at v4
+
+ - name: Build wheels (manylinux)
+ uses: pypa/cibuildwheel at v3.4.1
+ env:
+ CIBW_BEFORE_BUILD: "yum install -y flex bison zlib-devel &&
+ pip install cmake wheel &&
+ {package}/scripts/build_igraph.sh &&
+ {package}/scripts/build_libleidenalg.sh"
+ CIBW_ARCHS_LINUX: aarch64
+ CIBW_BUILD: "*-manylinux_aarch64"
+ CIBW_ENVIRONMENT: >
+ CFLAGS='-I/project/build-deps/install/include/ -L/project/build-deps/install/lib64/ -L/project/build-deps/install/lib/'
+ LD_LIBRARY_PATH='/project/build-deps/install/lib64/:/project/build-deps/install/lib/'
+
+ - uses: actions/upload-artifact at v7
+ with:
+ name: wheels-linux-aarch64
+ path: ./wheelhouse/*.whl
+
+ build_wheel_macos:
+ name: Build wheels on macOS (${{ matrix.wheel_arch }})
+ runs-on: macos-latest
+ env:
+ LLVM_VERSION: "14.0.5"
+ strategy:
+ matrix:
+ include:
+ - cmake_arch: x86_64
+ wheel_arch: x86_64
+ - cmake_arch: arm64
+ extra_cmake_args: -DF2C_EXTERNAL_ARITH_HEADER=../../../etc/arith_apple_m1.h -DIEEE754_DOUBLE_ENDIANNESS_MATCHES=ON
+ wheel_arch: arm64
+
+ steps:
+ - uses: actions/checkout at v6
+ with:
+ submodules: true
+ fetch-depth: 0
+
+ - name: Cache installed C core
+ id: cache-c-core
+ uses: actions/cache at v5
+ with:
+ path: build-deps
+ key: C-core-cache-${{ runner.os }}-${{ matrix.cmake_arch }}-llvm${{ env.LLVM_VERSION }}-${{ hashFiles('scripts/build_igraph.sh') }}-${{ hashFiles('scripts/build_libleidenalg.sh') }}
+
+ - uses: actions/setup-python at v6
+ name: Install Python
+ with:
+ python-version: '3.13'
+
+ - name: Install OS dependencies
+ if: steps.cache-c-core.outputs.cache-hit != 'true' || steps.cache-c-deps.outputs.cache-hit != 'true' # Only needed when building the C core
+ run:
+ brew install ninja cmake
+
+ - name: Build wheels
+ uses: pypa/cibuildwheel at v3.4.1
+ env:
+ CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}"
+ CIBW_BEFORE_BUILD: "{package}/scripts/build_igraph.sh &&
+ {package}/scripts/build_libleidenalg.sh"
+ CIBW_ENVIRONMENT: >
+ CFLAGS='-Wno-unused-command-line-argument -I/Users/runner/work/leidenalg/leidenalg/build-deps/install/include/ -L/Users/runner/work/leidenalg/leidenalg/build-deps/install/lib64/ -L/Users/runner/work/leidenalg/leidenalg/build-deps/install/lib/'
+ REPAIR_LIBRARY_PATH="${DYLD_LIBRARY_PATH}:/Users/runner/work/leidenalg/leidenalg/build-deps/install/lib64/:/Users/runner/work/leidenalg/leidenalg/build-deps/install/lib/"
+ EXTRA_CMAKE_ARGS="-DCMAKE_OSX_ARCHITECTURES=${{ matrix.cmake_arch }} ${{ matrix.extra_cmake_args }}"
+ CIBW_REPAIR_WHEEL_COMMAND: >
+ DYLD_LIBRARY_PATH=$REPAIR_LIBRARY_PATH delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel}
+ - uses: actions/upload-artifact at v7
+ with:
+ name: wheels-macos-${{ matrix.wheel_arch }}
+ path: ./wheelhouse/*.whl
+
+ build_wheel_win:
+ name: Build wheels on Windows (${{ matrix.cmake_arch }})
+ runs-on: windows-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - cmake_arch: Win32
+ wheel_arch: win32
+ - cmake_arch: x64
+ wheel_arch: win_amd64
+
+ steps:
+ - uses: actions/checkout at v6
+ with:
+ submodules: true
+ fetch-depth: 0
+
+ - uses: actions/setup-python at v6
+ name: Install Python
+ with:
+ python-version: '3.13'
+
+ - name: Cache installed C core
+ id: cache-c-core
+ uses: actions/cache at v5
+ with:
+ path: build-deps
+ key: C-core-cache-${{ runner.os }}-${{ matrix.cmake_arch }}-llvm${{ env.LLVM_VERSION }}-${{ hashFiles('scripts/build_igraph.sh') }}-${{ hashFiles('scripts/build_libleidenalg.sh') }}
+
+ - name: Install build dependencies
+ if: steps.cache-c-core.outputs.cache-hit != 'true' # Only needed when building the C core
+ run: choco install winflexbison3 cmake ninja
+
+ - name: Build wheels
+ uses: pypa/cibuildwheel at v3.4.1
+ env:
+ CIBW_BEFORE_BUILD: "{package}/scripts/build_igraph.bat &&
+ {package}/scripts/build_libleidenalg.bat &&
+ pip install delvewheel"
+ CIBW_BUILD: "*-${{ matrix.wheel_arch }}"
+ CIBW_TEST_COMMAND: "cd /d {project} && python -m unittest -v"
+ CIBW_SKIP: "cp3??t-* pp*"
+ CIBW_ENVIRONMENT: >
+ LIB="D:/a/leidenalg/leidenalg/build-deps/install/lib;$LIB"
+ INCLUDE="D:/a/leidenalg/leidenalg/build-deps/install/include/;$INCLUDE"
+ PATH="D:/a/leidenalg/leidenalg/build-deps/install/bin;$PATH"
+ EXTRA_CMAKE_ARGS="-A ${{ matrix.cmake_arch }}"
+ CIBW_REPAIR_WHEEL_COMMAND: "delvewheel repair -w {dest_dir} {wheel}"
+ - uses: actions/upload-artifact at v7
+ with:
+ name: wheels-win-${{ matrix.wheel_arch }}
+ path: ./wheelhouse/*.whl
+
+ build_sdist:
+ name: Build sdist
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout at v6
+ with:
+ submodules: true
+ fetch-depth: 0
+
+ - uses: actions/setup-python at v6
+ name: Install Python
+ with:
+ python-version: '3.13'
+
+ - name: Install pypa/build
+ run: pip3 install build
+
+ - name: Build sdist
+ run: |
+ python3 -m build --sdist
+
+ - uses: actions/upload-artifact at v7
+ with:
+ name: wheels-sdist
+ path: dist/*.tar.gz
+
+ upload_pypi:
+ needs: [build_wheel_linux, build_wheel_linux_aarch64, build_wheel_macos, build_wheel_win, build_sdist]
+ runs-on: ubuntu-latest
+ # upload to PyPI on every push from the master branch
+ if: github.event_name == 'push' &&
+ startsWith(github.ref, 'refs/tags')
+ steps:
+ - uses: actions/download-artifact at v8
+ with:
+ pattern: wheels-*
+ merge-multiple: true
+ path: dist
+
+ # Upload tagged versions to production PyPI
+ - name: Publish distribution 📦 to PyPI
+ uses: pypa/gh-action-pypi-publish at release/v1
+ with:
+ password: ${{ secrets.PYPI_API_TOKEN }}
\ No newline at end of file
=====================================
CHANGELOG
=====================================
@@ -1,3 +1,7 @@
+0.12.0
+- Update to libleidenalg 0.13.0
+ * Brings support for minimum community size
+
0.11.0
- Update to libleidenalg 0.12.0
- Update to igraph 1.0
=====================================
doc/source/advanced.rst
=====================================
@@ -227,15 +227,24 @@ We can then only update the community assignments for the new nodes as follows
In this example we used :class:`~leidenalg.CPMVertexPartition`. but any other
``VertexPartition`` would work as well.
-Maximum community size
+Minimum and maximum community size
----------------------
-In some cases, you may want to restrict the community sizes. It is possible to indicate this
-by setting the :attr:`~leidenalg.Optimiser.max_comm_size` parameter so that this constraint is
-taken into account during optimisation. In addition, it is possible to pass this parameter
-directly when using :func:`~leidenalg.find_partition`. For example
+In some cases, you may want to restrict the community sizes. It is possible to
+indicate this by setting the :attr:`~leidenalg.Optimiser.min_comm_size` and
+:attr:`~leidenalg.Optimiser.max_comm_size` parameters. Note that these
+constraints are only considered when the
+:attr:`~leidenalg.Optimiser.community_constraint_enforcement` parameter is
+larger than 0 with higher values indicating a more stringent enforcement of the
+community size constraints. For example
->>> partition = la.find_partition(G, la.ModularityVertexPartition, max_comm_size=10)
+>>> G = ig.Graph.Famous('Zachary')
+>>> part = la.ModularityVertexPartition(G)
+>>> opt = la.Optimiser()
+>>> opt.min_comm_size = 15
+>>> opt.max_comm_size = 30
+>>> opt.community_constraint_enforcement = 5
+>>> opt.optimise_partition(part)
References
----------
=====================================
include/pynterface.h
=====================================
@@ -67,7 +67,9 @@ extern "C"
{"_Optimiser_set_refine_routine", (PyCFunction)_Optimiser_set_refine_routine, METH_VARARGS | METH_KEYWORDS, ""},
{"_Optimiser_set_consider_empty_community", (PyCFunction)_Optimiser_set_consider_empty_community, METH_VARARGS | METH_KEYWORDS, ""},
{"_Optimiser_set_refine_partition", (PyCFunction)_Optimiser_set_refine_partition, METH_VARARGS | METH_KEYWORDS, ""},
+ {"_Optimiser_set_min_comm_size", (PyCFunction)_Optimiser_set_min_comm_size, METH_VARARGS | METH_KEYWORDS, ""},
{"_Optimiser_set_max_comm_size", (PyCFunction)_Optimiser_set_max_comm_size, METH_VARARGS | METH_KEYWORDS, ""},
+ {"_Optimiser_set_community_constraint_enforcement", (PyCFunction)_Optimiser_set_community_constraint_enforcement, METH_VARARGS | METH_KEYWORDS, ""},
{"_Optimiser_get_consider_comms", (PyCFunction)_Optimiser_get_consider_comms, METH_VARARGS | METH_KEYWORDS, ""},
{"_Optimiser_get_refine_consider_comms", (PyCFunction)_Optimiser_get_refine_consider_comms, METH_VARARGS | METH_KEYWORDS, ""},
@@ -75,7 +77,9 @@ extern "C"
{"_Optimiser_get_refine_routine", (PyCFunction)_Optimiser_get_refine_routine, METH_VARARGS | METH_KEYWORDS, ""},
{"_Optimiser_get_consider_empty_community", (PyCFunction)_Optimiser_get_consider_empty_community, METH_VARARGS | METH_KEYWORDS, ""},
{"_Optimiser_get_refine_partition", (PyCFunction)_Optimiser_get_refine_partition, METH_VARARGS | METH_KEYWORDS, ""},
+ {"_Optimiser_get_min_comm_size", (PyCFunction)_Optimiser_get_min_comm_size, METH_VARARGS | METH_KEYWORDS, ""},
{"_Optimiser_get_max_comm_size", (PyCFunction)_Optimiser_get_max_comm_size, METH_VARARGS | METH_KEYWORDS, ""},
+ {"_Optimiser_get_community_constraint_enforcement", (PyCFunction)_Optimiser_get_community_constraint_enforcement, METH_VARARGS | METH_KEYWORDS, ""},
{"_Optimiser_set_rng_seed", (PyCFunction)_Optimiser_set_rng_seed, METH_VARARGS | METH_KEYWORDS, ""},
=====================================
include/python_optimiser_interface.h
=====================================
@@ -42,7 +42,9 @@ extern "C"
PyObject* _Optimiser_set_refine_routine(PyObject *self, PyObject *args, PyObject *keywds);
PyObject* _Optimiser_set_consider_empty_community(PyObject *self, PyObject *args, PyObject *keywds);
PyObject* _Optimiser_set_refine_partition(PyObject *self, PyObject *args, PyObject *keywds);
+ PyObject* _Optimiser_set_min_comm_size(PyObject *self, PyObject *args, PyObject *keywds);
PyObject* _Optimiser_set_max_comm_size(PyObject *self, PyObject *args, PyObject *keywds);
+ PyObject* _Optimiser_set_community_constraint_enforcement(PyObject *self, PyObject *args, PyObject *keywds);
PyObject* _Optimiser_set_rng_seed(PyObject *self, PyObject *args, PyObject *keywds);
PyObject* _Optimiser_get_consider_comms(PyObject *self, PyObject *args, PyObject *keywds);
@@ -51,7 +53,9 @@ extern "C"
PyObject* _Optimiser_get_refine_routine(PyObject *self, PyObject *args, PyObject *keywds);
PyObject* _Optimiser_get_consider_empty_community(PyObject *self, PyObject *args, PyObject *keywds);
PyObject* _Optimiser_get_refine_partition(PyObject *self, PyObject *args, PyObject *keywds);
+ PyObject* _Optimiser_get_min_comm_size(PyObject *self, PyObject *args, PyObject *keywds);
PyObject* _Optimiser_get_max_comm_size(PyObject *self, PyObject *args, PyObject *keywds);
+ PyObject* _Optimiser_get_community_constraint_enforcement(PyObject *self, PyObject *args, PyObject *keywds);
#ifdef __cplusplus
}
=====================================
scripts/build_libleidenalg.bat
=====================================
@@ -1,6 +1,6 @@
@echo off
-set LIBLEIDENALG_VERSION="0.12.0"
+set LIBLEIDENALG_VERSION="0.13.0"
set ROOT_DIR=%cd%
echo Using root dir %ROOT_DIR%
=====================================
scripts/build_libleidenalg.sh
=====================================
@@ -1,4 +1,4 @@
-LIBLEIDENALG_VERSION=0.12.0
+LIBLEIDENALG_VERSION=0.13.0
ROOT_DIR=`pwd`
echo "Using root dir ${ROOT_DIR}"
=====================================
src/leidenalg/Optimiser.py
=====================================
@@ -219,6 +219,27 @@ class Optimiser(object):
def consider_empty_community(self, value):
_c_leiden._Optimiser_set_consider_empty_community(self._optimiser, value)
+ #########################################################3
+ # max_comm_size
+ @property
+ def min_comm_size(self):
+ """ Constrain the minimum community size.
+
+ By default (zero), communities can be of any size. If this is set to a
+ positive integer value, then communities will be constrained to be at least
+ this total size. The degree to which solutions actually adhere to this
+ constraint depends on the ``community_constraint_enforcement`` parameter.
+ """
+ return _c_leiden._Optimiser_get_min_comm_size(self._optimiser)
+
+ @min_comm_size.setter
+ def min_comm_size(self, value):
+ if value < 0:
+ raise ValueError("Negative minimum community size: %s" % value)
+ elif value > self.max_comm_size and self.max_comm_size > 0:
+ raise ValueError("Minimum community size should be less than or equal to the maximum community size")
+ _c_leiden._Optimiser_set_min_comm_size(self._optimiser, value)
+
#########################################################3
# max_comm_size
@property
@@ -227,7 +248,8 @@ class Optimiser(object):
By default (zero), communities can be of any size. If this is set to a
positive integer value, then communities will be constrained to be at most
- this total size.
+ this total size. The degree to which solutions actually adhere to this
+ constraint depends on the ``community_constraint_enforcement`` parameter.
"""
return _c_leiden._Optimiser_get_max_comm_size(self._optimiser)
@@ -235,8 +257,28 @@ class Optimiser(object):
def max_comm_size(self, value):
if value < 0:
raise ValueError("negative max_comm_size: %s" % value)
+ elif value < self.min_comm_size and self.min_comm_size > 0:
+ raise ValueError("Maximum community size should be larger than or equal to the minimum community size")
_c_leiden._Optimiser_set_max_comm_size(self._optimiser, value)
+ #########################################################3
+ # community_constraint_enforcement
+ @property
+ def community_constraint_enforcement(self):
+ """ Constrain the maximal community size.
+
+ By default (zero), communities constraints are not enforced. If this is set
+ to a positive value, then community sizes will be constrained. The higher
+ this enforcement is set, the stricter the community sizes will be constrained.
+ """
+ return _c_leiden._Optimiser_get_community_constraint_enforcement(self._optimiser)
+
+ @community_constraint_enforcement.setter
+ def community_constraint_enforcement(self, value):
+ if value < 0:
+ raise ValueError("negative community_constraint_enforcement: %s" % value)
+ _c_leiden._Optimiser_set_community_constraint_enforcement(self._optimiser, value)
+
##########################################################
# Set rng seed
def set_rng_seed(self, value):
=====================================
src/leidenalg/python_optimiser_interface.cpp
=====================================
@@ -862,6 +862,66 @@ extern "C"
return PyBool_FromLong(optimiser->refine_partition);
}
+ PyObject* _Optimiser_set_min_comm_size(PyObject *self, PyObject *args, PyObject *keywds)
+ {
+ PyObject* py_optimiser = NULL;
+ size_t min_comm_size = 0;
+ static const char* kwlist[] = {"optimiser", "min_comm_size", NULL};
+
+ #ifdef DEBUG
+ cerr << "Parsing arguments..." << endl;
+ #endif
+
+ if (!PyArg_ParseTupleAndKeywords(args, keywds, "On", (char**) kwlist,
+ &py_optimiser, &min_comm_size))
+ return NULL;
+
+ #ifdef DEBUG
+ cerr << "set_min_comm_size(" << min_comm_size << ");" << endl;
+ #endif
+
+ #ifdef DEBUG
+ cerr << "Capsule optimiser at address " << py_optimiser << endl;
+ #endif
+ Optimiser* optimiser = decapsule_Optimiser(py_optimiser);
+ #ifdef DEBUG
+ cerr << "Using optimiser at address " << optimiser << endl;
+ #endif
+
+ optimiser->min_comm_size = min_comm_size;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ PyObject* _Optimiser_get_min_comm_size(PyObject *self, PyObject *args, PyObject *keywds)
+ {
+ PyObject* py_optimiser = NULL;
+ static const char* kwlist[] = {"optimiser", NULL};
+
+ #ifdef DEBUG
+ cerr << "Parsing arguments..." << endl;
+ #endif
+
+ if (!PyArg_ParseTupleAndKeywords(args, keywds, "O", (char**) kwlist,
+ &py_optimiser))
+ return NULL;
+
+ #ifdef DEBUG
+ cerr << "get_min_comm_size();" << endl;
+ #endif
+
+ #ifdef DEBUG
+ cerr << "Capsule optimiser at address " << py_optimiser << endl;
+ #endif
+ Optimiser* optimiser = decapsule_Optimiser(py_optimiser);
+ #ifdef DEBUG
+ cerr << "Using optimiser at address " << optimiser << endl;
+ #endif
+
+ return PyLong_FromSize_t(optimiser->min_comm_size);
+ }
+
PyObject* _Optimiser_set_max_comm_size(PyObject *self, PyObject *args, PyObject *keywds)
{
PyObject* py_optimiser = NULL;
@@ -922,17 +982,78 @@ extern "C"
return PyLong_FromSize_t(optimiser->max_comm_size);
}
+
+ PyObject* _Optimiser_set_community_constraint_enforcement(PyObject *self, PyObject *args, PyObject *keywds)
+ {
+ PyObject* py_optimiser = NULL;
+ double community_constraint_enforcement = 0;
+ static const char* kwlist[] = {"optimiser", "community_constraint_enforcement", NULL};
+
+ #ifdef DEBUG
+ cerr << "Parsing arguments..." << endl;
+ #endif
+
+ if (!PyArg_ParseTupleAndKeywords(args, keywds, "Od", (char**) kwlist,
+ &py_optimiser, &community_constraint_enforcement))
+ return NULL;
+
+ #ifdef DEBUG
+ cerr << "set_community_constraint_enforcement(" << community_constraint_enforcement << ");" << endl;
+ #endif
+
+ #ifdef DEBUG
+ cerr << "Capsule optimiser at address " << py_optimiser << endl;
+ #endif
+ Optimiser* optimiser = decapsule_Optimiser(py_optimiser);
+ #ifdef DEBUG
+ cerr << "Using optimiser at address " << optimiser << endl;
+ #endif
+
+ optimiser->community_constraint_enforcement = community_constraint_enforcement;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ PyObject* _Optimiser_get_community_constraint_enforcement(PyObject *self, PyObject *args, PyObject *keywds)
+ {
+ PyObject* py_optimiser = NULL;
+ static const char* kwlist[] = {"optimiser", NULL};
+
+ #ifdef DEBUG
+ cerr << "Parsing arguments..." << endl;
+ #endif
+
+ if (!PyArg_ParseTupleAndKeywords(args, keywds, "O", (char**) kwlist,
+ &py_optimiser))
+ return NULL;
+
+ #ifdef DEBUG
+ cerr << "get_community_constraint_enforcement();" << endl;
+ #endif
+
+ #ifdef DEBUG
+ cerr << "Capsule optimiser at address " << py_optimiser << endl;
+ #endif
+ Optimiser* optimiser = decapsule_Optimiser(py_optimiser);
+ #ifdef DEBUG
+ cerr << "Using optimiser at address " << optimiser << endl;
+ #endif
+
+ return PyFloat_FromDouble(optimiser->community_constraint_enforcement);
+ }
+
PyObject* _Optimiser_set_rng_seed(PyObject *self, PyObject *args, PyObject *keywds)
{
PyObject* py_optimiser = NULL;
- int seed = 0;
+ size_t seed = 0;
static const char* kwlist[] = {"optimiser", "seed", NULL};
#ifdef DEBUG
cerr << "Parsing arguments..." << endl;
#endif
- if (!PyArg_ParseTupleAndKeywords(args, keywds, "Oi", (char**) kwlist,
+ if (!PyArg_ParseTupleAndKeywords(args, keywds, "On", (char**) kwlist,
&py_optimiser, &seed))
return NULL;
=====================================
tests/test_Optimiser.py
=====================================
@@ -17,10 +17,21 @@ class OptimiserTest(unittest.TestCase):
partition.sizes(), [100],
msg="CPMVertexPartition(resolution_parameter=0.5) of complete graph after move nodes incorrect.")
+ def test_move_nodes_with_min_comm_size(self):
+ G = ig.Graph.Full(100)
+ partition = leidenalg.CPMVertexPartition(G, resolution_parameter=1)
+ self.optimiser.min_comm_size = 5
+ self.optimiser.community_constraint_enforcement = 10
+ self.optimiser.move_nodes(partition, consider_comms=leidenalg.ALL_NEIGH_COMMS)
+ self.assertListEqual(
+ partition.sizes(), 20*[5],
+ msg="CPMVertexPartition(resolution_parameter=1) of complete graph after move nodes (min_comm_size=5) incorrect.")
+
def test_move_nodes_with_max_comm_size(self):
G = ig.Graph.Full(100)
partition = leidenalg.CPMVertexPartition(G, resolution_parameter=0.5)
self.optimiser.max_comm_size = 17
+ self.optimiser.community_constraint_enforcement = 100
self.optimiser.move_nodes(partition, consider_comms=leidenalg.ALL_NEIGH_COMMS)
self.assertListEqual(
partition.sizes(), [17, 17, 17, 17, 17, 15],
@@ -50,10 +61,21 @@ class OptimiserTest(unittest.TestCase):
G.ecount(),
msg="total_weight_in_all_comms not equal to ecount of graph.")
+ def test_merge_nodes_with_min_comm_size(self):
+ G = ig.Graph.Full(100)
+ partition = leidenalg.CPMVertexPartition(G, resolution_parameter=1)
+ self.optimiser.min_comm_size = 5
+ self.optimiser.community_constraint_enforcement = 10
+ self.optimiser.merge_nodes(partition, consider_comms=leidenalg.ALL_NEIGH_COMMS)
+ self.assertListEqual(
+ partition.sizes(), 20*[5],
+ msg="CPMVertexPartition(resolution_parameter=1) of complete graph after merge nodes (min_comm_size=5) incorrect.")
+
def test_merge_nodes_with_max_comm_size(self):
G = ig.Graph.Full(100)
partition = leidenalg.CPMVertexPartition(G, resolution_parameter=0.5)
self.optimiser.max_comm_size = 17
+ self.optimiser.community_constraint_enforcement = 100
self.optimiser.merge_nodes(partition, consider_comms=leidenalg.ALL_NEIGH_COMMS)
self.assertListEqual(
partition.sizes(), [17, 17, 17, 17, 17, 15],
@@ -80,28 +102,27 @@ class OptimiserTest(unittest.TestCase):
partition.sizes(), 10*[10],
msg="After optimising partition failed to find different components with CPMVertexPartition(resolution_parameter=0)")
- def test_optimiser_with_max_comm_size(self):
+ def test_optimiser_with_min_comm_size(self):
G = ig.Graph.Full(100)
- partition = leidenalg.CPMVertexPartition(G, resolution_parameter=0)
+ partition = leidenalg.CPMVertexPartition(G, resolution_parameter=1)
self.optimiser.consider_comms=leidenalg.ALL_NEIGH_COMMS
- self.optimiser.max_comm_size = 10
+ self.optimiser.min_comm_size = 5
+ self.optimiser.community_constraint_enforcement = 10
self.optimiser.optimise_partition(partition)
self.assertListEqual(
- partition.sizes(), 10*[10],
- msg="After optimising partition (max_comm_size=10) failed to find different components with CPMVertexPartition(resolution_parameter=0)")
+ partition.sizes(), 20*[5],
+ msg="After optimising partition (min_comm_size=5) failed to find different components with CPMVertexPartition(resolution_parameter=1)")
- def test_optimiser_split_with_max_comm_size(self):
+ def test_optimiser_with_max_comm_size(self):
G = ig.Graph.Full(100)
- partition = leidenalg.CPMVertexPartition(G, resolution_parameter=0.5)
- self.optimiser.merge_nodes(partition, consider_comms=leidenalg.ALL_NEIGH_COMMS)
- self.assertListEqual(
- partition.sizes(), [100],
- msg="CPMVertexPartition(resolution_parameter=0.5) of complete graph after merge nodes incorrect.")
+ partition = leidenalg.CPMVertexPartition(G, resolution_parameter=0)
+ self.optimiser.consider_comms=leidenalg.ALL_NEIGH_COMMS
self.optimiser.max_comm_size = 10
+ self.optimiser.community_constraint_enforcement = 100
self.optimiser.optimise_partition(partition)
self.assertListEqual(
partition.sizes(), 10*[10],
- msg="After optimising partition (max_comm_size=10) failed to find different components with CPMVertexPartition(resolution_parameter=0.5)")
+ msg="After optimising partition (max_comm_size=10) failed to find different components with CPMVertexPartition(resolution_parameter=0)")
def test_optimiser_with_is_membership_fixed(self):
G = ig.Graph.Full(3)
View it on GitLab: https://salsa.debian.org/med-team/python-leidenalg/-/commit/abac61111e39ba8d52a5f179b79995e0b968ef9b
--
View it on GitLab: https://salsa.debian.org/med-team/python-leidenalg/-/commit/abac61111e39ba8d52a5f179b79995e0b968ef9b
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20260614/60b4ab9a/attachment-0001.htm>
More information about the debian-med-commit
mailing list