Capítulo 2

Optimización con Restricciones

2.1 Multiplicadores de Lagrange

Para minimizar f(x)f(\mathbf{x}) sujeto a g(x)=0g(\mathbf{x}) = 0:

L(x,λ)=f(x)λg(x)\mathcal{L}(\mathbf{x}, \lambda) = f(\mathbf{x}) - \lambda g(\mathbf{x})

Resolvemos:

xL=0,Lλ=0\nabla_{\mathbf{x}} \mathcal{L} = 0, \quad \frac{\partial \mathcal{L}}{\partial \lambda} = 0

2.2 Ejemplo: Elipse y Recta

Minimizar f(x,y)=x2+2y2f(x,y) = x^2 + 2y^2 sujeto a x+y=3x + y = 3:

L=x2+2y2λ(x+y3)\mathcal{L} = x^2 + 2y^2 - \lambda(x + y - 3)

Derivando:

x=2xλ=0,  y=4yλ=0,  x+y=3\frac{\partial}{\partial x} = 2x - \lambda = 0, \; \frac{\partial}{\partial y} = 4y - \lambda = 0, \; x + y = 3

Solución: x=2,y=1,λ=4x = 2, y = 1, \lambda = 4.

python
import numpy as np
from scipy.optimize import minimize

# Minimizar x^2 + 2y^2 sujeto a x + y = 3
def f(xy):
    x, y = xy
    return x**2 + 2*y**2

# Restricción: x + y - 3 = 0
def constraint(xy):
    return xy[0] + xy[1] - 3

cons = {'type': 'eq', 'fun': constraint}
res = minimize(f, x0=[0, 0], constraints=cons)
print(f"Solución: x={res.x[0]:.4f}, y={res.x[1]:.4f}")
print(f"Valor óptimo: {res.fun:.4f}")
print(f"Verificación: x+y = {res.x[0] + res.x[1]:.4f}")

2.3 Condiciones KKT

Generalización de Lagrange para restricciones de desigualdad:

minf(x)  s.a.  gi(x)0,  hj(x)=0\min f(\mathbf{x}) \; \text{s.a.} \; g_i(\mathbf{x}) \le 0, \; h_j(\mathbf{x}) = 0

Condiciones necesarias:

  • Estacionariedad: f+μigi+λjhj=0\nabla f + \sum \mu_i \nabla g_i + \sum \lambda_j \nabla h_j = 0
  • Factibilidad: gi(x)0,  hj(x)=0g_i(\mathbf{x}) \le 0, \; h_j(\mathbf{x}) = 0
  • Holgura complementaria: μigi(x)=0\mu_i g_i(\mathbf{x}) = 0
  • Dualidad: μi0\mu_i \ge 0

2.4 SVM: El ejemplo estrella

SVM busca el hiperplano que maximiza el margen, con restricciones de clasificación correcta:

minw,b12w2  s.a.  yi(wTxi+b)1,  i\min_{\mathbf{w}, b} \frac{1}{2}\|\mathbf{w}\|^2 \; \text{s.a.} \; y_i(\mathbf{w}^T \mathbf{x}_i + b) \ge 1, \; \forall i

El Lagrangiano dual convierte esto en un problema de programación cuadrática.

python
from sklearn.svm import SVC
import numpy as np

# SVM con kernel lineal
X = np.array([[1, 1], [2, 2], [3, 3], [4, 4]])
y = np.array([0, 0, 1, 1])

svm = SVC(kernel='linear', C=1e5)  # C grande = margen duro
svm.fit(X, y)

print(f"Coeficientes: {svm.coef_}")
print(f"Intercepto: {svm.intercept_}")
print(f"Vectores soporte:
{svm.support_vectors_}")

# Predicción
print(f"Predicción [2.5, 2.5]: {svm.predict([[2.5, 2.5]])[0]}")