GeezerVison is showing github.com — Combination of transformations and reductions leads to model data corruption · Issue #1177 · python-control/python-control
Combination of transformations and reductions leads to model data corruption #1177Activityroryyorke commented on Aug 2, 2025 I can reproduce the fault, but it's non-deterministic. This keeps trying until it breaks:
import time
import control
def main():
i = 1
while True:
print(f'\riter {i} ...', end='')
K_dk = control.rss(21, 1, 2, strictly_proper=True)
K_arduino = reduce(K_dk,100,6)
print(' done', end='')
#time.sleep(0.1)
i += 1
def reduce(K,limit,order):
K,_ = control.modal_form(K)
fast_modes = list()
n = K.A.shape[0]
for i in range(n):
fast = False
for j,k in [(i,i-1),(i,i),(i,i+1),(i-1,i),(i+1,i)]:
if j>=0 and k>=0 and j<n and k<n and abs(K.A[j,k]) > limit: fast = True
if fast: fast_modes.append(i)
return control.balanced_reduction(control.model_reduction(K,fast_modes),order,method="matchdc")
if __name__ == "__main__":
main()
Sample output:
work) rory@rory-latitude:~/projects/pycontrol/gh1177$ python ex1.py
iter 184 ...Segmentation fault (core dumped)
(work) rory@rory-latitude:~/projects/pycontrol/gh1177$ python ex1.py
iter 44 ...corrupted size vs. prev_size
Aborted (core dumped)
(work) rory@rory-latitude:~/projects/pycontrol/gh1177$ python ex1.py
iter 44 ...corrupted double-linked list
Aborted (core dumped)
(work) rory@rory-latitude:~/projects/pycontrol/gh1177$ python ex1.py
iter 170 ...Segmentation fault (core dumped)
(work) rory@rory-latitude:~/projects/pycontrol/gh1177$ python ex1.py
iter 9 ...Segmentation fault (core dumped)
(work) rory@rory-latitude:~/projects/pycontrol/gh1177$ python ex1.py
iter 9 ...corrupted size vs. prev_size
Aborted (core dumped)
(work) rory@rory-latitude:~/projects/pycontrol/gh1177$ python ex1.py
iter 184 ...Segmentation fault (core dumped)
I've attached the Conda environment config file, whence likely important versions:
- control=0.10.2=pyhd8ed1ab_0
- cpython=3.12.11=py312hd8ed1ab_0
- libblas=3.9.0=32_h59b9bed_openblas
- libcblas=3.9.0=32_he106b2a_openblas
- liblapack=3.9.0=32_h7ac8fdf_openblas
- libopenblas=0.3.30=pthreads_h94d23a6_1
- numpy=2.3.2=py312h33ff503_0
- slycot=0.6.0=py312hb6c5a0b_2
My system:
(work) rory@rory-latitude:~/projects/pycontrol/gh1177$ uname -a
Linux rory-latitude 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
work-env.yaml.zip roryyorke commented on Aug 2, 2025 running a simpler, single-invocation of the test case under valgrind gives the output below. Command valgrind --log-file=valgrind2.out python ex2.py; ex2.py is at the end.
I'm not sure where the first problem ("Conditional jump...") is, but it looks like the next one ("Invalid write ...") happens starting from ab09nd which is in SLICOT, so called via Slycot.
==120208== Memcheck, a memory error detector
==120208== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==120208== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==120208== Command: python ex2.py
==120208== Parent PID: 20410
==120208==
==120208== Conditional jump or move depends on uninitialised value(s)
==120208== at 0x383D0B: PyUnicode_Decode (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x377EDE: unicode_new (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x314C7C: _PyObject_MakeTpCall (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x21BF1F: _PyEval_EvalFrameDefault.cold (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x317719: _PyObject_FastCallDictTstate (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x342C52: slot_tp_init (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x314D5B: _PyObject_MakeTpCall (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x21BF1F: _PyEval_EvalFrameDefault.cold (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x3CF6FD: PyEval_EvalCode (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x3EA9CC: builtin_exec (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x329F15: cfunction_vectorcall_FASTCALL_KEYWORDS (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x21CC53: _PyEval_EvalFrameDefault.cold (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208==
==120208== Invalid write of size 4
==120208== at 0x69D3F2F: dgetf2_k (in /home/rory/miniforge3/envs/work/lib/libopenblasp-r0.3.30.so)
==120208== by 0x6651130: dgetrf_ (in /home/rory/miniforge3/envs/work/lib/libopenblasp-r0.3.30.so)
==120208== by 0x3349A655: ab09dd_ (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/slycot/_wrapper.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x33499DBF: ab09bx_ (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/slycot/_wrapper.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x3349BB90: ab09nd_ (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/slycot/_wrapper.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x334605CA: f2py_rout__wrapper_ab09nd (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/slycot/_wrapper.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x314D8A: _PyObject_MakeTpCall (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x21BF1F: _PyEval_EvalFrameDefault.cold (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x3CF6FD: PyEval_EvalCode (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x3F37B9: run_eval_code_obj (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x3EEA9A: run_mod (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x4077AF: pyrun_file (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== Address 0x2c0a2558 is 0 bytes after a block of size 8 alloc'd
==120208== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==120208== by 0x5D8F00E: PyDataMem_UserNEW (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/numpy/_core/_multiarray_umath.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x5DAEA84: PyArray_NewFromDescr_int (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/numpy/_core/_multiarray_umath.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x5DB2D55: PyArray_NewLikeArrayWithShape (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/numpy/_core/_multiarray_umath.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x5DB30BD: PyArray_NewLikeArray (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/numpy/_core/_multiarray_umath.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x5DF4C5F: array_astype (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/numpy/_core/_multiarray_umath.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x329F15: cfunction_vectorcall_FASTCALL_KEYWORDS (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x5D1B363: gentype_generic_method (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/numpy/_core/_multiarray_umath.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x3376A0: method_vectorcall_VARARGS_KEYWORDS (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x329C9E: PyObject_Vectorcall (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x21BF1F: _PyEval_EvalFrameDefault.cold (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x3CF6FD: PyEval_EvalCode (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208==
==120208== Invalid read of size 4
==120208== at 0x69D3E05: dgetf2_k (in /home/rory/miniforge3/envs/work/lib/libopenblasp-r0.3.30.so)
==120208== by 0x6651130: dgetrf_ (in /home/rory/miniforge3/envs/work/lib/libopenblasp-r0.3.30.so)
==120208== by 0x3349A655: ab09dd_ (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/slycot/_wrapper.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x33499DBF: ab09bx_ (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/slycot/_wrapper.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x3349BB90: ab09nd_ (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/slycot/_wrapper.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x334605CA: f2py_rout__wrapper_ab09nd (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/slycot/_wrapper.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x314D8A: _PyObject_MakeTpCall (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x21BF1F: _PyEval_EvalFrameDefault.cold (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x3CF6FD: PyEval_EvalCode (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x3F37B9: run_eval_code_obj (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x3EEA9A: run_mod (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x4077AF: pyrun_file (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== Address 0x2c0a2558 is 0 bytes after a block of size 8 alloc'd
==120208== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==120208== by 0x5D8F00E: PyDataMem_UserNEW (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/numpy/_core/_multiarray_umath.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x5DAEA84: PyArray_NewFromDescr_int (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/numpy/_core/_multiarray_umath.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x5DB2D55: PyArray_NewLikeArrayWithShape (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/numpy/_core/_multiarray_umath.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x5DB30BD: PyArray_NewLikeArray (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/numpy/_core/_multiarray_umath.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x5DF4C5F: array_astype (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/numpy/_core/_multiarray_umath.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x329F15: cfunction_vectorcall_FASTCALL_KEYWORDS (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x5D1B363: gentype_generic_method (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/numpy/_core/_multiarray_umath.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x3376A0: method_vectorcall_VARARGS_KEYWORDS (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x329C9E: PyObject_Vectorcall (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x21BF1F: _PyEval_EvalFrameDefault.cold (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x3CF6FD: PyEval_EvalCode (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208==
==120208== at 0x58046FFA: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
==120208== by 0x58047127: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
==120208== by 0x580472CB: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
==120208== by 0x580514B4: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
==120208== by 0x5803DE9A: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
==120208== by 0x5803CD9F: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
==120208== by 0x58041F04: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
==120208== by 0x5803C1D8: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
==120208== by 0x101022653A: ???
==120208== by 0x1002EB9F2F: ???
==120208== by 0x1002EB9F17: ???
==120208== by 0x1002EB9F2F: ???
==120208== by 0x1002EB9F3F: ???
==120208== at 0x81C9661: dlacn2_ (in /home/rory/miniforge3/envs/work/lib/libopenblasp-r0.3.30.so)
==120208== by 0x818112C: dgecon_ (in /home/rory/miniforge3/envs/work/lib/libopenblasp-r0.3.30.so)
==120208== by 0x3349A6BA: ab09dd_ (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/slycot/_wrapper.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x33499DBF: ab09bx_ (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/slycot/_wrapper.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x3349BB90: ab09nd_ (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/slycot/_wrapper.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x334605CA: f2py_rout__wrapper_ab09nd (in /home/rory/miniforge3/envs/work/lib/python3.12/site-packages/slycot/_wrapper.cpython-312-x86_64-linux-gnu.so)
==120208== by 0x314D8A: _PyObject_MakeTpCall (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x21BF1F: _PyEval_EvalFrameDefault.cold (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x3CF6FD: PyEval_EvalCode (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x3F37B9: run_eval_code_obj (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x3EEA9A: run_mod (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x4077AF: pyrun_file (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x4072FD: _PyRun_SimpleFileObject (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x406A43: _PyRun_AnyFileObject (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x3FF1E1: Py_RunMain (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x3B7FA6: Py_BytesMain (in /home/rory/miniforge3/envs/work/bin/python3.12)
==120208== by 0x4A13082: (below main) (libc-start.c:308)
==120208== at 0x69C545C: blas_thread_server (in /home/rory/miniforge3/envs/work/lib/libopenblasp-r0.3.30.so)
==120208== by 0x4878608: start_thread (pthread_create.c:477)
==120208== by 0x4B0E352: clone (clone.S:95)
==120208== at 0x487F376: futex_wait_cancelable (futex-internal.h:183)
==120208== by 0x487F376: __pthread_cond_wait_common (pthread_cond_wait.c:508)
==120208== by 0x487F376: pthread_cond_wait@@GLIBC_2.3.2 (pthread_cond_wait.c:647)
==120208== by 0x69C54AB: blas_thread_server (in /home/rory/miniforge3/envs/work/lib/libopenblasp-r0.3.30.so)
==120208== by 0x4878608: start_thread (pthread_create.c:477)
==120208== by 0x4B0E352: clone (clone.S:95)
==120208== at 0x487F376: futex_wait_cancelable (futex-internal.h:183)
==120208== by 0x487F376: __pthread_cond_wait_common (pthread_cond_wait.c:508)
==120208== by 0x487F376: pthread_cond_wait@@GLIBC_2.3.2 (pthread_cond_wait.c:647)
==120208== by 0x69C54AB: blas_thread_server (in /home/rory/miniforge3/envs/work/lib/libopenblasp-r0.3.30.so)
==120208== by 0x4878608: start_thread (pthread_create.c:477)
==120208== by 0x4B0E352: clone (clone.S:95)
import control
def reduce(K,limit,order):
K,_ = control.modal_form(K)
fast_modes = list()
n = K.A.shape[0]
for i in range(n):
fast = False
for j,k in [(i,i-1),(i,i),(i,i+1),(i-1,i),(i+1,i)]:
if j>=0 and k>=0 and j<n and k<n and abs(K.A[j,k]) > limit: fast = True
if fast: fast_modes.append(i)
return control.balanced_reduction(control.model_reduction(K,fast_modes),order,method="matchdc")
K_dk = control.rss(21, 1, 2, strictly_proper=True)
K_arduino = reduce(K_dk,100,6)roryyorke commented on Aug 2, 2025 roryyorke commented on Aug 2, 2025 It turns out this was fixed in python-control/Slycot#243, but we haven't made a Slycot release in a while.
If I run tests with python-control 0.10.2 and Slycot master, I can't reproduce this.
This issue can be closed, and I'll open a Slycot issue to discuss making a release. bbbccd commented on Aug 2, 2025
I can reproduce the fault, but it's non-deterministic.
I don't know exactly what you mean by deterministic, but the original long code that produced this bug fails everytime (albeit with different errors).
This issue can be closed, and I'll open a Slycot issue to discuss making a release.
is there a workaround in the meantime? murrayrm commented on Aug 2, 2025
is there a workaround in the meantime?
If you have a FORTRAN compiler on your system, you could check out the development version of slycot from github and do a local installation. bbbccd commented on Aug 2, 2025
If you have a FORTRAN compiler on your system, you could check out the development version of slycot from github and do a local installation.
:) ok so nothing easy then, thanks
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|