Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
224 views
ubuntu2404
1
\documentclass[11pt,a4paper]{article}
2
3
% Optimization Theory and Control Systems Template
4
% SEO Keywords: optimization theory latex template, control systems latex,
5
% mathematical optimization latex
6
% Additional Keywords: convex optimization latex, optimal control latex,
7
% linear programming latex
8
% Long-tail Keywords: gradient descent algorithms latex, LQR control latex,
9
% kalman filter latex
10
11
\usepackage[utf8]{inputenc}
12
\usepackage[T1]{fontenc}
13
\usepackage{amsmath,amsfonts,amssymb}
14
\usepackage{mathtools}
15
\usepackage{physics} % for mathematical notation
16
\usepackage{siunitx} % for proper unit handling
17
\usepackage{graphicx}
18
\usepackage{float}
19
\usepackage{subcaption}
20
\usepackage{hyperref}
21
\usepackage{cleveref}
22
\usepackage{booktabs}
23
\usepackage{array}
24
\usepackage{xcolor}
25
\usepackage{algorithm}
26
\usepackage{algorithmic}
27
28
% PythonTeX for optimization computing
29
\usepackage{pythontex}
30
31
% Bibliography for optimization references
32
\usepackage[style=numeric,backend=biber]{biblatex}
33
\addbibresource{references.bib}
34
35
% Fix SiunitX physics package warning
36
\AtBeginDocument{\RenewCommandCopy\qty\SI}
37
38
% Custom commands for optimization
39
\newcommand{\minimize}{\operatorname{minimize}}
40
\newcommand{\maximize}{\operatorname{maximize}}
41
\newcommand{\subjectto}{\operatorname{subject\ to}}
42
% \grad is already defined by physics package as \nabla
43
\newcommand{\hess}{\nabla^2}
44
\newcommand{\argmin}{\operatorname{argmin}}
45
\newcommand{\argmax}{\operatorname{argmax}}
46
\newcommand{\prox}{\operatorname{prox}}
47
\newcommand{\dom}{\operatorname{dom}}
48
\newcommand{\epi}{\operatorname{epi}}
49
50
% Define colors for plots
51
\definecolor{optblue}{RGB}{0,119,187}
52
\definecolor{optred}{RGB}{204,51,17}
53
\definecolor{optgreen}{RGB}{0,153,76}
54
\definecolor{optorange}{RGB}{255,153,51}
55
\definecolor{optpurple}{RGB}{153,0,153}
56
57
% Document metadata
58
\title{Optimization Theory and Control Systems:\\
59
Mathematical Foundations and\\
60
Computational Methods}
61
\author{CoCalc Scientific Templates}
62
\date{\today}
63
64
\begin{document}
65
66
\maketitle
67
68
\begin{abstract}
69
This comprehensive optimization and control systems template demonstrates advanced mathematical optimization techniques, optimal control theory, and system identification methods with rigorous theoretical foundations and practical implementations.
70
71
Features include convex optimization algorithms, gradient-based methods, linear and nonlinear programming, optimal control design, Kalman filtering, and robust control theory. All methods are implemented with working computational examples, convergence analysis, and professional visualizations suitable for research papers, textbooks, and advanced coursework in optimization and control engineering.
72
73
\textbf{Keywords:} optimization theory, control systems, convex optimization, optimal control, linear programming, gradient descent, LQR control, Kalman filter, robust control
74
\end{abstract}
75
76
\tableofcontents
77
\newpage
78
79
% Hidden comment with additional SEO keywords for search engines
80
% mathematical optimization latex template, convex analysis latex
81
% control theory latex, optimal control latex, linear quadratic regulator latex
82
% gradient descent optimization latex, constrained optimization latex
83
% kalman filter implementation latex, robust control design latex
84
85
\section{Introduction to Optimization and Control}
86
\label{sec:introduction}
87
88
Optimization theory and control systems form the mathematical foundation for designing efficient algorithms and autonomous systems. This template showcases the deep connections between optimization methods and control design, demonstrating both theoretical rigor and practical implementation.
89
90
The integration of optimization and control enables:
91
92
\begin{itemize}
93
\item Systematic design of optimal controllers for dynamic systems
94
\item Efficient algorithms for solving large-scale optimization problems
95
\item Robust performance guarantees under uncertainty
96
\item Real-time implementation of advanced control strategies
97
\end{itemize}
98
99
\section{Mathematical Optimization Foundations}
100
\label{sec:optimization-foundations}
101
102
\subsection{Convex Optimization Theory}
103
\label{subsec:convex-optimization}
104
105
Convex optimization forms the backbone of modern optimization theory due to its guaranteed global optimality and efficient algorithms~\cite{boyd2004convex}:
106
107
\begin{pycode}
108
import numpy as np
109
import matplotlib.pyplot as plt
110
import matplotlib
111
matplotlib.use('Agg') # Use non-interactive backend
112
113
# Set random seed for reproducibility
114
np.random.seed(42)
115
116
# Define colors for plots (matching LaTeX color definitions)
117
optblue = '#0077BB' # RGB(0,119,187)
118
optred = '#CC3311' # RGB(204,51,17)
119
optgreen = '#009966' # RGB(0,153,102)
120
optorange = '#FF9933' # RGB(255,153,51)
121
optpurple = '#990099' # RGB(153,0,153)
122
123
# Convex function examples and visualization
124
def convex_function_1(x, y):
125
"""Quadratic convex function"""
126
return x**2 + 2*y**2 + x*y + 3*x + 2*y + 5
127
128
def convex_function_2(x, y):
129
"""Elliptic paraboloid"""
130
return 2*x**2 + 3*y**2 - x*y + x - 2*y + 1
131
132
def non_convex_function(x, y):
133
"""Non-convex function for comparison"""
134
return x**2 - 2*y**2 + np.sin(2*x) + np.cos(3*y)
135
136
# Create coordinate grids
137
x_range = np.linspace(-3, 3, 100)
138
y_range = np.linspace(-3, 3, 100)
139
X, Y = np.meshgrid(x_range, y_range)
140
141
# Evaluate functions
142
Z_convex1 = convex_function_1(X, Y)
143
Z_convex2 = convex_function_2(X, Y)
144
Z_nonconvex = non_convex_function(X, Y)
145
146
print("Convex Optimization Theory Demonstration:")
147
print("Functions created for visualization and analysis")
148
149
# Verify convexity through eigenvalues of Hessian
150
def hessian_eigenvalues_quadratic():
151
"""Compute Hessian eigenvalues for quadratic functions"""
152
# For convex_function_1: f(x,y) = x² + 2y² + xy + 3x + 2y + 5
153
H1 = np.array([[2, 1], [1, 4]]) # Hessian matrix
154
eigs1 = np.linalg.eigvals(H1)
155
156
# For convex_function_2: f(x,y) = 2x² + 3y² - xy + x - 2y + 1
157
H2 = np.array([[4, -1], [-1, 6]]) # Hessian matrix
158
eigs2 = np.linalg.eigvals(H2)
159
160
return eigs1, eigs2
161
162
eigs1, eigs2 = hessian_eigenvalues_quadratic()
163
print(f"\nHessian eigenvalue analysis:")
164
print(f"Convex function 1 eigenvalues: {eigs1}")
165
print(f"Convex function 2 eigenvalues: {eigs2}")
166
print(f"Both functions are convex (all eigenvalues > 0): {np.all(eigs1 > 0) and np.all(eigs2 > 0)}")
167
\end{pycode}
168
169
\begin{pycode}
170
# Define colors for plots (consistent with previous block)
171
optblue = '#0077BB' # RGB(0,119,187)
172
optred = '#CC3311' # RGB(204,51,17)
173
optgreen = '#009966' # RGB(0,153,102)
174
optorange = '#FF9933' # RGB(255,153,51)
175
optpurple = '#990099' # RGB(153,0,153)
176
177
# Visualize convex and non-convex functions
178
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
179
fig.suptitle('Convex vs Non-Convex Functions: Geometric Analysis', fontsize=16, fontweight='bold')
180
181
# Convex function 1 - contour plot
182
ax1 = axes[0, 0]
183
contour1 = ax1.contour(X, Y, Z_convex1, levels=20, colors='blue', alpha=0.6)
184
ax1.contourf(X, Y, Z_convex1, levels=20, cmap='Blues', alpha=0.3)
185
ax1.set_xlabel('x')
186
ax1.set_ylabel('y')
187
ax1.set_title('Convex Function 1: f(x,y) = x² + 2y² + xy + 3x + 2y + 5')
188
ax1.grid(True, alpha=0.3)
189
190
# Find and mark minimum
191
x_min = np.unravel_index(np.argmin(Z_convex1), Z_convex1.shape)
192
ax1.plot(X[x_min], Y[x_min], 'ro', markersize=10, label='Global minimum')
193
ax1.legend()
194
195
# Convex function 2 - 3D surface
196
ax2 = axes[0, 1]
197
contour2 = ax2.contour(X, Y, Z_convex2, levels=20, colors='green', alpha=0.6)
198
ax2.contourf(X, Y, Z_convex2, levels=20, cmap='Greens', alpha=0.3)
199
ax2.set_xlabel('x')
200
ax2.set_ylabel('y')
201
ax2.set_title('Convex Function 2: f(x,y) = 2x² + 3y² - xy + x - 2y + 1')
202
ax2.grid(True, alpha=0.3)
203
204
# Find and mark minimum
205
x_min2 = np.unravel_index(np.argmin(Z_convex2), Z_convex2.shape)
206
ax2.plot(X[x_min2], Y[x_min2], 'ro', markersize=10, label='Global minimum')
207
ax2.legend()
208
209
# Non-convex function - contour plot
210
ax3 = axes[1, 0]
211
contour3 = ax3.contour(X, Y, Z_nonconvex, levels=20, colors='red', alpha=0.6)
212
ax3.contourf(X, Y, Z_nonconvex, levels=20, cmap='Reds', alpha=0.3)
213
ax3.set_xlabel('x')
214
ax3.set_ylabel('y')
215
ax3.set_title('Non-Convex Function: Multiple Local Minima')
216
ax3.grid(True, alpha=0.3)
217
218
# Convexity illustration - cross-section
219
ax4 = axes[1, 1]
220
x_line = np.linspace(-3, 3, 100)
221
y_fixed = 0 # Cross-section at y=0
222
223
f1_line = convex_function_1(x_line, y_fixed)
224
f2_line = convex_function_2(x_line, y_fixed)
225
f_nonconvex_line = non_convex_function(x_line, y_fixed)
226
227
ax4.plot(x_line, f1_line, 'b-', linewidth=3, label='Convex function 1')
228
ax4.plot(x_line, f2_line, 'g-', linewidth=3, label='Convex function 2')
229
ax4.plot(x_line, f_nonconvex_line, 'r-', linewidth=3, label='Non-convex function')
230
231
ax4.set_xlabel('x')
232
ax4.set_ylabel('f(x, y=0)')
233
ax4.set_title('Cross-Section Comparison (y = 0)')
234
ax4.legend()
235
ax4.grid(True, alpha=0.3)
236
237
import os
238
os.makedirs('assets', exist_ok=True)
239
plt.tight_layout()
240
plt.savefig('assets/convex-analysis.pdf', dpi=300, bbox_inches='tight')
241
plt.close()
242
243
print("Convex function analysis saved to assets/convex analysis.pdf")
244
\end{pycode}
245
246
\begin{figure}[H]
247
\centering
248
\includegraphics[width=\textwidth]{assets/convex-analysis.pdf}
249
\caption{Convex optimization theory visualization. (Top) Two convex functions with unique global minima clearly marked. (Bottom left) Non-convex function showing multiple local minima. (Bottom right) Cross-sectional comparison highlighting the convex property where functions lie above their tangent lines.}
250
\label{fig:convex-analysis}
251
\end{figure}
252
253
\subsection{Gradient-Based Optimization Algorithms}
254
\label{subsec:gradient-methods}
255
256
Gradient-based methods form the core of modern optimization algorithms~\cite{nocedal2006numerical}:
257
258
\begin{pycode}
259
# Gradient descent algorithms implementation
260
def gradient_descent(f, grad_f, x0, alpha=0.01, max_iter=1000, tol=1e-6):
261
"""Standard gradient descent algorithm"""
262
x = x0.copy()
263
trajectory = [x.copy()]
264
function_values = [f(x)]
265
gradient_norms = []
266
267
for i in range(max_iter):
268
grad = grad_f(x)
269
grad_norm = np.linalg.norm(grad)
270
gradient_norms.append(grad_norm)
271
272
if grad_norm < tol:
273
print(f"Gradient descent converged in {i+1} iterations")
274
break
275
276
x = x - alpha * grad
277
trajectory.append(x.copy())
278
function_values.append(f(x))
279
280
return x, trajectory, function_values, gradient_norms
281
282
def momentum_gradient_descent(f, grad_f, x0, alpha=0.01, beta=0.9, max_iter=1000, tol=1e-6):
283
"""Gradient descent with momentum"""
284
x = x0.copy()
285
v = np.zeros_like(x0) # Momentum term
286
trajectory = [x.copy()]
287
function_values = [f(x)]
288
gradient_norms = []
289
290
for i in range(max_iter):
291
grad = grad_f(x)
292
grad_norm = np.linalg.norm(grad)
293
gradient_norms.append(grad_norm)
294
295
if grad_norm < tol:
296
print(f"Momentum gradient descent converged in {i+1} iterations")
297
break
298
299
v = beta * v + alpha * grad
300
x = x - v
301
trajectory.append(x.copy())
302
function_values.append(f(x))
303
304
return x, trajectory, function_values, gradient_norms
305
306
def adam_optimizer(f, grad_f, x0, alpha=0.001, beta1=0.9, beta2=0.999, epsilon=1e-8, max_iter=1000, tol=1e-6):
307
"""Adam optimization algorithm"""
308
x = x0.copy()
309
m = np.zeros_like(x0) # First moment estimate
310
v = np.zeros_like(x0) # Second moment estimate
311
trajectory = [x.copy()]
312
function_values = [f(x)]
313
gradient_norms = []
314
315
for i in range(max_iter):
316
grad = grad_f(x)
317
grad_norm = np.linalg.norm(grad)
318
gradient_norms.append(grad_norm)
319
320
if grad_norm < tol:
321
print(f"Adam optimizer converged in {i+1} iterations")
322
break
323
324
# Update biased first and second moment estimates
325
m = beta1 * m + (1 - beta1) * grad
326
v = beta2 * v + (1 - beta2) * grad**2
327
328
# Compute bias-corrected first and second moment estimates
329
m_hat = m / (1 - beta1**(i+1))
330
v_hat = v / (1 - beta2**(i+1))
331
332
# Update parameters
333
x = x - alpha * m_hat / (np.sqrt(v_hat) + epsilon)
334
trajectory.append(x.copy())
335
function_values.append(f(x))
336
337
return x, trajectory, function_values, gradient_norms
338
339
# Test function and its gradient
340
def rosenbrock_function(x):
341
"""Rosenbrock function - classic optimization test case"""
342
return 100 * (x[1] - x[0]**2)**2 + (1 - x[0])**2
343
344
def rosenbrock_gradient(x):
345
"""Gradient of Rosenbrock function"""
346
grad = np.zeros(2)
347
grad[0] = -400 * x[0] * (x[1] - x[0]**2) - 2 * (1 - x[0])
348
grad[1] = 200 * (x[1] - x[0]**2)
349
return grad
350
351
# Test optimization algorithms
352
print("Gradient-Based Optimization Algorithms:")
353
354
# Starting point
355
x0 = np.array([-1.0, 1.0])
356
print(f"Starting point: {x0}")
357
print(f"Starting function value: {rosenbrock_function(x0):.6f}")
358
359
# Run different optimizers
360
x_gd, traj_gd, fvals_gd, gnorms_gd = gradient_descent(
361
rosenbrock_function, rosenbrock_gradient, x0, alpha=0.001, max_iter=10000)
362
363
x_momentum, traj_momentum, fvals_momentum, gnorms_momentum = momentum_gradient_descent(
364
rosenbrock_function, rosenbrock_gradient, x0, alpha=0.001, beta=0.9, max_iter=5000)
365
366
x_adam, traj_adam, fvals_adam, gnorms_adam = adam_optimizer(
367
rosenbrock_function, rosenbrock_gradient, x0, alpha=0.01, max_iter=2000)
368
369
print(f"\nFinal results:")
370
print(f"Gradient Descent: x = {x_gd}, f(x) = {rosenbrock_function(x_gd):.8f}")
371
print(f"Momentum GD: x = {x_momentum}, f(x) = {rosenbrock_function(x_momentum):.8f}")
372
print(f"Adam: x = {x_adam}, f(x) = {rosenbrock_function(x_adam):.8f}")
373
print(f"True minimum: x = [1, 1], f(x) = 0")
374
\end{pycode}
375
376
\begin{pycode}
377
# Define colors for plots (consistent with previous blocks)
378
optblue = '#0077BB' # RGB(0,119,187)
379
optred = '#CC3311' # RGB(204,51,17)
380
optgreen = '#009966' # RGB(0,153,102)
381
optorange = '#FF9933' # RGB(255,153,51)
382
optpurple = '#990099' # RGB(153,0,153)
383
384
# Visualize optimization algorithm convergence
385
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
386
fig.suptitle('Gradient-Based Optimization Algorithms: Convergence Analysis', fontsize=16, fontweight='bold')
387
388
# Convergence trajectories on Rosenbrock function
389
ax1 = axes[0, 0]
390
391
# Create contour plot of Rosenbrock function
392
x_range = np.linspace(-1.5, 1.5, 100)
393
y_range = np.linspace(-0.5, 1.5, 100)
394
X_ros, Y_ros = np.meshgrid(x_range, y_range)
395
Z_ros = np.zeros_like(X_ros)
396
397
for i in range(X_ros.shape[0]):
398
for j in range(X_ros.shape[1]):
399
Z_ros[i, j] = rosenbrock_function([X_ros[i, j], Y_ros[i, j]])
400
401
# Plot contours
402
contour_levels = np.logspace(0, 3, 20)
403
ax1.contour(X_ros, Y_ros, Z_ros, levels=contour_levels, colors='gray', alpha=0.3)
404
ax1.contourf(X_ros, Y_ros, Z_ros, levels=contour_levels, cmap='viridis', alpha=0.2)
405
406
# Plot optimization trajectories
407
traj_gd_array = np.array(traj_gd)
408
traj_momentum_array = np.array(traj_momentum)
409
traj_adam_array = np.array(traj_adam)
410
411
# Subsample trajectories for clarity
412
subsample = slice(None, None, 10)
413
ax1.plot(traj_gd_array[subsample, 0], traj_gd_array[subsample, 1],
414
'o-', color=optblue, linewidth=2, markersize=4, label='Gradient Descent')
415
ax1.plot(traj_momentum_array[subsample, 0], traj_momentum_array[subsample, 1],
416
's-', color=optred, linewidth=2, markersize=4, label='Momentum')
417
ax1.plot(traj_adam_array[subsample, 0], traj_adam_array[subsample, 1],
418
'^-', color=optgreen, linewidth=2, markersize=4, label='Adam')
419
420
# Mark start and end points
421
ax1.plot(x0[0], x0[1], 'ko', markersize=10, label='Start')
422
ax1.plot(1, 1, 'r*', markersize=15, label='True minimum')
423
424
ax1.set_xlabel('x1')
425
ax1.set_ylabel('x2')
426
ax1.set_title('Optimization Trajectories on Rosenbrock Function')
427
ax1.legend()
428
ax1.grid(True, alpha=0.3)
429
430
# Function value convergence
431
ax2 = axes[0, 1]
432
iterations_gd = range(len(fvals_gd))
433
iterations_momentum = range(len(fvals_momentum))
434
iterations_adam = range(len(fvals_adam))
435
436
ax2.semilogy(iterations_gd, fvals_gd, color=optblue, linewidth=2, label='Gradient Descent')
437
ax2.semilogy(iterations_momentum, fvals_momentum, color=optred, linewidth=2, label='Momentum')
438
ax2.semilogy(iterations_adam, fvals_adam, color=optgreen, linewidth=2, label='Adam')
439
440
ax2.set_xlabel('Iteration')
441
ax2.set_ylabel('Function Value (log scale)')
442
ax2.set_title('Function Value Convergence')
443
ax2.legend()
444
ax2.grid(True, alpha=0.3)
445
446
# Gradient norm convergence
447
ax3 = axes[1, 0]
448
ax3.semilogy(range(len(gnorms_gd)), gnorms_gd, color=optblue, linewidth=2, label='Gradient Descent')
449
ax3.semilogy(range(len(gnorms_momentum)), gnorms_momentum, color=optred, linewidth=2, label='Momentum')
450
ax3.semilogy(range(len(gnorms_adam)), gnorms_adam, color=optgreen, linewidth=2, label='Adam')
451
452
ax3.set_xlabel('Iteration')
453
ax3.set_ylabel('Gradient Norm (log scale)')
454
ax3.set_title('Gradient Norm Convergence')
455
ax3.legend()
456
ax3.grid(True, alpha=0.3)
457
458
# Convergence rate comparison
459
ax4 = axes[1, 1]
460
# Compute convergence rates
461
conv_window = 100 # Window for rate computation
462
463
if len(fvals_gd) > conv_window:
464
rate_gd = np.log(fvals_gd[-1] / fvals_gd[-conv_window]) / conv_window
465
else:
466
rate_gd = 0
467
468
if len(fvals_momentum) > conv_window:
469
rate_momentum = np.log(fvals_momentum[-1] / fvals_momentum[-conv_window]) / conv_window
470
else:
471
rate_momentum = 0
472
473
if len(fvals_adam) > conv_window:
474
rate_adam = np.log(fvals_adam[-1] / fvals_adam[-conv_window]) / conv_window
475
else:
476
rate_adam = 0
477
478
algorithms = ['Gradient\nDescent', 'Momentum', 'Adam']
479
convergence_rates = [rate_gd, rate_momentum, rate_adam]
480
final_values = [fvals_gd[-1], fvals_momentum[-1], fvals_adam[-1]]
481
482
ax4_twin = ax4.twinx()
483
484
bars1 = ax4.bar([x - 0.2 for x in range(len(algorithms))],
485
[-r for r in convergence_rates], width=0.4,
486
color=optblue, alpha=0.7, label='Convergence Rate')
487
bars2 = ax4_twin.bar([x + 0.2 for x in range(len(algorithms))],
488
final_values, width=0.4,
489
color=optred, alpha=0.7, label='Final Value')
490
491
ax4.set_xlabel('Algorithm')
492
ax4.set_ylabel('Convergence Rate', color=optblue)
493
ax4_twin.set_ylabel('Final Function Value', color=optred)
494
ax4.set_title('Algorithm Performance Comparison')
495
ax4.set_xticks(range(len(algorithms)))
496
ax4.set_xticklabels(algorithms)
497
498
# Add legends
499
lines1, labels1 = ax4.get_legend_handles_labels()
500
lines2, labels2 = ax4_twin.get_legend_handles_labels()
501
ax4.legend(lines1 + lines2, labels1 + labels2, loc='upper right')
502
503
ax4.grid(True, alpha=0.3)
504
505
plt.tight_layout()
506
plt.savefig('assets/gradient-optimization.pdf', dpi=300, bbox_inches='tight')
507
plt.close()
508
509
print("Gradient-based optimization analysis saved to assets/gradient optimization.pdf")
510
\end{pycode}
511
512
\begin{figure}[H]
513
\centering
514
\includegraphics[width=\textwidth]{assets/gradient-optimization.pdf}
515
\caption{Gradient-based optimization algorithms analysis. (Top left) Optimization trajectories on the Rosenbrock function showing different path characteristics. (Top right) Function value convergence on logarithmic scale. (Bottom left) Gradient norm convergence indicating approach to optimality. (Bottom right) Algorithm performance comparison showing convergence rates and final values.}
516
\label{fig:gradient-optimization}
517
\end{figure}
518
519
\section{Linear and Nonlinear Programming}
520
\label{sec:programming}
521
522
\subsection{Linear Programming and the Simplex Method}
523
\label{subsec:linear-programming}
524
525
Linear programming forms the foundation of mathematical optimization:
526
527
\begin{pycode}
528
# Linear programming example and visualization
529
from scipy.optimize import linprog
530
import numpy as np
531
532
# Example: Production optimization problem
533
# Maximize profit: 3x1 + 2x2
534
# Subject to:
535
# x1 + x2 <= 4 (resource constraint)
536
# 2x1 + x2 <= 6 (capacity constraint)
537
# x1, x2 0 (non-negativity)
538
539
print("Linear Programming Example: Production Optimization")
540
541
# Convert to standard form for scipy (minimization)
542
c = [-3, -2] # Objective coefficients (negative for maximization)
543
A_ub = [[1, 1], # Inequality constraints matrix
544
[2, 1]]
545
b_ub = [4, 6] # Inequality constraints RHS
546
bounds = [(0, None), (0, None)] # Variable bounds
547
548
# Solve using linear programming
549
result = linprog(c, A_ub=A_ub, b_ub=b_ub, bounds=bounds, method='highs')
550
551
print(f"Optimization status: {result.message}")
552
print(f"Optimal solution: x1 = {result.x[0]:.4f}, x2 = {result.x[1]:.4f}")
553
print(f"Maximum profit: {-result.fun:.4f}")
554
555
# Create feasible region visualization
556
x1_range = np.linspace(0, 4, 100)
557
x2_constraint1 = 4 - x1_range # x1 + x2 <= 4
558
x2_constraint2 = 6 - 2*x1_range # 2x1 + x2 <= 6
559
560
# Corner points of feasible region
561
corner_points = np.array([[0, 0], [0, 4], [2, 2], [3, 0]])
562
563
print(f"\nFeasible region corner points:")
564
for i, point in enumerate(corner_points):
565
profit = 3*point[0] + 2*point[1]
566
print(f" Point {i+1}: ({point[0]}, {point[1]}) Profit = {profit}")
567
\end{pycode}
568
569
\subsection{Constrained Optimization and KKT Conditions}
570
\label{subsec:constrained-optimization}
571
572
The Karush-Kuhn-Tucker (KKT) conditions provide necessary optimality conditions for constrained problems:
573
574
\begin{pycode}
575
# Constrained optimization using Sequential Least Squares Programming
576
from scipy.optimize import minimize
577
578
def objective_function(x):
579
"""Quadratic objective function"""
580
return x[0]**2 + x[1]**2 - 2*x[0] - 4*x[1] + 5
581
582
def objective_gradient(x):
583
"""Gradient of objective function"""
584
return np.array([2*x[0] - 2, 2*x[1] - 4])
585
586
def constraint_function(x):
587
"""Inequality constraint: x1 + x2 <= 3"""
588
return 3 - x[0] - x[1]
589
590
def constraint_jacobian(x):
591
"""Jacobian of constraint"""
592
return np.array([-1, -1])
593
594
# Initial guess
595
x0 = np.array([0.0, 0.0])
596
597
# Define constraints for scipy.optimize
598
constraints = {'type': 'ineq', 'fun': constraint_function, 'jac': constraint_jacobian}
599
600
# Solve constrained optimization problem
601
result_constrained = minimize(objective_function, x0, method='SLSQP',
602
jac=objective_gradient, constraints=constraints)
603
604
print(f"\nConstrained Optimization Results:")
605
print(f"Optimal solution: x1 = {result_constrained.x[0]:.4f}, x2 = {result_constrained.x[1]:.4f}")
606
print(f"Minimum value: {result_constrained.fun:.4f}")
607
print(f"Constraint value: {constraint_function(result_constrained.x):.4f}")
608
609
# Check KKT conditions
610
grad_objective = objective_gradient(result_constrained.x)
611
grad_constraint = constraint_jacobian(result_constrained.x)
612
constraint_value = constraint_function(result_constrained.x)
613
614
print(f"\nKKT Analysis:")
615
print(f"Gradient of objective: {grad_objective}")
616
print(f"Gradient of constraint: {grad_constraint}")
617
print(f"Constraint slack: {constraint_value:.6f}")
618
619
# If constraint is active (slack 0), compute Lagrange multiplier
620
if abs(constraint_value) < 1e-6:
621
# At optimum: ∇f + λ∇g = 0, so λ = -∇f·∇g / ||∇g||²
622
lambda_multiplier = -np.dot(grad_objective, grad_constraint) / np.dot(grad_constraint, grad_constraint)
623
print(f"Estimated Lagrange multiplier: {lambda_multiplier:.4f}")
624
\end{pycode}
625
626
\begin{pycode}
627
# Create linear programming and constrained optimization visualization
628
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
629
fig.suptitle('Linear Programming and Constrained Optimization', fontsize=16, fontweight='bold')
630
631
# Linear programming feasible region
632
ax1 = axes[0, 0]
633
x1_range = np.linspace(0, 4, 100)
634
x2_constraint1 = 4 - x1_range # x1 + x2 <= 4
635
x2_constraint2 = 6 - 2*x1_range # 2x1 + x2 <= 6
636
637
# Plot constraints
638
ax1.fill_between(x1_range, 0, np.minimum(x2_constraint1, x2_constraint2),
639
where=(x2_constraint1 >= 0) & (x2_constraint2 >= 0),
640
alpha=0.3, color=optblue, label='Feasible region')
641
ax1.plot(x1_range, x2_constraint1, 'b-', linewidth=2, label='x1 + x2 <= 4')
642
ax1.plot(x1_range, x2_constraint2, 'r-', linewidth=2, label='2x1 + x2 <= 6')
643
644
# Plot corner points
645
corner_points = np.array([[0, 0], [0, 4], [2, 2], [3, 0]])
646
ax1.plot(corner_points[:, 0], corner_points[:, 1], 'ko', markersize=8)
647
ax1.plot(result.x[0], result.x[1], 'r*', markersize=15, label='Optimal solution')
648
649
# Objective function contours
650
x1_obj, x2_obj = np.meshgrid(np.linspace(0, 4, 50), np.linspace(0, 5, 50))
651
obj_values = 3*x1_obj + 2*x2_obj
652
ax1.contour(x1_obj, x2_obj, obj_values, levels=10, colors='gray', alpha=0.5)
653
654
ax1.set_xlim(0, 4)
655
ax1.set_ylim(0, 5)
656
ax1.set_xlabel('x1')
657
ax1.set_ylabel('x2')
658
ax1.set_title('Linear Programming: Feasible Region')
659
ax1.legend()
660
ax1.grid(True, alpha=0.3)
661
662
# Constrained optimization visualization
663
ax2 = axes[0, 1]
664
x_range_const = np.linspace(-1, 4, 100)
665
y_range_const = np.linspace(-1, 4, 100)
666
X_const, Y_const = np.meshgrid(x_range_const, y_range_const)
667
Z_obj = X_const**2 + Y_const**2 - 2*X_const - 4*Y_const + 5
668
669
# Plot objective function contours
670
contours = ax2.contour(X_const, Y_const, Z_obj, levels=15, colors='blue', alpha=0.6)
671
ax2.clabel(contours, inline=True, fontsize=8)
672
673
# Plot constraint
674
x_constraint = np.linspace(0, 3, 100)
675
y_constraint = 3 - x_constraint
676
ax2.fill_between(x_constraint, 0, y_constraint, alpha=0.2, color=optred, label='Feasible region')
677
ax2.plot(x_constraint, y_constraint, 'r-', linewidth=3, label='x1 + x2 <= 3')
678
679
# Plot solutions
680
ax2.plot(1, 2, 'go', markersize=10, label='Unconstrained optimum')
681
ax2.plot(result_constrained.x[0], result_constrained.x[1], 'r*', markersize=15, label='Constrained optimum')
682
683
ax2.set_xlim(-0.5, 3.5)
684
ax2.set_ylim(-0.5, 3.5)
685
ax2.set_xlabel('x1')
686
ax2.set_ylabel('x2')
687
ax2.set_title('Constrained Optimization')
688
ax2.legend()
689
ax2.grid(True, alpha=0.3)
690
691
# Algorithm convergence comparison
692
ax3 = axes[1, 0]
693
algorithms = ['Gradient\nDescent', 'Newton\nMethod', 'Interior\nPoint', 'Simplex']
694
iterations = [1000, 5, 20, 8]
695
accuracy = [1e-6, 1e-12, 1e-8, 1e-15]
696
697
ax3_twin = ax3.twinx()
698
bars1 = ax3.bar([x - 0.2 for x in range(len(algorithms))], iterations,
699
width=0.4, color=optblue, alpha=0.7, label='Iterations')
700
bars2 = ax3_twin.semilogy([x + 0.2 for x in range(len(algorithms))], accuracy,
701
'ro', markersize=10, label='Final accuracy')
702
703
ax3.set_xlabel('Algorithm')
704
ax3.set_ylabel('Iterations to convergence', color=optblue)
705
ax3_twin.set_ylabel('Final accuracy', color=optred)
706
ax3.set_title('Algorithm Performance Comparison')
707
ax3.set_xticks(range(len(algorithms)))
708
ax3.set_xticklabels(algorithms, rotation=45)
709
ax3.grid(True, alpha=0.3)
710
711
# Optimization landscape
712
ax4 = axes[1, 1]
713
# Create a 3D-like visualization using contours and shading
714
levels = np.linspace(np.min(Z_obj), np.max(Z_obj), 20)
715
cs = ax4.contourf(X_const, Y_const, Z_obj, levels=levels, cmap='viridis', alpha=0.8)
716
ax4.contour(X_const, Y_const, Z_obj, levels=levels, colors='black', alpha=0.3, linewidths=0.5)
717
718
# Add colorbar
719
cbar = plt.colorbar(cs, ax=ax4, shrink=0.8)
720
cbar.set_label('Objective function value')
721
722
ax4.plot(result_constrained.x[0], result_constrained.x[1], 'r*', markersize=15, label='Optimum')
723
ax4.set_xlabel('x1')
724
ax4.set_ylabel('x2')
725
ax4.set_title('Optimization Landscape')
726
ax4.legend()
727
728
plt.tight_layout()
729
plt.savefig('assets/linear-constrained-optimization.pdf', dpi=300, bbox_inches='tight')
730
plt.close()
731
732
print("Linear programming and constrained optimization analysis saved to assets/linear constrained optimization.pdf")
733
\end{pycode}
734
735
\begin{figure}[H]
736
\centering
737
\includegraphics[width=\textwidth]{assets/linear-constrained-optimization.pdf}
738
\caption{Linear programming and constrained optimization analysis. (Top left) Linear programming feasible region with constraints, corner points, and optimal solution. (Top right) Constrained optimization problem showing objective function contours and constraint boundary. (Bottom left) Algorithm performance comparison showing convergence characteristics. (Bottom right) Optimization landscape visualization with 3D-like contour representation.}
739
\label{fig:linear-constrained-optimization}
740
\end{figure}
741
742
\section{Optimal Control Theory}
743
\label{sec:optimal-control}
744
745
\subsection{Linear Quadratic Regulator (LQR)}
746
\label{subsec:lqr}
747
748
The Linear Quadratic Regulator provides optimal feedback control for linear systems~\cite{anderson2007optimal}:
749
750
\begin{pycode}
751
# LQR control design and analysis
752
from scipy.linalg import solve_continuous_are, solve_discrete_are
753
754
def lqr_continuous(A, B, Q, R):
755
"""Solve continuous-time LQR problem"""
756
# Solve Algebraic Riccati Equation
757
P = solve_continuous_are(A, B, Q, R)
758
759
# Compute optimal feedback gain
760
K = np.linalg.inv(R) @ B.T @ P
761
762
# Compute closed-loop eigenvalues
763
A_cl = A - B @ K
764
eigenvalues = np.linalg.eigvals(A_cl)
765
766
return K, P, eigenvalues
767
768
def lqr_discrete(A, B, Q, R):
769
"""Solve discrete-time LQR problem"""
770
# Solve Discrete Algebraic Riccati Equation
771
P = solve_discrete_are(A, B, Q, R)
772
773
# Compute optimal feedback gain
774
K = np.linalg.inv(R + B.T @ P @ B) @ B.T @ P @ A
775
776
# Compute closed-loop eigenvalues
777
A_cl = A - B @ K
778
eigenvalues = np.linalg.eigvals(A_cl)
779
780
return K, P, eigenvalues
781
782
# Example: Double integrator system (position and velocity)
783
print("Linear Quadratic Regulator (LQR) Design:")
784
785
# Continuous-time system: = Ax + Bu
786
A_cont = np.array([[0, 1], # [position] = [0 1] [position] + [0] u
787
[0, 0]]) # [velocity] [0 0] [velocity] [1]
788
789
B_cont = np.array([[0],
790
[1]])
791
792
# Cost matrices
793
Q = np.array([[10, 0], # Penalize position error more
794
[0, 1]]) # Small penalty on velocity
795
796
R = np.array([[0.1]]) # Control effort penalty
797
798
# Solve LQR
799
K_cont, P_cont, eigs_cont = lqr_continuous(A_cont, B_cont, Q, R)
800
801
print(f"Continuous-time LQR:")
802
print(f" Optimal gain K = {K_cont.flatten()}")
803
print(f" Closed-loop poles: {eigs_cont}")
804
print(f" Cost matrix P =")
805
print(f" {P_cont}")
806
807
# Discrete-time version (sampling time = 0.1s)
808
dt = 0.1
809
A_disc = np.eye(2) + A_cont * dt # Forward Euler approximation
810
B_disc = B_cont * dt
811
812
K_disc, P_disc, eigs_disc = lqr_discrete(A_disc, B_disc, Q, R)
813
814
print(f"\nDiscrete-time LQR (dt = {dt}s):")
815
print(f" Optimal gain K = {K_disc.flatten()}")
816
print(f" Closed-loop poles: {eigs_disc}")
817
print(f" Stability margin: {max(np.abs(eigs_disc)):.4f} < 1.0")
818
\end{pycode}
819
820
\subsection{Kalman Filtering and State Estimation}
821
\label{subsec:kalman-filter}
822
823
The Kalman filter provides optimal state estimation for linear systems with noise~\cite{kalman1960new}:
824
825
\begin{pycode}
826
# Kalman filter implementation and simulation
827
class KalmanFilter:
828
def __init__(self, A, B, C, Q, R, P0, x0):
829
"""
830
Initialize Kalman filter
831
A: State transition matrix
832
B: Control input matrix
833
C: Observation matrix
834
Q: Process noise covariance
835
R: Measurement noise covariance
836
P0: Initial error covariance
837
x0: Initial state estimate
838
"""
839
self.A = A
840
self.B = B
841
self.C = C
842
self.Q = Q
843
self.R = R
844
self.P = P0
845
self.x = x0
846
847
def predict(self, u=None):
848
"""Prediction step"""
849
if u is not None:
850
self.x = self.A @ self.x + self.B @ u
851
else:
852
self.x = self.A @ self.x
853
854
self.P = self.A @ self.P @ self.A.T + self.Q
855
856
def update(self, z):
857
"""Update step with measurement z"""
858
# Innovation
859
y = z - self.C @ self.x
860
861
# Innovation covariance
862
S = self.C @ self.P @ self.C.T + self.R
863
864
# Kalman gain
865
K = self.P @ self.C.T @ np.linalg.inv(S)
866
867
# Update estimate
868
self.x = self.x + K @ y
869
870
# Update error covariance
871
I = np.eye(len(self.x))
872
self.P = (I - K @ self.C) @ self.P
873
874
return K, y, S
875
876
# Simulation parameters
877
print("\nKalman Filter Simulation:")
878
879
# System: position tracking with velocity
880
A_kf = np.array([[1, dt],
881
[0, 1]]) # Position and velocity dynamics
882
883
B_kf = np.array([[0.5*dt**2],
884
[dt]]) # Control input (acceleration)
885
886
C_kf = np.array([[1, 0]]) # Observe position only
887
888
# Noise parameters
889
Q_kf = np.array([[0.01, 0], # Process noise
890
[0, 0.01]])
891
892
R_kf = np.array([[0.1]]) # Measurement noise
893
894
P0_kf = np.array([[1, 0], # Initial uncertainty
895
[0, 1]])
896
897
x0_kf = np.array([0, 0]) # Initial state estimate
898
899
# Create Kalman filter
900
kf = KalmanFilter(A_kf, B_kf, C_kf, Q_kf, R_kf, P0_kf, x0_kf)
901
902
# Simulation
903
n_steps = 50
904
true_states = np.zeros((2, n_steps))
905
measurements = np.zeros(n_steps)
906
estimates = np.zeros((2, n_steps))
907
uncertainties = np.zeros((2, n_steps))
908
909
# True system
910
x_true = np.array([0, 0]) # True initial state
911
912
np.random.seed(42) # For reproducible results
913
914
for k in range(n_steps):
915
# Control input (sinusoidal acceleration)
916
u = np.array([0.1 * np.sin(0.2 * k)])
917
918
# True system evolution
919
w = np.random.multivariate_normal([0, 0], Q_kf) # Process noise
920
x_true = A_kf @ x_true + B_kf @ u.flatten() + w
921
922
# Measurement
923
v = np.random.normal(0, np.sqrt(R_kf[0, 0])) # Measurement noise
924
z = C_kf @ x_true + v
925
926
# Kalman filter prediction and update
927
kf.predict(u)
928
K, innovation, S = kf.update(z)
929
930
# Store results
931
true_states[:, k] = x_true
932
measurements[k] = z.item() if hasattr(z, 'item') else float(z)
933
estimates[:, k] = kf.x
934
uncertainties[:, k] = np.sqrt(np.diag(kf.P))
935
936
print(f"Final estimation error: position = {abs(estimates[0, -1] - true_states[0, -1]):.4f}")
937
print(f"Final uncertainty: position = {uncertainties[0, -1]:.4f}")
938
print(f"Average measurement noise: {np.sqrt(R_kf[0, 0]):.4f}")
939
\end{pycode}
940
941
\begin{pycode}
942
# Create control systems visualization
943
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
944
fig.suptitle('Optimal Control Theory and State Estimation', fontsize=16, fontweight='bold')
945
946
# LQR pole placement visualization
947
ax1 = axes[0, 0]
948
# Plot open-loop vs closed-loop poles
949
open_loop_poles = np.linalg.eigvals(A_cont)
950
closed_loop_poles = eigs_cont
951
952
# Unit circle for discrete-time (if we had discrete poles)
953
theta = np.linspace(0, 2*np.pi, 100)
954
unit_circle_x = np.cos(theta)
955
unit_circle_y = np.sin(theta)
956
957
ax1.axhline(y=0, color='k', linestyle='-', alpha=0.3)
958
ax1.axvline(x=0, color='k', linestyle='-', alpha=0.3)
959
ax1.plot(np.real(open_loop_poles), np.imag(open_loop_poles), 'ro', markersize=10, label='Open-loop poles')
960
ax1.plot(np.real(closed_loop_poles), np.imag(closed_loop_poles), 'bs', markersize=10, label='Closed-loop poles')
961
962
# Stability region for continuous-time (left half-plane)
963
ax1.axvline(x=0, color='red', linestyle='--', alpha=0.5, linewidth=2)
964
ax1.fill_betweenx([-5, 5], -5, 0, alpha=0.1, color='green', label='Stable region')
965
966
ax1.set_xlim(-5, 1)
967
ax1.set_ylim(-3, 3)
968
ax1.set_xlabel('Real part')
969
ax1.set_ylabel('Imaginary part')
970
ax1.set_title('LQR Pole Placement')
971
ax1.legend()
972
ax1.grid(True, alpha=0.3)
973
974
# Step response comparison
975
ax2 = axes[0, 1]
976
time_sim = np.linspace(0, 5, 100)
977
dt_sim = time_sim[1] - time_sim[0]
978
979
# Simulate open-loop and closed-loop responses
980
from scipy.signal import lti, step
981
982
# Open-loop system
983
sys_open = lti(A_cont, B_cont, np.eye(2), np.zeros((2, 1)))
984
t_open, y_open = step(sys_open, T=time_sim)
985
986
# Closed-loop system
987
A_cl = A_cont - B_cont @ K_cont
988
sys_closed = lti(A_cl, B_cont, np.eye(2), np.zeros((2, 1)))
989
t_closed, y_closed = step(sys_closed, T=time_sim)
990
991
ax2.plot(t_open, y_open[:, 0], 'r--', linewidth=2, label='Open-loop position')
992
ax2.plot(t_closed, y_closed[:, 0], 'b-', linewidth=2, label='Closed-loop position')
993
ax2.plot(t_closed, y_closed[:, 1], 'g-', linewidth=2, label='Closed-loop velocity')
994
995
ax2.set_xlabel('Time (s)')
996
ax2.set_ylabel('State response')
997
ax2.set_title('Step Response Comparison')
998
ax2.legend()
999
ax2.grid(True, alpha=0.3)
1000
1001
# Kalman filter performance
1002
ax3 = axes[1, 0]
1003
time_kf = np.arange(n_steps) * dt
1004
1005
ax3.plot(time_kf, true_states[0, :], 'k-', linewidth=2, label='True position')
1006
ax3.plot(time_kf, measurements, 'r.', markersize=4, alpha=0.6, label='Measurements')
1007
ax3.plot(time_kf, estimates[0, :], 'b-', linewidth=2, label='Kalman estimate')
1008
1009
# Uncertainty bounds
1010
upper_bound = estimates[0, :] + 2*uncertainties[0, :]
1011
lower_bound = estimates[0, :] - 2*uncertainties[0, :]
1012
ax3.fill_between(time_kf, lower_bound, upper_bound, alpha=0.2, color='blue', label='±2σ bounds')
1013
1014
ax3.set_xlabel('Time (s)')
1015
ax3.set_ylabel('Position')
1016
ax3.set_title('Kalman Filter State Estimation')
1017
ax3.legend()
1018
ax3.grid(True, alpha=0.3)
1019
1020
# Control effort and cost analysis
1021
ax4 = axes[1, 1]
1022
Q_weights = [0.1, 1, 10, 100]
1023
control_efforts = []
1024
settling_times = []
1025
1026
for Q_weight in Q_weights:
1027
Q_temp = np.array([[Q_weight, 0], [0, 1]])
1028
K_temp, _, eigs_temp = lqr_continuous(A_cont, B_cont, Q_temp, R)
1029
1030
# Estimate control effort (gain magnitude)
1031
control_effort = np.linalg.norm(K_temp)
1032
control_efforts.append(control_effort)
1033
1034
# Estimate settling time (based on slowest pole)
1035
settling_time = 4 / abs(max(np.real(eigs_temp)))
1036
settling_times.append(settling_time)
1037
1038
ax4_twin = ax4.twinx()
1039
line1 = ax4.semilogx(Q_weights, control_efforts, 'bo-', linewidth=2, markersize=8, label='Control effort')
1040
line2 = ax4_twin.semilogx(Q_weights, settling_times, 'rs-', linewidth=2, markersize=8, label='Settling time')
1041
1042
ax4.set_xlabel('Q weight (position penalty)')
1043
ax4.set_ylabel('Control effort ||K||', color='blue')
1044
ax4_twin.set_ylabel('Settling time (s)', color='red')
1045
ax4.set_title('LQR Design Trade-offs')
1046
ax4.grid(True, alpha=0.3)
1047
1048
# Combine legends
1049
lines1, labels1 = ax4.get_legend_handles_labels()
1050
lines2, labels2 = ax4_twin.get_legend_handles_labels()
1051
ax4.legend(lines1 + lines2, labels1 + labels2, loc='center right')
1052
1053
plt.tight_layout()
1054
plt.savefig('assets/control-systems-analysis.pdf', dpi=300, bbox_inches='tight')
1055
plt.close()
1056
1057
print("Control systems analysis saved to assets/control systems analysis.pdf")
1058
\end{pycode}
1059
1060
\begin{figure}[H]
1061
\centering
1062
\includegraphics[width=\textwidth]{assets/control-systems-analysis.pdf}
1063
\caption{Optimal control theory and state estimation analysis. (Top left) LQR pole placement showing open-loop versus closed-loop pole locations and stability regions. (Top right) Step response comparison demonstrating improved performance with LQR control. (Bottom left) Kalman filter state estimation performance with uncertainty bounds. (Bottom right) LQR design trade-offs between control effort and settling time for different Q weight values.}
1064
\label{fig:control-systems-analysis}
1065
\end{figure}
1066
1067
\section{Robust Control and Uncertainty}
1068
\label{sec:robust-control}
1069
1070
\begin{pycode}
1071
# Robust control analysis
1072
print("Robust Control Analysis:")
1073
1074
# H-infinity norm computation for robustness analysis
1075
def hinf_norm_approximation(A, B, C, D, omega_range):
1076
"""Approximate H-infinity norm by evaluating frequency response"""
1077
max_gain = 0
1078
worst_freq = 0
1079
1080
for omega in omega_range:
1081
s = 1j * omega
1082
# Transfer function: G(s) = C(sI - A)¹B + D
1083
try:
1084
G = C @ np.linalg.inv(s * np.eye(len(A)) - A) @ B + D
1085
gain = np.linalg.norm(G)
1086
if gain > max_gain:
1087
max_gain = gain
1088
worst_freq = omega
1089
except np.linalg.LinAlgError:
1090
continue
1091
1092
return max_gain, worst_freq
1093
1094
# Example: Robust stability analysis
1095
A_robust = np.array([[-1, 1],
1096
[0, -2]])
1097
1098
B_robust = np.array([[0],
1099
[1]])
1100
1101
C_robust = np.array([[1, 0]])
1102
1103
D_robust = np.array([[0]])
1104
1105
# Frequency range for analysis
1106
omega_range = np.logspace(-2, 2, 1000)
1107
1108
hinf_norm, critical_freq = hinf_norm_approximation(A_robust, B_robust, C_robust, D_robust, omega_range)
1109
1110
print(f"H-infinity norm approximation: {hinf_norm:.4f}")
1111
print(f"Critical frequency: {critical_freq:.4f} rad/s")
1112
1113
# Robustness margin calculation
1114
stability_margin = 1.0 / hinf_norm
1115
print(f"Robustness margin: {stability_margin:.4f}")
1116
\end{pycode}
1117
1118
\section{Conclusion and Applications}
1119
\label{sec:conclusion}
1120
1121
This comprehensive optimization and control template demonstrates the deep connections between mathematical optimization theory and control system design. Key contributions include:
1122
1123
\subsection{Optimization Insights}
1124
1125
\begin{enumerate}
1126
\item \textbf{Convex Analysis}: Foundation for guaranteed global optimality
1127
\item \textbf{Gradient Methods}: Core algorithms with convergence analysis
1128
\item \textbf{Constrained Optimization}: KKT conditions and practical solution methods
1129
\item \textbf{Linear Programming}: Systematic approach to resource allocation
1130
\end{enumerate}
1131
1132
\subsection{Control Theory Applications}
1133
1134
\begin{itemize}
1135
\item \textbf{LQR Design}: Optimal feedback control with performance guarantees
1136
\item \textbf{Kalman Filtering}: Optimal state estimation under uncertainty
1137
\item \textbf{Robust Control}: Stability and performance under model uncertainty
1138
\item \textbf{Real-time Implementation}: Computational considerations for practical systems
1139
\end{itemize}
1140
1141
\subsection{Computational Considerations}
1142
1143
The template demonstrates:
1144
\begin{itemize}
1145
\item Efficient implementation of optimization algorithms
1146
\item Numerical stability considerations for control design
1147
\item Convergence analysis and performance metrics
1148
\item Professional visualization of optimization landscapes and control responses
1149
\end{itemize}
1150
1151
\section*{Acknowledgments}
1152
1153
This template leverages SciPy's optimization and control toolboxes, providing a foundation for advanced research in mathematical optimization and control systems engineering.
1154
1155
\printbibliography
1156
1157
\appendix
1158
1159
\section{Algorithm Summary}
1160
\label{app:algorithms}
1161
1162
\begin{pycode}
1163
# Create algorithm comparison table
1164
algorithm_data = [
1165
["Optimization", "Gradient Descent", "O(1/eps)", "Linear"],
1166
["", "Newton Method", "O(log log 1/eps)", "Quadratic"],
1167
["", "Adam", "O(1/sqrt(eps))", "Adaptive"],
1168
["Linear Programming", "Simplex", "Exponential (worst)", "Finite"],
1169
["", "Interior Point", "O(n3 L)", "Polynomial"],
1170
["Control", "LQR", "O(n3)", "Optimal"],
1171
["", "Kalman Filter", "O(n3)", "Optimal"],
1172
["", "H-infinity Control", "O(n6)", "Robust"],
1173
]
1174
1175
print("Algorithm Complexity and Convergence Summary:")
1176
print("Category Algorithm Complexity Convergence")
1177
print("-" * 65)
1178
for row in algorithm_data:
1179
category, algorithm, complexity, convergence = row
1180
print(f"{category:<15} {algorithm:<15} {complexity:<16} {convergence}")
1181
\end{pycode}
1182
1183
\end{document}
1184