8000 Merge pull request #868 from henklaak/feature_enable_doctest · python-control/python-control@2c5c2f0 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2c5c2f0

Browse files
authored
Merge pull request #868 from henklaak/feature_enable_doctest
Implement doctests
2 parents 26c44e1 + df38286 commit 2c5c2f0

36 files changed

+769
-249
lines changed

.github/conda-env/doctest-env.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: test-env
2+
dependencies:
3+
- conda-build # for conda index
4+
- pip
5+
- coverage
6+
- coveralls
7+
- pytest
8+
- pytest-cov
9+
- pytest-timeout
10+
- pytest-xvfb
11+
- numpy
12+
- matplotlib
13+
- scipy
14+
- sphinx
15+
- sphinx_rtd_theme
16+
- ipykernel
17+
- nbsphinx
18+
- docutils
19+
- numpydoc

.github/workflows/doctest.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: Doctest
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
doctest-linux:
7+
# doctest needs to run only on
8+
# latest-greatest platform with full options
9+
runs-on: ubuntu-latest
10+
11+
steps:
12+
- name: Checkout python-control
13+
uses: actions/checkout@v3
14+
15+
- name: Setup Conda
16+
uses: conda-incubator/setup-miniconda@v2
17+
with:
18+
python-version: 3.11
19+
activate-environment: test-env
20+
environment-file: .github/conda-env/doctest-env.yml
21+
miniforge-version: latest
22+
miniforge-variant: Mambaforge
23+
channels: conda-forge
24+
channel-priority: strict
25+
auto-update-conda: false
26+
auto-activate-base: false
27+
28+
- name: Install full dependencies
29+
shell: bash -l {0}
30+
run: |
31+
mamba install cvxopt pandas slycot
32+
33+
- name: Run doctest
34+
shell: bash -l {0}
35+
env:
36+
PYTHON_CONTROL_ARRAY_AND_MATRIX: ${{ matrix.array-and-matrix }}
37+
MPLBACKEND: ${{ matrix.mplbackend }}
38+
working-directory: doc
39+
run: |
40+
make html
41+
make doctest
42+
43+
- name: Archive results
44+
uses: actions/upload-artifact@v3
45+
with:
46+
name: doctest-output
47+
path: doc/_build/doctest/output.txt

control/__init__.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,23 @@
4242
"""
4343
The Python Control Systems Library :mod:`control` provides common functions
4444
for analyzing and designing feedback control systems.
45+
46+
Documentation is available in two forms: docstrings provided with the code,
47+
and the python-control users guide, available from `the python-control
48+
homepage <https://www.python-control.org>`_.
49+
50+
The docstring examples assume that the following import commands::
51+
52+
>>> import numpy as np
53+
>>> import control as ct
54+
55+
Available subpackages
56+
---------------------
57+
flatsys
58+
Differentially flat systems
59+
optimal
60+
Optimization-based control
61+
4562
"""
4663

4764
# Import functions from within the control system library

control/bdalg.py

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,17 @@ def series(sys1, *sysn):
9999
100100
Examples
101101
--------
102-
>>> sys3 = series(sys1, sys2) # Same as sys3 = sys2 * sys1
103-
104-
>>> sys5 = series(sys1, sys2, sys3, sys4) # More systems
102+
>>> G1 = ct.rss(3)
103+
>>> G2 = ct.rss(4)
104+
>>> G = ct.series(G1, G2) # Same as sys3 = sys2 * sys1
105+
>>> G.ninputs, G.noutputs, G.nstates
106+
(1, 1, 7)
107+
108+
>>> G1 = ct.rss(2, inputs=2, outputs=3)
109+
>>> G2 = ct.rss(3, inputs=3, outputs=1)
110+
>>> G = ct.series(G1, G2) # Same as sys3 = sys2 * sys1
111+
>>> G.ninputs, G.noutputs, G.nstates
112+
(2, 1, 5)
105113
106114
"""
107115
from functools import reduce
@@ -146,9 +154,17 @@ def parallel(sys1, *sysn):
146154
147155
Examples
148156
--------
149-
>>> sys3 = parallel(sys1, sys2) # Same as sys3 = sys1 + sys2
150-
151-
>>> sys5 = parallel(sys1, sys2, sys3, sys4) # More systems
157+
>>> G1 = ct.rss(3)
158+
>>> G2 = ct.rss(4)
159+
>>> G = ct.parallel(G1, G2) # Same as sys3 = sys1 + sys2
160+
>>> G.ninputs, G.noutputs, G.nstates
161+
(1, 1, 7)
162+
163+
>>> G1 = ct.rss(3, inputs=3, outputs=4)
164+
>>> G2 = ct.rss(4, inputs=3, outputs=4)
165+
>>> G = ct.parallel(G1, G2) # Add another system
166+
>>> G.ninputs, G.noutputs, G.nstates
167+
(3, 4, 7)
152168
153169
"""
154170
from functools import reduce
@@ -174,7 +190,13 @@ def negate(sys):
174190
175191
Examples
176192
--------
177-
>>> sys2 = negate(sys1) # Same as sys2 = -sys1.
193+
>>> G = ct.tf([2], [1, 1])
194+
>>> G.dcgain()
195+
2.0
196+
197+
>>> Gn = ct.negate(G) # Same as sys2 = -sys1.
198+
>>> Gn.dcgain()
199+
-2.0
178200
179201
"""
180202
return -sys
@@ -222,6 +244,14 @@ def feedback(sys1, sys2=1, sign=-1):
222244
the corresponding feedback function is used. If `sys1` and `sys2` are both
223245
scalars, then TransferFunction.feedback is used.
224246
247+
Examples
248+
--------
249+
>>> G = ct.rss(3, inputs=2, outputs=5)
250+
>>> C = ct.rss(4, inputs=5, outputs=2)
251+
>>> T = ct.feedback(G, C, sign=1)
252+
>>> T.ninputs, T.noutputs, T.nstates
253+
(2, 5, 7)
254+
225255
"""
226256
# Allow anything with a feedback function to call that function
227257
try:
@@ -278,9 +308,17 @@ def append(*sys):
278308
279309
Examples
280310
--------
281-
>>> sys1 = ss([[1., -2], [3., -4]], [[5.], [7]], [[6., 8]], [[9.]])
282-
>>> sys2 = ss([[-1.]], [[1.]], [[1.]], [[0.]])
283-
>>> sys = append(sys1, sys2)
311+
>>> G1 = ct.rss(3)
312+
>>> G2 = ct.rss(4)
313+
>>> G = ct.append(G1, G2)
314+
>>> G.ninputs, G.noutputs, G.nstates
315+
(2, 2, 7)
316+
317+
>>> G1 = ct.rss(3, inputs=2, outputs=4)
318+
>>> G2 = ct.rss(4, inputs=1, outputs=4)
319+
>>> G = ct.append(G1, G2)
320+
>>> G.ninputs, G.noutputs, G.nstates
321+
(3, 8, 7)
284322
285323
"""
286324
s1 = ss._convert_to_statespace(sys[0])
@@ -323,11 +361,11 @@ def connect(sys, Q, inputv, outputv):
323361
324362
Examples
325363
--------
326-
>>> sys1 = ss([[1., -2], [3., -4]], [[5.], [7]], [[6, 8]], [[9.]])
327-
>>> sys2 = ss([[-1.]], [[1.]], [[1.]], [[0.]])
328-
>>> sys = append(sys1, sys2)
329-
>>> Q = [[1, 2], [2, -1]] # negative feedback interconnection
330-
>>> sysc = connect(sys, Q, [2], [1, 2])
364+
>>> G = ct.rss(7, inputs=2, outputs=2)
365+
>>> K = [[1, 2], [2, -1]] # negative feedback interconnection
366+
>>> T = ct.connect(G, K, [2], [1, 2])
367+
>>> T.ninputs, T.noutputs, T.nstates
368+
(1, 2, 7)
331369
332370
Notes
333371
-----

control/bench/time_freqresp.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
from numpy import logspace
44
from timeit import timeit
55

6-
nstates = 10
7-
sys = rss(nstates)
8-
sys_tf = tf(sys)
9-
w = logspace(-1,1,50)
10-
ntimes = 1000
11-
time_ss = timeit("sys.freqquency_response(w)", setup="from __main__ import sys, w", number=ntimes)
12-
time_tf = timeit("sys_tf.frequency_response(w)", setup="from __main__ import sys_tf, w", number=ntimes)
13-
print("State-space model on %d states: %f" % (nstates, time_ss))
14-
print("Transfer-function model on %d states: %f" % (nstates, time_tf))
6+
7+
if __name__ == '__main__':
8+
nstates = 10
9+
sys = rss(nstates)
10+
sys_tf = tf(sys)
11+
w = logspace(-1,1,50)
12+
ntimes = 1000
13+
time_ss = timeit("sys.freqquency_response(w)", setup="from __main__ import sys, w", number=ntimes)
14+
time_tf = timeit("sys_tf.frequency_response(w)", setup="from __main__ import sys_tf, w", number=ntimes)
15+
print("State-space model on %d states: %f" % (nstates, time_ss))
16+
print("Transfer-function model on %d states: %f" % (nstates, time_tf))

0 commit comments

Comments
 (0)
0