|
1 | 1 | from numpy import * |
2 | 2 | from numpy.linalg import * |
3 | 3 | from scipy.integrate import solve_ivp |
4 | | -from scipy.linalg import solve_continuous_are |
5 | 4 | from matplotlib.pyplot import * |
6 | | -from numpy.testing import * |
7 | 5 | # Python 3.x Standard Library |
8 | 6 | import gc |
9 | 7 | import os |
@@ -63,82 +61,110 @@ def set_ratio(ratio=1.0, bottom=0.1, top=0.1, left=0.1, right=0.1): |
63 | 61 | height_in = (1.0 - left - right)/(1.0 - bottom - top) * width_in / ratio |
64 | 62 | pp.gcf().set_size_inches((width_in, height_in)) |
65 | 63 | pp.gcf().subplots_adjust(bottom=bottom, top=1.0-top, left=left, right=1.0-right) |
| 64 | + |
| 65 | +width |
66 | 66 | def Q(f, xs, ys): |
67 | 67 | X, Y = meshgrid(xs, ys) |
68 | 68 | fx = vectorize(lambda x, y: f([x, y])[0]) |
69 | 69 | fy = vectorize(lambda x, y: f([x, y])[1]) |
70 | 70 | return X, Y, fx(X, Y), fy(X, Y) |
71 | | -from scipy.signal import place_poles |
72 | | -A = array([[0, 1], [0, 0]]) |
73 | | -C = array([[1, 0]]) |
74 | | -poles = [-1, -2] |
75 | | -K = place_poles(A.T, C.T, poles).gain_matrix |
76 | | -L = K.T |
77 | | -assert_almost_equal(K, [[3.0, 2.0]]) |
78 | | -def fun(t, X_Xhat): |
79 | | - x, x_hat = X_Xhat[0:2], X_Xhat[2:4] |
80 | | - y, y_hat = C.dot(x), C.dot(x_hat) |
81 | | - dx = A.dot(x) |
82 | | - dx_hat = A.dot(x_hat) - L.dot(y_hat - y) |
83 | | - return r_[dx, dx_hat] |
84 | | -y0 = [-2.0, 1.0, 0.0, 0.0] |
85 | | -result = solve_ivp( |
86 | | - fun=fun, |
87 | | - t_span=[0.0, 5.0], |
88 | | - y0=y0, |
89 | | - max_step=0.1 |
90 | | -) |
| 71 | +def fun(t, y): |
| 72 | + return y * y |
| 73 | +t0, tf, y0 = 0.0, 3.0, array([1.0]) |
| 74 | +result = solve_ivp(fun, t_span=[t0, tf], y0=y0) |
| 75 | +figure() |
| 76 | +plot(result["t"], result["y"][0], "k") |
| 77 | +xlim(t0, tf); xlabel("$t$"); ylabel("$x(t)$") |
| 78 | +tight_layout() |
| 79 | +save("images/finite-time-blowup") |
| 80 | +tf = 1.0 |
| 81 | +r = solve_ivp(fun, [t0, tf], y0, |
| 82 | + dense_output=True) |
| 83 | +figure() |
| 84 | +t = linspace(t0, tf, 1000) |
| 85 | +plot(t, r["sol"](t)[0], "k") |
| 86 | +ylim(0.0, 10.0); grid(); |
| 87 | +xlabel("$t$"); ylabel("$x(t)$") |
| 88 | +tight_layout() |
| 89 | +save("images/finite-time-blowup-2") |
| 90 | +def f(x1x2): |
| 91 | + x1, x2 = x1x2 |
| 92 | + dx1 = 1.0 if x1 < 0.0 else -1.0 |
| 93 | + return array([dx1, 0.0]) |
91 | 94 | figure() |
92 | | -t = result["t"] |
93 | | -y = result["y"] |
94 | | -plot(t, y[0], "C0", label="$x_1$") |
95 | | -plot(t, y[2], "C0--", label=r"$\hat{x}_1$") |
96 | | -plot(t, y[1], "C1", label="$x_2$") |
97 | | -plot(t, y[3], "C1--", label=r"$\hat{x}_2$") |
98 | | -xlabel("$t$"); grid(); legend() |
| 95 | +x1 = x2 = linspace(-1.0, 1.0, 20) |
| 96 | +gca().set_aspect(1.0) |
| 97 | +quiver(*Q(f, x1, x2), color="k") |
| 98 | +tight_layout() |
| 99 | +save("images/discont") |
| 100 | +def sigma(x): |
| 101 | + return 1 / (1 + exp(-x)) |
| 102 | +figure() |
| 103 | +x = linspace(-7.0, 7.0, 1000) |
| 104 | +plot(x, sigma(x), label="$y=\sigma(x)$") |
| 105 | +grid(True) |
| 106 | +xlim(-5, 5) |
| 107 | +xticks([-5.0, 0.0, 5.0]) |
| 108 | +yticks([0.0, 0.5, 1.0]) |
| 109 | +xlabel("$x$") |
| 110 | +ylabel("$y$") |
| 111 | +legend() |
99 | 112 | pp.gcf().subplots_adjust(bottom=0.2) |
100 | | -save("images/observer-trajectories") |
101 | | -A = array([[0, 1], [0, 0]]) |
102 | | -B = array([[0], [1]]) |
103 | | -Q = array([[1, 0], [0, 1]]) |
104 | | -R = array([[1]]) |
105 | | -sca = solve_continuous_are |
106 | | -Sigma = sca(A.T, C.T, inv(Q), inv(R)) |
107 | | -L = Sigma @ C.T @ R |
| 113 | +save("images/sigmoid") |
| 114 | +alpha = 2 / 3; beta = 4 / 3; delta = gamma = 1.0 |
108 | 115 |
|
109 | | -eigenvalues, _ = eig(A - L @ C) |
110 | | -assert all([real(s) < 0 for s in eigenvalues]) |
111 | | -figure() |
112 | | -x = [real(s) for s in eigenvalues] |
113 | | -y = [imag(s) for s in eigenvalues] |
114 | | -plot(x, y, "kx"); xlim(-2, 2); ylim(-2, 2) |
115 | | -plot([0, 0], [-2, 2], "k"); |
116 | | -plot([-2, 2], [0, 0], "k") |
117 | | -grid(True); axis("square") |
118 | | -title("Eigenvalues") |
119 | | -axis("square") |
120 | | -axis([-2, 2, -2, 2]) |
121 | | -save("images/poles-Kalman") |
122 | | -def fun(t, X_Xhat): |
123 | | - x, x_hat = X_Xhat[0:2], X_Xhat[2:4] |
124 | | - y, y_hat = C.dot(x), C.dot(x_hat) |
125 | | - dx = A.dot(x) |
126 | | - dx_hat = A.dot(x_hat) - L.dot(y_hat - y) |
127 | | - return r_[dx, dx_hat] |
128 | | -y0 = [-2.0, 1.0, 0.0, 0.0] |
| 116 | +def fun(t, y): |
| 117 | + x, y = y |
| 118 | + u = alpha * x - beta * x * y |
| 119 | + v = delta * x * y - gamma * y |
| 120 | + return array([u, v]) |
| 121 | +tf = 3.0 |
129 | 122 | result = solve_ivp( |
130 | | - fun=fun, |
131 | | - t_span=[0.0, 5.0], |
132 | | - y0=y0, |
133 | | - max_step=0.1 |
134 | | -) |
| 123 | + fun, |
| 124 | + t_span=(0.0, tf), |
| 125 | + y0=[1.5, 1.5], |
| 126 | + max_step=0.01) |
| 127 | +x, y = result["y"][0], result["y"][1] |
| 128 | +def display_streamplot(): |
| 129 | + ax = gca() |
| 130 | + xr = yr = linspace(0.0, 2.0, 1000) |
| 131 | + def f(y): |
| 132 | + return fun(0, y) |
| 133 | + streamplot(*Q(f, xr, yr), color="grey") |
| 134 | +def display_reference_solution(): |
| 135 | + for xy in zip(x, y): |
| 136 | + x_, y_ = xy |
| 137 | + gca().add_artist(Circle((x_, y_), |
| 138 | + 0.2, color="#d3d3d3")) |
| 139 | + gca().add_artist(Circle((x[0], y[0]), 0.1, |
| 140 | + color="#808080")) |
| 141 | + plot(x, y, "k") |
| 142 | +def display_alternate_solution(): |
| 143 | + result = solve_ivp(fun, |
| 144 | + t_span=[0.0, tf], |
| 145 | + y0=[1.5, 1.575], |
| 146 | + max_step=0.01) |
| 147 | + x, y = result["y"][0], result["y"][1] |
| 148 | + plot(x, y, "k--") |
| 149 | +figure() |
| 150 | +display_streamplot() |
| 151 | +display_reference_solution() |
| 152 | +display_alternate_solution() |
| 153 | +axis([0,2,0,2]); axis("square") |
| 154 | +save("images/continuity") |
| 155 | +def fun(t, y): |
| 156 | + x = y[0] |
| 157 | + dx = sqrt(abs(y)) |
| 158 | + return [dx] |
| 159 | +tspan = [0.0, 3.0] |
| 160 | +t = linspace(tspan[0], tspan[1], 1000) |
135 | 161 | figure() |
136 | | -t = result["t"]; y = result["y"] |
137 | | -plot(t, y[0], "C0", label="$x_1$") |
138 | | -plot(t, y[2], "C0--", label=r"$\hat{x}_1$") |
139 | | -plot(t, y[1], "C1", label="$x_2$") |
140 | | -plot(t, y[3], "C1--", label=r"$\hat{x}_2$") |
141 | | -xlabel("$t$") |
142 | | -grid(); legend() |
| 162 | +for x0 in [0.1, 0.01, 0.001, 0.0001, 0.0]: |
| 163 | + r = solve_ivp(fun, tspan, [x0], |
| 164 | + dense_output=True) |
| 165 | + plot(t, r["sol"](t)[0], |
| 166 | + label=f"$x_0 = {x0}$") |
| 167 | +xlabel("$t$"); ylabel("$x(t)$") |
| 168 | +legend() |
143 | 169 | pp.gcf().subplots_adjust(bottom=0.2) |
144 | | -save("images/observer-Kalman-trajectories") |
| 170 | +save("images/eps") |
0 commit comments