ubuntu2404
#!/usr/bin/env python31"""2Generate missing figures for optimization-control-systems template3"""45import numpy as np6import matplotlib.pyplot as plt7import matplotlib8matplotlib.use('Agg') # Use non-interactive backend9from scipy.optimize import minimize, linprog10from scipy.linalg import solve_continuous_are11import os1213# Set random seed for reproducibility14np.random.seed(42)1516# Define colors for plots (matching LaTeX color definitions)17optblue = '#0077BB' # RGB(0,119,187)18optred = '#CC3311' # RGB(204,51,17)19optgreen = '#009966' # RGB(0,153,102)20optorange = '#FF9933' # RGB(255,153,51)21optpurple = '#990099' # RGB(153,0,153)2223# Ensure assets directory exists24os.makedirs('assets', exist_ok=True)2526def generate_linear_constrained_optimization():27"""Generate linear programming and constrained optimization figure"""2829# Linear programming setup30c = np.array([-3, -2]) # Maximize 3x1 + 2x2 (negate for minimize)31A_ub = np.array([[1, 1], [2, 1]]) # Constraints matrix32b_ub = np.array([4, 6]) # Constraints bounds33bounds = [(0, None), (0, None)] # x1, x2 >= 03435# Solve linear programming problem36result = linprog(c, A_ub=A_ub, b_ub=b_ub, bounds=bounds, method='highs')3738# Constrained optimization setup39def objective_function(x):40return x[0]**2 + x[1]**2 - 2*x[0] - 4*x[1] + 54142def constraint_function(x):43return x[0] + x[1] - 34445# Solve constrained optimization46constraints = {'type': 'ineq', 'fun': lambda x: -constraint_function(x)}47result_constrained = minimize(objective_function, [0.5, 0.5], constraints=constraints)4849# Create visualization50fig, axes = plt.subplots(2, 2, figsize=(15, 12))51fig.suptitle('Linear Programming and Constrained Optimization', fontsize=16, fontweight='bold')5253# Linear programming feasible region54ax1 = axes[0, 0]55x1_range = np.linspace(0, 4, 100)56x2_constraint1 = 4 - x1_range # x1 + x2 <= 457x2_constraint2 = 6 - 2*x1_range # 2x1 + x2 <= 65859# Plot constraints60ax1.fill_between(x1_range, 0, np.minimum(x2_constraint1, x2_constraint2),61where=(x2_constraint1 >= 0) & (x2_constraint2 >= 0),62alpha=0.3, color=optblue, label='Feasible region')63ax1.plot(x1_range, x2_constraint1, 'b-', linewidth=2, label='x1 + x2 <= 4')64ax1.plot(x1_range, x2_constraint2, 'r-', linewidth=2, label='2x1 + x2 <= 6')6566# Plot corner points67corner_points = np.array([[0, 0], [0, 4], [2, 2], [3, 0]])68ax1.plot(corner_points[:, 0], corner_points[:, 1], 'ko', markersize=8)69ax1.plot(result.x[0], result.x[1], 'r*', markersize=15, label='Optimal solution')7071# Objective function contours72x1_obj, x2_obj = np.meshgrid(np.linspace(0, 4, 50), np.linspace(0, 5, 50))73obj_values = 3*x1_obj + 2*x2_obj74ax1.contour(x1_obj, x2_obj, obj_values, levels=10, colors='gray', alpha=0.5)7576ax1.set_xlim(0, 4)77ax1.set_ylim(0, 5)78ax1.set_xlabel('x1')79ax1.set_ylabel('x2')80ax1.set_title('Linear Programming: Feasible Region')81ax1.legend()82ax1.grid(True, alpha=0.3)8384# Constrained optimization visualization85ax2 = axes[0, 1]86x_range_const = np.linspace(-1, 4, 100)87y_range_const = np.linspace(-1, 4, 100)88X_const, Y_const = np.meshgrid(x_range_const, y_range_const)89Z_obj = X_const**2 + Y_const**2 - 2*X_const - 4*Y_const + 59091# Plot objective function contours92contours = ax2.contour(X_const, Y_const, Z_obj, levels=15, colors='blue', alpha=0.6)93ax2.clabel(contours, inline=True, fontsize=8)9495# Plot constraint96x_constraint = np.linspace(0, 3, 100)97y_constraint = 3 - x_constraint98ax2.fill_between(x_constraint, 0, y_constraint, alpha=0.2, color=optred, label='Feasible region')99ax2.plot(x_constraint, y_constraint, 'r-', linewidth=3, label='x1 + x2 <= 3')100101# Plot solutions102ax2.plot(1, 2, 'go', markersize=10, label='Unconstrained optimum')103ax2.plot(result_constrained.x[0], result_constrained.x[1], 'r*', markersize=15, label='Constrained optimum')104105ax2.set_xlim(-0.5, 3.5)106ax2.set_ylim(-0.5, 3.5)107ax2.set_xlabel('x1')108ax2.set_ylabel('x2')109ax2.set_title('Constrained Optimization')110ax2.legend()111ax2.grid(True, alpha=0.3)112113# Algorithm convergence comparison114ax3 = axes[1, 0]115algorithms = ['Gradient\nDescent', 'Newton\nMethod', 'Interior\nPoint', 'Simplex']116iterations = [1000, 5, 20, 8]117accuracy = [1e-6, 1e-12, 1e-8, 1e-15]118119ax3_twin = ax3.twinx()120bars1 = ax3.bar([x - 0.2 for x in range(len(algorithms))], iterations,121width=0.4, color=optblue, alpha=0.7, label='Iterations')122bars2 = ax3_twin.semilogy([x + 0.2 for x in range(len(algorithms))], accuracy,123'ro', markersize=10, label='Final accuracy')124125ax3.set_xlabel('Algorithm')126ax3.set_ylabel('Iterations to convergence', color=optblue)127ax3_twin.set_ylabel('Final accuracy', color=optred)128ax3.set_title('Algorithm Performance Comparison')129ax3.set_xticks(range(len(algorithms)))130ax3.set_xticklabels(algorithms, rotation=45)131ax3.grid(True, alpha=0.3)132133# Optimization landscape134ax4 = axes[1, 1]135# Create a 3D-like visualization using contours and shading136levels = np.linspace(np.min(Z_obj), np.max(Z_obj), 20)137cs = ax4.contourf(X_const, Y_const, Z_obj, levels=levels, cmap='viridis', alpha=0.8)138ax4.contour(X_const, Y_const, Z_obj, levels=levels, colors='black', alpha=0.3, linewidths=0.5)139140# Add colorbar141cbar = plt.colorbar(cs, ax=ax4, shrink=0.8)142cbar.set_label('Objective function value')143144ax4.plot(result_constrained.x[0], result_constrained.x[1], 'r*', markersize=15, label='Optimum')145ax4.set_xlabel('x1')146ax4.set_ylabel('x2')147ax4.set_title('Optimization Landscape')148ax4.legend()149150plt.tight_layout()151plt.savefig('assets/linear_constrained_optimization.pdf', dpi=300, bbox_inches='tight')152plt.close()153154print("Generated linear_constrained_optimization.pdf")155156def generate_control_systems_analysis():157"""Generate control systems analysis figure"""158159# Define LQR continuous function160def lqr_continuous(A, B, Q, R):161"""Solve continuous-time LQR problem"""162P = solve_continuous_are(A, B, Q, R)163K = np.linalg.inv(R) @ B.T @ P164return K, P165166# System matrices for double integrator167A = np.array([[0, 1], [0, 0]])168B = np.array([[0], [1]])169C = np.array([[1, 0]])170171# LQR design parameters172Q = np.array([[1, 0], [0, 1]])173R = np.array([[1]])174175# Design LQR controller176K_lqr, P_lqr = lqr_continuous(A, B, Q, R)177A_cl = A - B @ K_lqr178179# Simulate step response180t = np.linspace(0, 10, 1000)181dt = t[1] - t[0]182183# Initial condition response184x0 = np.array([[1], [0]])185x_open = np.zeros((2, len(t)))186x_closed = np.zeros((2, len(t)))187x_open[:, [0]] = x0188x_closed[:, [0]] = x0189190for i in range(1, len(t)):191# Open-loop (unstable system would blow up, so we'll simulate a different scenario)192x_open[:, [i]] = x_open[:, [i-1]] + dt * A @ x_open[:, [i-1]]193194# Closed-loop195x_closed[:, [i]] = x_closed[:, [i-1]] + dt * A_cl @ x_closed[:, [i-1]]196197# Generate Kalman filter data198# Process and measurement noise199Q_kf = 0.01 * np.eye(2)200R_kf = 0.1201202# Generate true trajectory with noise203x_true = np.zeros((2, len(t)))204y_meas = np.zeros(len(t))205x_true[:, [0]] = x0206207for i in range(1, len(t)):208process_noise = np.random.multivariate_normal([0, 0], Q_kf).reshape(2, 1)209x_true[:, [i]] = x_true[:, [i-1]] + dt * A_cl @ x_true[:, [i-1]] + process_noise210y_meas[i] = (C @ x_true[:, [i]])[0, 0] + np.random.normal(0, np.sqrt(R_kf))211212# Simple Kalman filter estimate (simplified)213x_est = np.zeros((2, len(t)))214x_est[:, [0]] = x0215P_est = np.eye(2)216217for i in range(1, len(t)):218# Prediction219x_pred = x_est[:, [i-1]] + dt * A_cl @ x_est[:, [i-1]]220P_pred = P_est + dt * Q_kf221222# Update223K_kf = P_pred @ C.T / (C @ P_pred @ C.T + R_kf)224x_est[:, [i]] = x_pred + K_kf * (y_meas[i] - (C @ x_pred)[0, 0])225P_est = (np.eye(2) - K_kf @ C) @ P_pred226227# Create visualization228fig, axes = plt.subplots(2, 2, figsize=(15, 12))229fig.suptitle('Optimal Control Theory and State Estimation', fontsize=16, fontweight='bold')230231# LQR pole placement232ax1 = axes[0, 0]233234# Open-loop poles235open_poles = np.linalg.eigvals(A)236closed_poles = np.linalg.eigvals(A_cl)237238ax1.plot(np.real(open_poles), np.imag(open_poles), 'ro', markersize=10, label='Open-loop poles')239ax1.plot(np.real(closed_poles), np.imag(closed_poles), 'bo', markersize=10, label='Closed-loop poles')240ax1.axvline(0, color='black', linestyle='--', alpha=0.5)241ax1.fill_between([-2, 0], [-3, -3], [3, 3], alpha=0.2, color='green', label='Stable region')242ax1.set_xlabel('Real Part')243ax1.set_ylabel('Imaginary Part')244ax1.set_title('LQR Pole Placement')245ax1.legend()246ax1.grid(True, alpha=0.3)247ax1.set_xlim(-2, 1)248ax1.set_ylim(-2, 2)249250# Step response comparison251ax2 = axes[0, 1]252ax2.plot(t, x_open[0, :], 'r-', linewidth=2, label='Open-loop')253ax2.plot(t, x_closed[0, :], 'b-', linewidth=2, label='Closed-loop (LQR)')254ax2.set_xlabel('Time (s)')255ax2.set_ylabel('Position')256ax2.set_title('Step Response Comparison')257ax2.legend()258ax2.grid(True, alpha=0.3)259ax2.set_xlim(0, 10)260261# Kalman filter performance262ax3 = axes[1, 0]263ax3.plot(t, x_true[0, :], 'g-', linewidth=2, label='True state')264ax3.plot(t, y_meas, 'r.', markersize=2, alpha=0.5, label='Measurements')265ax3.plot(t, x_est[0, :], 'b-', linewidth=2, label='Kalman estimate')266267# Add uncertainty bounds (simplified)268uncertainty = 0.1 * np.ones_like(t)269ax3.fill_between(t, x_est[0, :] - uncertainty, x_est[0, :] + uncertainty,270alpha=0.3, color='blue', label='Uncertainty bounds')271272ax3.set_xlabel('Time (s)')273ax3.set_ylabel('Position')274ax3.set_title('Kalman Filter State Estimation')275ax3.legend()276ax3.grid(True, alpha=0.3)277ax3.set_xlim(0, 10)278279# LQR design trade-offs280ax4 = axes[1, 1]281Q_weights = [0.1, 1, 10, 100]282settling_times = []283control_efforts = []284285for q_weight in Q_weights:286Q_test = q_weight * np.eye(2)287K_test, _ = lqr_continuous(A, B, Q_test, R)288A_cl_test = A - B @ K_test289290# Approximate settling time (time to reach 2% of steady state)291settling_times.append(4 / abs(np.real(np.linalg.eigvals(A_cl_test)).max()))292control_efforts.append(np.linalg.norm(K_test))293294ax4_twin = ax4.twinx()295296lines1 = ax4.plot(Q_weights, settling_times, 'bo-', linewidth=2, markersize=8, label='Settling time')297lines2 = ax4_twin.plot(Q_weights, control_efforts, 'ro-', linewidth=2, markersize=8, label='Control effort')298299ax4.set_xlabel('Q weight')300ax4.set_ylabel('Settling time (s)', color='blue')301ax4_twin.set_ylabel('Control effort', color='red')302ax4.set_title('LQR Design Trade-offs')303ax4.set_xscale('log')304ax4.grid(True, alpha=0.3)305306# Combine legends307lines1, labels1 = ax4.get_legend_handles_labels()308lines2, labels2 = ax4_twin.get_legend_handles_labels()309ax4.legend(lines1 + lines2, labels1 + labels2, loc='center right')310311plt.tight_layout()312plt.savefig('assets/control_systems_analysis.pdf', dpi=300, bbox_inches='tight')313plt.close()314315print("Generated control_systems_analysis.pdf")316317if __name__ == "__main__":318print("Generating missing optimization and control systems figures...")319320try:321generate_linear_constrained_optimization()322generate_control_systems_analysis()323print("All missing figures generated successfully!")324except Exception as e:325print(f"Error generating figures: {e}")326import traceback327traceback.print_exc()328329