ubuntu2404
\documentclass[11pt,a4paper]{article}12% Optimization Theory and Control Systems Template3% SEO Keywords: optimization theory latex template, control systems latex,4% mathematical optimization latex5% Additional Keywords: convex optimization latex, optimal control latex,6% linear programming latex7% Long-tail Keywords: gradient descent algorithms latex, LQR control latex,8% kalman filter latex910\usepackage[utf8]{inputenc}11\usepackage[T1]{fontenc}12\usepackage{amsmath,amsfonts,amssymb}13\usepackage{mathtools}14\usepackage{physics} % for mathematical notation15\usepackage{siunitx} % for proper unit handling16\usepackage{graphicx}17\usepackage{float}18\usepackage{subcaption}19\usepackage{hyperref}20\usepackage{cleveref}21\usepackage{booktabs}22\usepackage{array}23\usepackage{xcolor}24\usepackage{algorithm}25\usepackage{algorithmic}2627% PythonTeX for optimization computing28\usepackage{pythontex}2930% Bibliography for optimization references31\usepackage[style=numeric,backend=biber]{biblatex}32\addbibresource{references.bib}3334% Fix SiunitX physics package warning35\AtBeginDocument{\RenewCommandCopy\qty\SI}3637% Custom commands for optimization38\newcommand{\minimize}{\operatorname{minimize}}39\newcommand{\maximize}{\operatorname{maximize}}40\newcommand{\subjectto}{\operatorname{subject\ to}}41% \grad is already defined by physics package as \nabla42\newcommand{\hess}{\nabla^2}43\newcommand{\argmin}{\operatorname{argmin}}44\newcommand{\argmax}{\operatorname{argmax}}45\newcommand{\prox}{\operatorname{prox}}46\newcommand{\dom}{\operatorname{dom}}47\newcommand{\epi}{\operatorname{epi}}4849% Define colors for plots50\definecolor{optblue}{RGB}{0,119,187}51\definecolor{optred}{RGB}{204,51,17}52\definecolor{optgreen}{RGB}{0,153,76}53\definecolor{optorange}{RGB}{255,153,51}54\definecolor{optpurple}{RGB}{153,0,153}5556% Document metadata57\title{Optimization Theory and Control Systems:\\58Mathematical Foundations and\\59Computational Methods}60\author{CoCalc Scientific Templates}61\date{\today}6263\begin{document}6465\maketitle6667\begin{abstract}68This 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.6970Features 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.7172\textbf{Keywords:} optimization theory, control systems, convex optimization, optimal control, linear programming, gradient descent, LQR control, Kalman filter, robust control73\end{abstract}7475\tableofcontents76\newpage7778% Hidden comment with additional SEO keywords for search engines79% mathematical optimization latex template, convex analysis latex80% control theory latex, optimal control latex, linear quadratic regulator latex81% gradient descent optimization latex, constrained optimization latex82% kalman filter implementation latex, robust control design latex8384\section{Introduction to Optimization and Control}85\label{sec:introduction}8687Optimization 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.8889The integration of optimization and control enables:9091\begin{itemize}92\item Systematic design of optimal controllers for dynamic systems93\item Efficient algorithms for solving large-scale optimization problems94\item Robust performance guarantees under uncertainty95\item Real-time implementation of advanced control strategies96\end{itemize}9798\section{Mathematical Optimization Foundations}99\label{sec:optimization-foundations}100101\subsection{Convex Optimization Theory}102\label{subsec:convex-optimization}103104Convex optimization forms the backbone of modern optimization theory due to its guaranteed global optimality and efficient algorithms~\cite{boyd2004convex}:105106\begin{pycode}107import numpy as np108import matplotlib.pyplot as plt109import matplotlib110matplotlib.use('Agg') # Use non-interactive backend111112# Set random seed for reproducibility113np.random.seed(42)114115# Define colors for plots (matching LaTeX color definitions)116optblue = '#0077BB' # RGB(0,119,187)117optred = '#CC3311' # RGB(204,51,17)118optgreen = '#009966' # RGB(0,153,102)119optorange = '#FF9933' # RGB(255,153,51)120optpurple = '#990099' # RGB(153,0,153)121122# Convex function examples and visualization123def convex_function_1(x, y):124"""Quadratic convex function"""125return x**2 + 2*y**2 + x*y + 3*x + 2*y + 5126127def convex_function_2(x, y):128"""Elliptic paraboloid"""129return 2*x**2 + 3*y**2 - x*y + x - 2*y + 1130131def non_convex_function(x, y):132"""Non-convex function for comparison"""133return x**2 - 2*y**2 + np.sin(2*x) + np.cos(3*y)134135# Create coordinate grids136x_range = np.linspace(-3, 3, 100)137y_range = np.linspace(-3, 3, 100)138X, Y = np.meshgrid(x_range, y_range)139140# Evaluate functions141Z_convex1 = convex_function_1(X, Y)142Z_convex2 = convex_function_2(X, Y)143Z_nonconvex = non_convex_function(X, Y)144145print("Convex Optimization Theory Demonstration:")146print("Functions created for visualization and analysis")147148# Verify convexity through eigenvalues of Hessian149def hessian_eigenvalues_quadratic():150"""Compute Hessian eigenvalues for quadratic functions"""151# For convex_function_1: f(x,y) = x² + 2y² + xy + 3x + 2y + 5152H1 = np.array([[2, 1], [1, 4]]) # Hessian matrix153eigs1 = np.linalg.eigvals(H1)154155# For convex_function_2: f(x,y) = 2x² + 3y² - xy + x - 2y + 1156H2 = np.array([[4, -1], [-1, 6]]) # Hessian matrix157eigs2 = np.linalg.eigvals(H2)158159return eigs1, eigs2160161eigs1, eigs2 = hessian_eigenvalues_quadratic()162print(f"\nHessian eigenvalue analysis:")163print(f"Convex function 1 eigenvalues: {eigs1}")164print(f"Convex function 2 eigenvalues: {eigs2}")165print(f"Both functions are convex (all eigenvalues > 0): {np.all(eigs1 > 0) and np.all(eigs2 > 0)}")166\end{pycode}167168\begin{pycode}169# Define colors for plots (consistent with previous block)170optblue = '#0077BB' # RGB(0,119,187)171optred = '#CC3311' # RGB(204,51,17)172optgreen = '#009966' # RGB(0,153,102)173optorange = '#FF9933' # RGB(255,153,51)174optpurple = '#990099' # RGB(153,0,153)175176# Visualize convex and non-convex functions177fig, axes = plt.subplots(2, 2, figsize=(15, 12))178fig.suptitle('Convex vs Non-Convex Functions: Geometric Analysis', fontsize=16, fontweight='bold')179180# Convex function 1 - contour plot181ax1 = axes[0, 0]182contour1 = ax1.contour(X, Y, Z_convex1, levels=20, colors='blue', alpha=0.6)183ax1.contourf(X, Y, Z_convex1, levels=20, cmap='Blues', alpha=0.3)184ax1.set_xlabel('x')185ax1.set_ylabel('y')186ax1.set_title('Convex Function 1: f(x,y) = x² + 2y² + xy + 3x + 2y + 5')187ax1.grid(True, alpha=0.3)188189# Find and mark minimum190x_min = np.unravel_index(np.argmin(Z_convex1), Z_convex1.shape)191ax1.plot(X[x_min], Y[x_min], 'ro', markersize=10, label='Global minimum')192ax1.legend()193194# Convex function 2 - 3D surface195ax2 = axes[0, 1]196contour2 = ax2.contour(X, Y, Z_convex2, levels=20, colors='green', alpha=0.6)197ax2.contourf(X, Y, Z_convex2, levels=20, cmap='Greens', alpha=0.3)198ax2.set_xlabel('x')199ax2.set_ylabel('y')200ax2.set_title('Convex Function 2: f(x,y) = 2x² + 3y² - xy + x - 2y + 1')201ax2.grid(True, alpha=0.3)202203# Find and mark minimum204x_min2 = np.unravel_index(np.argmin(Z_convex2), Z_convex2.shape)205ax2.plot(X[x_min2], Y[x_min2], 'ro', markersize=10, label='Global minimum')206ax2.legend()207208# Non-convex function - contour plot209ax3 = axes[1, 0]210contour3 = ax3.contour(X, Y, Z_nonconvex, levels=20, colors='red', alpha=0.6)211ax3.contourf(X, Y, Z_nonconvex, levels=20, cmap='Reds', alpha=0.3)212ax3.set_xlabel('x')213ax3.set_ylabel('y')214ax3.set_title('Non-Convex Function: Multiple Local Minima')215ax3.grid(True, alpha=0.3)216217# Convexity illustration - cross-section218ax4 = axes[1, 1]219x_line = np.linspace(-3, 3, 100)220y_fixed = 0 # Cross-section at y=0221222f1_line = convex_function_1(x_line, y_fixed)223f2_line = convex_function_2(x_line, y_fixed)224f_nonconvex_line = non_convex_function(x_line, y_fixed)225226ax4.plot(x_line, f1_line, 'b-', linewidth=3, label='Convex function 1')227ax4.plot(x_line, f2_line, 'g-', linewidth=3, label='Convex function 2')228ax4.plot(x_line, f_nonconvex_line, 'r-', linewidth=3, label='Non-convex function')229230ax4.set_xlabel('x')231ax4.set_ylabel('f(x, y=0)')232ax4.set_title('Cross-Section Comparison (y = 0)')233ax4.legend()234ax4.grid(True, alpha=0.3)235236import os237os.makedirs('assets', exist_ok=True)238plt.tight_layout()239plt.savefig('assets/convex-analysis.pdf', dpi=300, bbox_inches='tight')240plt.close()241242print("Convex function analysis saved to assets/convex analysis.pdf")243\end{pycode}244245\begin{figure}[H]246\centering247\includegraphics[width=\textwidth]{assets/convex-analysis.pdf}248\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.}249\label{fig:convex-analysis}250\end{figure}251252\subsection{Gradient-Based Optimization Algorithms}253\label{subsec:gradient-methods}254255Gradient-based methods form the core of modern optimization algorithms~\cite{nocedal2006numerical}:256257\begin{pycode}258# Gradient descent algorithms implementation259def gradient_descent(f, grad_f, x0, alpha=0.01, max_iter=1000, tol=1e-6):260"""Standard gradient descent algorithm"""261x = x0.copy()262trajectory = [x.copy()]263function_values = [f(x)]264gradient_norms = []265266for i in range(max_iter):267grad = grad_f(x)268grad_norm = np.linalg.norm(grad)269gradient_norms.append(grad_norm)270271if grad_norm < tol:272print(f"Gradient descent converged in {i+1} iterations")273break274275x = x - alpha * grad276trajectory.append(x.copy())277function_values.append(f(x))278279return x, trajectory, function_values, gradient_norms280281def momentum_gradient_descent(f, grad_f, x0, alpha=0.01, beta=0.9, max_iter=1000, tol=1e-6):282"""Gradient descent with momentum"""283x = x0.copy()284v = np.zeros_like(x0) # Momentum term285trajectory = [x.copy()]286function_values = [f(x)]287gradient_norms = []288289for i in range(max_iter):290grad = grad_f(x)291grad_norm = np.linalg.norm(grad)292gradient_norms.append(grad_norm)293294if grad_norm < tol:295print(f"Momentum gradient descent converged in {i+1} iterations")296break297298v = beta * v + alpha * grad299x = x - v300trajectory.append(x.copy())301function_values.append(f(x))302303return x, trajectory, function_values, gradient_norms304305def adam_optimizer(f, grad_f, x0, alpha=0.001, beta1=0.9, beta2=0.999, epsilon=1e-8, max_iter=1000, tol=1e-6):306"""Adam optimization algorithm"""307x = x0.copy()308m = np.zeros_like(x0) # First moment estimate309v = np.zeros_like(x0) # Second moment estimate310trajectory = [x.copy()]311function_values = [f(x)]312gradient_norms = []313314for i in range(max_iter):315grad = grad_f(x)316grad_norm = np.linalg.norm(grad)317gradient_norms.append(grad_norm)318319if grad_norm < tol:320print(f"Adam optimizer converged in {i+1} iterations")321break322323# Update biased first and second moment estimates324m = beta1 * m + (1 - beta1) * grad325v = beta2 * v + (1 - beta2) * grad**2326327# Compute bias-corrected first and second moment estimates328m_hat = m / (1 - beta1**(i+1))329v_hat = v / (1 - beta2**(i+1))330331# Update parameters332x = x - alpha * m_hat / (np.sqrt(v_hat) + epsilon)333trajectory.append(x.copy())334function_values.append(f(x))335336return x, trajectory, function_values, gradient_norms337338# Test function and its gradient339def rosenbrock_function(x):340"""Rosenbrock function - classic optimization test case"""341return 100 * (x[1] - x[0]**2)**2 + (1 - x[0])**2342343def rosenbrock_gradient(x):344"""Gradient of Rosenbrock function"""345grad = np.zeros(2)346grad[0] = -400 * x[0] * (x[1] - x[0]**2) - 2 * (1 - x[0])347grad[1] = 200 * (x[1] - x[0]**2)348return grad349350# Test optimization algorithms351print("Gradient-Based Optimization Algorithms:")352353# Starting point354x0 = np.array([-1.0, 1.0])355print(f"Starting point: {x0}")356print(f"Starting function value: {rosenbrock_function(x0):.6f}")357358# Run different optimizers359x_gd, traj_gd, fvals_gd, gnorms_gd = gradient_descent(360rosenbrock_function, rosenbrock_gradient, x0, alpha=0.001, max_iter=10000)361362x_momentum, traj_momentum, fvals_momentum, gnorms_momentum = momentum_gradient_descent(363rosenbrock_function, rosenbrock_gradient, x0, alpha=0.001, beta=0.9, max_iter=5000)364365x_adam, traj_adam, fvals_adam, gnorms_adam = adam_optimizer(366rosenbrock_function, rosenbrock_gradient, x0, alpha=0.01, max_iter=2000)367368print(f"\nFinal results:")369print(f"Gradient Descent: x = {x_gd}, f(x) = {rosenbrock_function(x_gd):.8f}")370print(f"Momentum GD: x = {x_momentum}, f(x) = {rosenbrock_function(x_momentum):.8f}")371print(f"Adam: x = {x_adam}, f(x) = {rosenbrock_function(x_adam):.8f}")372print(f"True minimum: x = [1, 1], f(x) = 0")373\end{pycode}374375\begin{pycode}376# Define colors for plots (consistent with previous blocks)377optblue = '#0077BB' # RGB(0,119,187)378optred = '#CC3311' # RGB(204,51,17)379optgreen = '#009966' # RGB(0,153,102)380optorange = '#FF9933' # RGB(255,153,51)381optpurple = '#990099' # RGB(153,0,153)382383# Visualize optimization algorithm convergence384fig, axes = plt.subplots(2, 2, figsize=(15, 12))385fig.suptitle('Gradient-Based Optimization Algorithms: Convergence Analysis', fontsize=16, fontweight='bold')386387# Convergence trajectories on Rosenbrock function388ax1 = axes[0, 0]389390# Create contour plot of Rosenbrock function391x_range = np.linspace(-1.5, 1.5, 100)392y_range = np.linspace(-0.5, 1.5, 100)393X_ros, Y_ros = np.meshgrid(x_range, y_range)394Z_ros = np.zeros_like(X_ros)395396for i in range(X_ros.shape[0]):397for j in range(X_ros.shape[1]):398Z_ros[i, j] = rosenbrock_function([X_ros[i, j], Y_ros[i, j]])399400# Plot contours401contour_levels = np.logspace(0, 3, 20)402ax1.contour(X_ros, Y_ros, Z_ros, levels=contour_levels, colors='gray', alpha=0.3)403ax1.contourf(X_ros, Y_ros, Z_ros, levels=contour_levels, cmap='viridis', alpha=0.2)404405# Plot optimization trajectories406traj_gd_array = np.array(traj_gd)407traj_momentum_array = np.array(traj_momentum)408traj_adam_array = np.array(traj_adam)409410# Subsample trajectories for clarity411subsample = slice(None, None, 10)412ax1.plot(traj_gd_array[subsample, 0], traj_gd_array[subsample, 1],413'o-', color=optblue, linewidth=2, markersize=4, label='Gradient Descent')414ax1.plot(traj_momentum_array[subsample, 0], traj_momentum_array[subsample, 1],415's-', color=optred, linewidth=2, markersize=4, label='Momentum')416ax1.plot(traj_adam_array[subsample, 0], traj_adam_array[subsample, 1],417'^-', color=optgreen, linewidth=2, markersize=4, label='Adam')418419# Mark start and end points420ax1.plot(x0[0], x0[1], 'ko', markersize=10, label='Start')421ax1.plot(1, 1, 'r*', markersize=15, label='True minimum')422423ax1.set_xlabel('x1')424ax1.set_ylabel('x2')425ax1.set_title('Optimization Trajectories on Rosenbrock Function')426ax1.legend()427ax1.grid(True, alpha=0.3)428429# Function value convergence430ax2 = axes[0, 1]431iterations_gd = range(len(fvals_gd))432iterations_momentum = range(len(fvals_momentum))433iterations_adam = range(len(fvals_adam))434435ax2.semilogy(iterations_gd, fvals_gd, color=optblue, linewidth=2, label='Gradient Descent')436ax2.semilogy(iterations_momentum, fvals_momentum, color=optred, linewidth=2, label='Momentum')437ax2.semilogy(iterations_adam, fvals_adam, color=optgreen, linewidth=2, label='Adam')438439ax2.set_xlabel('Iteration')440ax2.set_ylabel('Function Value (log scale)')441ax2.set_title('Function Value Convergence')442ax2.legend()443ax2.grid(True, alpha=0.3)444445# Gradient norm convergence446ax3 = axes[1, 0]447ax3.semilogy(range(len(gnorms_gd)), gnorms_gd, color=optblue, linewidth=2, label='Gradient Descent')448ax3.semilogy(range(len(gnorms_momentum)), gnorms_momentum, color=optred, linewidth=2, label='Momentum')449ax3.semilogy(range(len(gnorms_adam)), gnorms_adam, color=optgreen, linewidth=2, label='Adam')450451ax3.set_xlabel('Iteration')452ax3.set_ylabel('Gradient Norm (log scale)')453ax3.set_title('Gradient Norm Convergence')454ax3.legend()455ax3.grid(True, alpha=0.3)456457# Convergence rate comparison458ax4 = axes[1, 1]459# Compute convergence rates460conv_window = 100 # Window for rate computation461462if len(fvals_gd) > conv_window:463rate_gd = np.log(fvals_gd[-1] / fvals_gd[-conv_window]) / conv_window464else:465rate_gd = 0466467if len(fvals_momentum) > conv_window:468rate_momentum = np.log(fvals_momentum[-1] / fvals_momentum[-conv_window]) / conv_window469else:470rate_momentum = 0471472if len(fvals_adam) > conv_window:473rate_adam = np.log(fvals_adam[-1] / fvals_adam[-conv_window]) / conv_window474else:475rate_adam = 0476477algorithms = ['Gradient\nDescent', 'Momentum', 'Adam']478convergence_rates = [rate_gd, rate_momentum, rate_adam]479final_values = [fvals_gd[-1], fvals_momentum[-1], fvals_adam[-1]]480481ax4_twin = ax4.twinx()482483bars1 = ax4.bar([x - 0.2 for x in range(len(algorithms))],484[-r for r in convergence_rates], width=0.4,485color=optblue, alpha=0.7, label='Convergence Rate')486bars2 = ax4_twin.bar([x + 0.2 for x in range(len(algorithms))],487final_values, width=0.4,488color=optred, alpha=0.7, label='Final Value')489490ax4.set_xlabel('Algorithm')491ax4.set_ylabel('Convergence Rate', color=optblue)492ax4_twin.set_ylabel('Final Function Value', color=optred)493ax4.set_title('Algorithm Performance Comparison')494ax4.set_xticks(range(len(algorithms)))495ax4.set_xticklabels(algorithms)496497# Add legends498lines1, labels1 = ax4.get_legend_handles_labels()499lines2, labels2 = ax4_twin.get_legend_handles_labels()500ax4.legend(lines1 + lines2, labels1 + labels2, loc='upper right')501502ax4.grid(True, alpha=0.3)503504plt.tight_layout()505plt.savefig('assets/gradient-optimization.pdf', dpi=300, bbox_inches='tight')506plt.close()507508print("Gradient-based optimization analysis saved to assets/gradient optimization.pdf")509\end{pycode}510511\begin{figure}[H]512\centering513\includegraphics[width=\textwidth]{assets/gradient-optimization.pdf}514\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.}515\label{fig:gradient-optimization}516\end{figure}517518\section{Linear and Nonlinear Programming}519\label{sec:programming}520521\subsection{Linear Programming and the Simplex Method}522\label{subsec:linear-programming}523524Linear programming forms the foundation of mathematical optimization:525526\begin{pycode}527# Linear programming example and visualization528from scipy.optimize import linprog529import numpy as np530531# Example: Production optimization problem532# Maximize profit: 3x1 + 2x2533# Subject to:534# x1 + x2 <= 4 (resource constraint)535# 2x1 + x2 <= 6 (capacity constraint)536# x1, x2 ≥ 0 (non-negativity)537538print("Linear Programming Example: Production Optimization")539540# Convert to standard form for scipy (minimization)541c = [-3, -2] # Objective coefficients (negative for maximization)542A_ub = [[1, 1], # Inequality constraints matrix543[2, 1]]544b_ub = [4, 6] # Inequality constraints RHS545bounds = [(0, None), (0, None)] # Variable bounds546547# Solve using linear programming548result = linprog(c, A_ub=A_ub, b_ub=b_ub, bounds=bounds, method='highs')549550print(f"Optimization status: {result.message}")551print(f"Optimal solution: x1 = {result.x[0]:.4f}, x2 = {result.x[1]:.4f}")552print(f"Maximum profit: {-result.fun:.4f}")553554# Create feasible region visualization555x1_range = np.linspace(0, 4, 100)556x2_constraint1 = 4 - x1_range # x1 + x2 <= 4557x2_constraint2 = 6 - 2*x1_range # 2x1 + x2 <= 6558559# Corner points of feasible region560corner_points = np.array([[0, 0], [0, 4], [2, 2], [3, 0]])561562print(f"\nFeasible region corner points:")563for i, point in enumerate(corner_points):564profit = 3*point[0] + 2*point[1]565print(f" Point {i+1}: ({point[0]}, {point[1]}) → Profit = {profit}")566\end{pycode}567568\subsection{Constrained Optimization and KKT Conditions}569\label{subsec:constrained-optimization}570571The Karush-Kuhn-Tucker (KKT) conditions provide necessary optimality conditions for constrained problems:572573\begin{pycode}574# Constrained optimization using Sequential Least Squares Programming575from scipy.optimize import minimize576577def objective_function(x):578"""Quadratic objective function"""579return x[0]**2 + x[1]**2 - 2*x[0] - 4*x[1] + 5580581def objective_gradient(x):582"""Gradient of objective function"""583return np.array([2*x[0] - 2, 2*x[1] - 4])584585def constraint_function(x):586"""Inequality constraint: x1 + x2 <= 3"""587return 3 - x[0] - x[1]588589def constraint_jacobian(x):590"""Jacobian of constraint"""591return np.array([-1, -1])592593# Initial guess594x0 = np.array([0.0, 0.0])595596# Define constraints for scipy.optimize597constraints = {'type': 'ineq', 'fun': constraint_function, 'jac': constraint_jacobian}598599# Solve constrained optimization problem600result_constrained = minimize(objective_function, x0, method='SLSQP',601jac=objective_gradient, constraints=constraints)602603print(f"\nConstrained Optimization Results:")604print(f"Optimal solution: x1 = {result_constrained.x[0]:.4f}, x2 = {result_constrained.x[1]:.4f}")605print(f"Minimum value: {result_constrained.fun:.4f}")606print(f"Constraint value: {constraint_function(result_constrained.x):.4f}")607608# Check KKT conditions609grad_objective = objective_gradient(result_constrained.x)610grad_constraint = constraint_jacobian(result_constrained.x)611constraint_value = constraint_function(result_constrained.x)612613print(f"\nKKT Analysis:")614print(f"Gradient of objective: {grad_objective}")615print(f"Gradient of constraint: {grad_constraint}")616print(f"Constraint slack: {constraint_value:.6f}")617618# If constraint is active (slack ≈ 0), compute Lagrange multiplier619if abs(constraint_value) < 1e-6:620# At optimum: ∇f + λ∇g = 0, so λ = -∇f·∇g / ||∇g||²621lambda_multiplier = -np.dot(grad_objective, grad_constraint) / np.dot(grad_constraint, grad_constraint)622print(f"Estimated Lagrange multiplier: {lambda_multiplier:.4f}")623\end{pycode}624625\begin{pycode}626# Create linear programming and constrained optimization visualization627fig, axes = plt.subplots(2, 2, figsize=(15, 12))628fig.suptitle('Linear Programming and Constrained Optimization', fontsize=16, fontweight='bold')629630# Linear programming feasible region631ax1 = axes[0, 0]632x1_range = np.linspace(0, 4, 100)633x2_constraint1 = 4 - x1_range # x1 + x2 <= 4634x2_constraint2 = 6 - 2*x1_range # 2x1 + x2 <= 6635636# Plot constraints637ax1.fill_between(x1_range, 0, np.minimum(x2_constraint1, x2_constraint2),638where=(x2_constraint1 >= 0) & (x2_constraint2 >= 0),639alpha=0.3, color=optblue, label='Feasible region')640ax1.plot(x1_range, x2_constraint1, 'b-', linewidth=2, label='x1 + x2 <= 4')641ax1.plot(x1_range, x2_constraint2, 'r-', linewidth=2, label='2x1 + x2 <= 6')642643# Plot corner points644corner_points = np.array([[0, 0], [0, 4], [2, 2], [3, 0]])645ax1.plot(corner_points[:, 0], corner_points[:, 1], 'ko', markersize=8)646ax1.plot(result.x[0], result.x[1], 'r*', markersize=15, label='Optimal solution')647648# Objective function contours649x1_obj, x2_obj = np.meshgrid(np.linspace(0, 4, 50), np.linspace(0, 5, 50))650obj_values = 3*x1_obj + 2*x2_obj651ax1.contour(x1_obj, x2_obj, obj_values, levels=10, colors='gray', alpha=0.5)652653ax1.set_xlim(0, 4)654ax1.set_ylim(0, 5)655ax1.set_xlabel('x1')656ax1.set_ylabel('x2')657ax1.set_title('Linear Programming: Feasible Region')658ax1.legend()659ax1.grid(True, alpha=0.3)660661# Constrained optimization visualization662ax2 = axes[0, 1]663x_range_const = np.linspace(-1, 4, 100)664y_range_const = np.linspace(-1, 4, 100)665X_const, Y_const = np.meshgrid(x_range_const, y_range_const)666Z_obj = X_const**2 + Y_const**2 - 2*X_const - 4*Y_const + 5667668# Plot objective function contours669contours = ax2.contour(X_const, Y_const, Z_obj, levels=15, colors='blue', alpha=0.6)670ax2.clabel(contours, inline=True, fontsize=8)671672# Plot constraint673x_constraint = np.linspace(0, 3, 100)674y_constraint = 3 - x_constraint675ax2.fill_between(x_constraint, 0, y_constraint, alpha=0.2, color=optred, label='Feasible region')676ax2.plot(x_constraint, y_constraint, 'r-', linewidth=3, label='x1 + x2 <= 3')677678# Plot solutions679ax2.plot(1, 2, 'go', markersize=10, label='Unconstrained optimum')680ax2.plot(result_constrained.x[0], result_constrained.x[1], 'r*', markersize=15, label='Constrained optimum')681682ax2.set_xlim(-0.5, 3.5)683ax2.set_ylim(-0.5, 3.5)684ax2.set_xlabel('x1')685ax2.set_ylabel('x2')686ax2.set_title('Constrained Optimization')687ax2.legend()688ax2.grid(True, alpha=0.3)689690# Algorithm convergence comparison691ax3 = axes[1, 0]692algorithms = ['Gradient\nDescent', 'Newton\nMethod', 'Interior\nPoint', 'Simplex']693iterations = [1000, 5, 20, 8]694accuracy = [1e-6, 1e-12, 1e-8, 1e-15]695696ax3_twin = ax3.twinx()697bars1 = ax3.bar([x - 0.2 for x in range(len(algorithms))], iterations,698width=0.4, color=optblue, alpha=0.7, label='Iterations')699bars2 = ax3_twin.semilogy([x + 0.2 for x in range(len(algorithms))], accuracy,700'ro', markersize=10, label='Final accuracy')701702ax3.set_xlabel('Algorithm')703ax3.set_ylabel('Iterations to convergence', color=optblue)704ax3_twin.set_ylabel('Final accuracy', color=optred)705ax3.set_title('Algorithm Performance Comparison')706ax3.set_xticks(range(len(algorithms)))707ax3.set_xticklabels(algorithms, rotation=45)708ax3.grid(True, alpha=0.3)709710# Optimization landscape711ax4 = axes[1, 1]712# Create a 3D-like visualization using contours and shading713levels = np.linspace(np.min(Z_obj), np.max(Z_obj), 20)714cs = ax4.contourf(X_const, Y_const, Z_obj, levels=levels, cmap='viridis', alpha=0.8)715ax4.contour(X_const, Y_const, Z_obj, levels=levels, colors='black', alpha=0.3, linewidths=0.5)716717# Add colorbar718cbar = plt.colorbar(cs, ax=ax4, shrink=0.8)719cbar.set_label('Objective function value')720721ax4.plot(result_constrained.x[0], result_constrained.x[1], 'r*', markersize=15, label='Optimum')722ax4.set_xlabel('x1')723ax4.set_ylabel('x2')724ax4.set_title('Optimization Landscape')725ax4.legend()726727plt.tight_layout()728plt.savefig('assets/linear-constrained-optimization.pdf', dpi=300, bbox_inches='tight')729plt.close()730731print("Linear programming and constrained optimization analysis saved to assets/linear constrained optimization.pdf")732\end{pycode}733734\begin{figure}[H]735\centering736\includegraphics[width=\textwidth]{assets/linear-constrained-optimization.pdf}737\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.}738\label{fig:linear-constrained-optimization}739\end{figure}740741\section{Optimal Control Theory}742\label{sec:optimal-control}743744\subsection{Linear Quadratic Regulator (LQR)}745\label{subsec:lqr}746747The Linear Quadratic Regulator provides optimal feedback control for linear systems~\cite{anderson2007optimal}:748749\begin{pycode}750# LQR control design and analysis751from scipy.linalg import solve_continuous_are, solve_discrete_are752753def lqr_continuous(A, B, Q, R):754"""Solve continuous-time LQR problem"""755# Solve Algebraic Riccati Equation756P = solve_continuous_are(A, B, Q, R)757758# Compute optimal feedback gain759K = np.linalg.inv(R) @ B.T @ P760761# Compute closed-loop eigenvalues762A_cl = A - B @ K763eigenvalues = np.linalg.eigvals(A_cl)764765return K, P, eigenvalues766767def lqr_discrete(A, B, Q, R):768"""Solve discrete-time LQR problem"""769# Solve Discrete Algebraic Riccati Equation770P = solve_discrete_are(A, B, Q, R)771772# Compute optimal feedback gain773K = np.linalg.inv(R + B.T @ P @ B) @ B.T @ P @ A774775# Compute closed-loop eigenvalues776A_cl = A - B @ K777eigenvalues = np.linalg.eigvals(A_cl)778779return K, P, eigenvalues780781# Example: Double integrator system (position and velocity)782print("Linear Quadratic Regulator (LQR) Design:")783784# Continuous-time system: ẋ = Ax + Bu785A_cont = np.array([[0, 1], # [position] = [0 1] [position] + [0] u786[0, 0]]) # [velocity] [0 0] [velocity] [1]787788B_cont = np.array([[0],789[1]])790791# Cost matrices792Q = np.array([[10, 0], # Penalize position error more793[0, 1]]) # Small penalty on velocity794795R = np.array([[0.1]]) # Control effort penalty796797# Solve LQR798K_cont, P_cont, eigs_cont = lqr_continuous(A_cont, B_cont, Q, R)799800print(f"Continuous-time LQR:")801print(f" Optimal gain K = {K_cont.flatten()}")802print(f" Closed-loop poles: {eigs_cont}")803print(f" Cost matrix P =")804print(f" {P_cont}")805806# Discrete-time version (sampling time = 0.1s)807dt = 0.1808A_disc = np.eye(2) + A_cont * dt # Forward Euler approximation809B_disc = B_cont * dt810811K_disc, P_disc, eigs_disc = lqr_discrete(A_disc, B_disc, Q, R)812813print(f"\nDiscrete-time LQR (dt = {dt}s):")814print(f" Optimal gain K = {K_disc.flatten()}")815print(f" Closed-loop poles: {eigs_disc}")816print(f" Stability margin: {max(np.abs(eigs_disc)):.4f} < 1.0")817\end{pycode}818819\subsection{Kalman Filtering and State Estimation}820\label{subsec:kalman-filter}821822The Kalman filter provides optimal state estimation for linear systems with noise~\cite{kalman1960new}:823824\begin{pycode}825# Kalman filter implementation and simulation826class KalmanFilter:827def __init__(self, A, B, C, Q, R, P0, x0):828"""829Initialize Kalman filter830A: State transition matrix831B: Control input matrix832C: Observation matrix833Q: Process noise covariance834R: Measurement noise covariance835P0: Initial error covariance836x0: Initial state estimate837"""838self.A = A839self.B = B840self.C = C841self.Q = Q842self.R = R843self.P = P0844self.x = x0845846def predict(self, u=None):847"""Prediction step"""848if u is not None:849self.x = self.A @ self.x + self.B @ u850else:851self.x = self.A @ self.x852853self.P = self.A @ self.P @ self.A.T + self.Q854855def update(self, z):856"""Update step with measurement z"""857# Innovation858y = z - self.C @ self.x859860# Innovation covariance861S = self.C @ self.P @ self.C.T + self.R862863# Kalman gain864K = self.P @ self.C.T @ np.linalg.inv(S)865866# Update estimate867self.x = self.x + K @ y868869# Update error covariance870I = np.eye(len(self.x))871self.P = (I - K @ self.C) @ self.P872873return K, y, S874875# Simulation parameters876print("\nKalman Filter Simulation:")877878# System: position tracking with velocity879A_kf = np.array([[1, dt],880[0, 1]]) # Position and velocity dynamics881882B_kf = np.array([[0.5*dt**2],883[dt]]) # Control input (acceleration)884885C_kf = np.array([[1, 0]]) # Observe position only886887# Noise parameters888Q_kf = np.array([[0.01, 0], # Process noise889[0, 0.01]])890891R_kf = np.array([[0.1]]) # Measurement noise892893P0_kf = np.array([[1, 0], # Initial uncertainty894[0, 1]])895896x0_kf = np.array([0, 0]) # Initial state estimate897898# Create Kalman filter899kf = KalmanFilter(A_kf, B_kf, C_kf, Q_kf, R_kf, P0_kf, x0_kf)900901# Simulation902n_steps = 50903true_states = np.zeros((2, n_steps))904measurements = np.zeros(n_steps)905estimates = np.zeros((2, n_steps))906uncertainties = np.zeros((2, n_steps))907908# True system909x_true = np.array([0, 0]) # True initial state910911np.random.seed(42) # For reproducible results912913for k in range(n_steps):914# Control input (sinusoidal acceleration)915u = np.array([0.1 * np.sin(0.2 * k)])916917# True system evolution918w = np.random.multivariate_normal([0, 0], Q_kf) # Process noise919x_true = A_kf @ x_true + B_kf @ u.flatten() + w920921# Measurement922v = np.random.normal(0, np.sqrt(R_kf[0, 0])) # Measurement noise923z = C_kf @ x_true + v924925# Kalman filter prediction and update926kf.predict(u)927K, innovation, S = kf.update(z)928929# Store results930true_states[:, k] = x_true931measurements[k] = z.item() if hasattr(z, 'item') else float(z)932estimates[:, k] = kf.x933uncertainties[:, k] = np.sqrt(np.diag(kf.P))934935print(f"Final estimation error: position = {abs(estimates[0, -1] - true_states[0, -1]):.4f}")936print(f"Final uncertainty: position = {uncertainties[0, -1]:.4f}")937print(f"Average measurement noise: {np.sqrt(R_kf[0, 0]):.4f}")938\end{pycode}939940\begin{pycode}941# Create control systems visualization942fig, axes = plt.subplots(2, 2, figsize=(15, 12))943fig.suptitle('Optimal Control Theory and State Estimation', fontsize=16, fontweight='bold')944945# LQR pole placement visualization946ax1 = axes[0, 0]947# Plot open-loop vs closed-loop poles948open_loop_poles = np.linalg.eigvals(A_cont)949closed_loop_poles = eigs_cont950951# Unit circle for discrete-time (if we had discrete poles)952theta = np.linspace(0, 2*np.pi, 100)953unit_circle_x = np.cos(theta)954unit_circle_y = np.sin(theta)955956ax1.axhline(y=0, color='k', linestyle='-', alpha=0.3)957ax1.axvline(x=0, color='k', linestyle='-', alpha=0.3)958ax1.plot(np.real(open_loop_poles), np.imag(open_loop_poles), 'ro', markersize=10, label='Open-loop poles')959ax1.plot(np.real(closed_loop_poles), np.imag(closed_loop_poles), 'bs', markersize=10, label='Closed-loop poles')960961# Stability region for continuous-time (left half-plane)962ax1.axvline(x=0, color='red', linestyle='--', alpha=0.5, linewidth=2)963ax1.fill_betweenx([-5, 5], -5, 0, alpha=0.1, color='green', label='Stable region')964965ax1.set_xlim(-5, 1)966ax1.set_ylim(-3, 3)967ax1.set_xlabel('Real part')968ax1.set_ylabel('Imaginary part')969ax1.set_title('LQR Pole Placement')970ax1.legend()971ax1.grid(True, alpha=0.3)972973# Step response comparison974ax2 = axes[0, 1]975time_sim = np.linspace(0, 5, 100)976dt_sim = time_sim[1] - time_sim[0]977978# Simulate open-loop and closed-loop responses979from scipy.signal import lti, step980981# Open-loop system982sys_open = lti(A_cont, B_cont, np.eye(2), np.zeros((2, 1)))983t_open, y_open = step(sys_open, T=time_sim)984985# Closed-loop system986A_cl = A_cont - B_cont @ K_cont987sys_closed = lti(A_cl, B_cont, np.eye(2), np.zeros((2, 1)))988t_closed, y_closed = step(sys_closed, T=time_sim)989990ax2.plot(t_open, y_open[:, 0], 'r--', linewidth=2, label='Open-loop position')991ax2.plot(t_closed, y_closed[:, 0], 'b-', linewidth=2, label='Closed-loop position')992ax2.plot(t_closed, y_closed[:, 1], 'g-', linewidth=2, label='Closed-loop velocity')993994ax2.set_xlabel('Time (s)')995ax2.set_ylabel('State response')996ax2.set_title('Step Response Comparison')997ax2.legend()998ax2.grid(True, alpha=0.3)9991000# Kalman filter performance1001ax3 = axes[1, 0]1002time_kf = np.arange(n_steps) * dt10031004ax3.plot(time_kf, true_states[0, :], 'k-', linewidth=2, label='True position')1005ax3.plot(time_kf, measurements, 'r.', markersize=4, alpha=0.6, label='Measurements')1006ax3.plot(time_kf, estimates[0, :], 'b-', linewidth=2, label='Kalman estimate')10071008# Uncertainty bounds1009upper_bound = estimates[0, :] + 2*uncertainties[0, :]1010lower_bound = estimates[0, :] - 2*uncertainties[0, :]1011ax3.fill_between(time_kf, lower_bound, upper_bound, alpha=0.2, color='blue', label='±2σ bounds')10121013ax3.set_xlabel('Time (s)')1014ax3.set_ylabel('Position')1015ax3.set_title('Kalman Filter State Estimation')1016ax3.legend()1017ax3.grid(True, alpha=0.3)10181019# Control effort and cost analysis1020ax4 = axes[1, 1]1021Q_weights = [0.1, 1, 10, 100]1022control_efforts = []1023settling_times = []10241025for Q_weight in Q_weights:1026Q_temp = np.array([[Q_weight, 0], [0, 1]])1027K_temp, _, eigs_temp = lqr_continuous(A_cont, B_cont, Q_temp, R)10281029# Estimate control effort (gain magnitude)1030control_effort = np.linalg.norm(K_temp)1031control_efforts.append(control_effort)10321033# Estimate settling time (based on slowest pole)1034settling_time = 4 / abs(max(np.real(eigs_temp)))1035settling_times.append(settling_time)10361037ax4_twin = ax4.twinx()1038line1 = ax4.semilogx(Q_weights, control_efforts, 'bo-', linewidth=2, markersize=8, label='Control effort')1039line2 = ax4_twin.semilogx(Q_weights, settling_times, 'rs-', linewidth=2, markersize=8, label='Settling time')10401041ax4.set_xlabel('Q weight (position penalty)')1042ax4.set_ylabel('Control effort ||K||', color='blue')1043ax4_twin.set_ylabel('Settling time (s)', color='red')1044ax4.set_title('LQR Design Trade-offs')1045ax4.grid(True, alpha=0.3)10461047# Combine legends1048lines1, labels1 = ax4.get_legend_handles_labels()1049lines2, labels2 = ax4_twin.get_legend_handles_labels()1050ax4.legend(lines1 + lines2, labels1 + labels2, loc='center right')10511052plt.tight_layout()1053plt.savefig('assets/control-systems-analysis.pdf', dpi=300, bbox_inches='tight')1054plt.close()10551056print("Control systems analysis saved to assets/control systems analysis.pdf")1057\end{pycode}10581059\begin{figure}[H]1060\centering1061\includegraphics[width=\textwidth]{assets/control-systems-analysis.pdf}1062\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.}1063\label{fig:control-systems-analysis}1064\end{figure}10651066\section{Robust Control and Uncertainty}1067\label{sec:robust-control}10681069\begin{pycode}1070# Robust control analysis1071print("Robust Control Analysis:")10721073# H-infinity norm computation for robustness analysis1074def hinf_norm_approximation(A, B, C, D, omega_range):1075"""Approximate H-infinity norm by evaluating frequency response"""1076max_gain = 01077worst_freq = 010781079for omega in omega_range:1080s = 1j * omega1081# Transfer function: G(s) = C(sI - A)⁻¹B + D1082try:1083G = C @ np.linalg.inv(s * np.eye(len(A)) - A) @ B + D1084gain = np.linalg.norm(G)1085if gain > max_gain:1086max_gain = gain1087worst_freq = omega1088except np.linalg.LinAlgError:1089continue10901091return max_gain, worst_freq10921093# Example: Robust stability analysis1094A_robust = np.array([[-1, 1],1095[0, -2]])10961097B_robust = np.array([[0],1098[1]])10991100C_robust = np.array([[1, 0]])11011102D_robust = np.array([[0]])11031104# Frequency range for analysis1105omega_range = np.logspace(-2, 2, 1000)11061107hinf_norm, critical_freq = hinf_norm_approximation(A_robust, B_robust, C_robust, D_robust, omega_range)11081109print(f"H-infinity norm approximation: {hinf_norm:.4f}")1110print(f"Critical frequency: {critical_freq:.4f} rad/s")11111112# Robustness margin calculation1113stability_margin = 1.0 / hinf_norm1114print(f"Robustness margin: {stability_margin:.4f}")1115\end{pycode}11161117\section{Conclusion and Applications}1118\label{sec:conclusion}11191120This comprehensive optimization and control template demonstrates the deep connections between mathematical optimization theory and control system design. Key contributions include:11211122\subsection{Optimization Insights}11231124\begin{enumerate}1125\item \textbf{Convex Analysis}: Foundation for guaranteed global optimality1126\item \textbf{Gradient Methods}: Core algorithms with convergence analysis1127\item \textbf{Constrained Optimization}: KKT conditions and practical solution methods1128\item \textbf{Linear Programming}: Systematic approach to resource allocation1129\end{enumerate}11301131\subsection{Control Theory Applications}11321133\begin{itemize}1134\item \textbf{LQR Design}: Optimal feedback control with performance guarantees1135\item \textbf{Kalman Filtering}: Optimal state estimation under uncertainty1136\item \textbf{Robust Control}: Stability and performance under model uncertainty1137\item \textbf{Real-time Implementation}: Computational considerations for practical systems1138\end{itemize}11391140\subsection{Computational Considerations}11411142The template demonstrates:1143\begin{itemize}1144\item Efficient implementation of optimization algorithms1145\item Numerical stability considerations for control design1146\item Convergence analysis and performance metrics1147\item Professional visualization of optimization landscapes and control responses1148\end{itemize}11491150\section*{Acknowledgments}11511152This template leverages SciPy's optimization and control toolboxes, providing a foundation for advanced research in mathematical optimization and control systems engineering.11531154\printbibliography11551156\appendix11571158\section{Algorithm Summary}1159\label{app:algorithms}11601161\begin{pycode}1162# Create algorithm comparison table1163algorithm_data = [1164["Optimization", "Gradient Descent", "O(1/eps)", "Linear"],1165["", "Newton Method", "O(log log 1/eps)", "Quadratic"],1166["", "Adam", "O(1/sqrt(eps))", "Adaptive"],1167["Linear Programming", "Simplex", "Exponential (worst)", "Finite"],1168["", "Interior Point", "O(n3 L)", "Polynomial"],1169["Control", "LQR", "O(n3)", "Optimal"],1170["", "Kalman Filter", "O(n3)", "Optimal"],1171["", "H-infinity Control", "O(n6)", "Robust"],1172]11731174print("Algorithm Complexity and Convergence Summary:")1175print("Category Algorithm Complexity Convergence")1176print("-" * 65)1177for row in algorithm_data:1178category, algorithm, complexity, convergence = row1179print(f"{category:<15} {algorithm:<15} {complexity:<16} {convergence}")1180\end{pycode}11811182\end{document}11831184