Skip to content

Commit 99d5218

Browse files
jamestjspclaude
andcommitted
Replace slycot with slicot throughout codebase
slicot is a C11 translation of SLICOT with Python bindings, replacing slycot (Fortran 77 wrapper). Changes: - Add control/slicot_compat.py: compatibility layer wrapping slicot functions to match slycot's API signatures - Update all imports from slycot to slicot_compat - Rename test markers: slycot -> slicot, noslycot -> noslicot - Update pyproject.toml optional dependency - Rename test/example files: slycot -> slicot Wrapper fixes for API differences: - sb03od: different parameter order, no n/m/Q params - ab09ad/ab09md/ab09nd: add ordsel param, slice output arrays - ab13dd: add fpeak input parameter - ab13md: fix parameter order, int32 casting - tb01pd: handle tol=None, slice output arrays Test results: 430 passed, 1 skipped, 1 xfail (test sensitivity) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 5c1f26f commit 99d5218

36 files changed

Lines changed: 1416 additions & 343 deletions

control/canonical.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from numpy.linalg import matrix_rank, solve
1111
from scipy.linalg import schur
1212

13-
from .exception import ControlNotImplemented, ControlSlycot
13+
from .exception import ControlNotImplemented, ControlSlicot
1414
from .iosys import issiso
1515
from .statefbk import ctrb, obsv
1616
from .statesp import StateSpace, _convert_to_statespace
@@ -330,15 +330,15 @@ def _bdschur_condmax_search(aschur, tschur, condmax):
330330
331331
Notes
332332
-----
333-
Outputs as for slycot.mb03rd.
333+
Outputs as for slicot.mb03rd.
334334
335335
`aschur`, `tschur` are as returned by scipy.linalg.schur.
336336
337337
"""
338338
try:
339-
from slycot import mb03rd
339+
from .slicot_compat import mb03rd
340340
except ImportError:
341-
raise ControlSlycot("can't find slycot module 'mb03rd'")
341+
raise ControlSlicot("can't find slicot module 'mb03rd'")
342342

343343
# see notes on RuntimeError below
344344
pmaxlower = None

control/exception.py

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,28 @@
55

66
"""Exception definitions for the control package."""
77

8-
class ControlSlycot(ImportError):
9-
"""Slycot import failed."""
8+
import warnings
9+
10+
11+
class ControlSlicot(ImportError):
12+
"""Slicot import failed."""
1013
pass
1114

15+
16+
def _deprecated_alias(old_name, new_name):
17+
"""Issue deprecation warning for renamed class/function."""
18+
warnings.warn(
19+
f"{old_name} is deprecated, use {new_name} instead",
20+
DeprecationWarning, stacklevel=3
21+
)
22+
23+
24+
class ControlSlycot(ControlSlicot):
25+
"""Deprecated alias for ControlSlicot."""
26+
def __init__(self, *args, **kwargs):
27+
_deprecated_alias('ControlSlycot', 'ControlSlicot')
28+
super().__init__(*args, **kwargs)
29+
1230
class ControlDimension(ValueError):
1331
"""Raised when dimensions of system objects are not correct."""
1432
pass
@@ -29,18 +47,22 @@ class ControlNotImplemented(NotImplementedError):
2947
"""Functionality is not yet implemented."""
3048
pass
3149

32-
# Utility function to see if Slycot is installed
33-
slycot_installed = None
34-
def slycot_check():
35-
"""Return True if Slycot is installed, otherwise False."""
36-
global slycot_installed
37-
if slycot_installed is None:
50+
# Utility function to see if slicot is installed
51+
slicot_installed = None
52+
def slicot_check():
53+
"""Return True if slicot is installed, otherwise False."""
54+
global slicot_installed
55+
if slicot_installed is None:
3856
try:
39-
import slycot # noqa: F401
40-
slycot_installed = True
57+
import slicot # noqa: F401
58+
slicot_installed = True
4159
except:
42-
slycot_installed = False
43-
return slycot_installed
60+
slicot_installed = False
61+
return slicot_installed
62+
63+
64+
# Backwards-compatible alias (no warning to avoid noise in existing code)
65+
slycot_check = slicot_check
4466

4567

4668
# Utility function to see if pandas is installed

control/margins.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from .iosys import issiso
1717
from .ctrlutil import mag2db
1818
try:
19-
from slycot import ab13md
19+
from .slicot_compat import ab13md
2020
except ImportError:
2121
ab13md = None
2222

@@ -577,7 +577,7 @@ def disk_margins(L, omega, skew=0.0, returnall=False):
577577
# Need slycot if L is MIMO, for mu calculation
578578
if not L.issiso() and ab13md == None:
579579
raise ControlMIMONotImplemented(
580-
"Need slycot to compute MIMO disk_margins")
580+
"Need slicot to compute MIMO disk_margins")
581581

582582
# Get dimensions of feedback system
583583
num_loops = statesp.ss(L).C.shape[0]

0 commit comments

Comments
 (0)