Uni-Logo
Sie sind hier: Startseite Professuren Diehl, Moritz Events Dateien Solution, exercise 7 (Gauss Newton SQP)

Solution, exercise 7 (Gauss Newton SQP)

gauss_newton.py — Python Source, 4Kb

Dateiinhalt

from casadi import *
from numpy import *
import matplotlib.pyplot as plt

# Solve a QP
def qpsolve(H,g,lbx,ubx,A,lba,uba):
    # QP structure
    qp = qpStruct(h=H.sparsity(),a=A.sparsity())

    # Create CasADi solver instance
    if False:
        solver = QpSolver("qpoases",qp)
    else:
        solver = QpSolver("nlp",qp)
        solver.setOption("nlp_solver","ipopt")    
    
    # Initialize the solver
    solver.init()
    
    # Pass problem data
    solver.setInput(H,"h")
    solver.setInput(g,"g")
    solver.setInput(A,"a")
    solver.setInput(lbx,"lbx")
    solver.setInput(ubx,"ubx")
    solver.setInput(lba,"lba")
    solver.setInput(uba,"uba")

    # Solver the QP
    solver.evaluate()
    
    # Return the solution
    return solver.getOutput("x")


N = 20      # Control discretization
T = 10.0    # End time

# Declare variables (use scalar graph)
u  = SX.sym("u")    # control
x  = SX.sym("x",2)  # states

# System dynamics
xdot = vertcat( [(1 - x[1]**2)*x[0] - x[1] + u, x[0]] )
f = SXFunction([x,u],[xdot])
f.init()

# RK4 with M steps
U = MX.sym("U")
X = MX.sym("X",2)
M = 10; DT = T/(N*M)
XF = X
QF = 0
for j in range(M):
    [k1] = f([XF,             U])
    [k2] = f([XF + DT/2 * k1, U])
    [k3] = f([XF + DT/2 * k2, U])
    [k4] = f([XF + DT   * k3, U])
    XF += DT/6*(k1   + 2*k2   + 2*k3   + k4)
F = MXFunction([X,U],[XF])
F.init()

# Formulate NLP (use matrix graph)
nv = 1*N + 2*(N+1)
v = MX.sym("v", nv)

# Get the state for each shooting interval
xk = [v[3*k : 3*k + 2] for k in range(N+1)]

# Get the control for each shooting interval
uk = [v[3*k + 2] for k in range(N)]

# Variable bounds
vmin = -inf*ones(nv)
vmax =  inf*ones(nv)

# Initial solution guess
v0 = zeros(nv)

# Control bounds
vmin[2::3] = -1.0
vmax[2::3] =  1.0

# Initial condition
vmin[0] = vmax[0] = v0[0] = 0
vmin[1] = vmax[1] = v0[1] = 1

# Terminal constraint
vmin[-2] = vmax[-2] = v0[-2] = 0
vmin[-1] = vmax[-1] = v0[-1] = 0

# Constraint function with bounds
g = []; gmin = []; gmax = []

# Build up a graph of integrator calls
for k in range(N):
    # Call the integrator
    [xf] = F([xk[k],uk[k]])

    # Append continuity constraints
    g.append(xf - xk[k+1])
    gmin.append(zeros(2))
    gmax.append(zeros(2))

# Concatenate constraints
g = vertcat(g)
gmin = concatenate(gmin)
gmax = concatenate(gmax)

# Gauss-Newton objective
r = v

# Form function for calculating the Gauss-Newton objective
r_fcn = MXFunction([v],[r])
r_fcn.init()

# Form function for calculating the constraints
g_fcn = MXFunction([v],[g])
g_fcn.init()

# Generate functions for the Jacobians
Jac_r_fcn = r_fcn.jacobian()
Jac_r_fcn.init()
Jac_g_fcn = g_fcn.jacobian()
Jac_g_fcn.init()

# Objective value history
obj_history = []

# Constraint violation history
con_history = []

# Gauss-Newton SQP
v_opt = DMatrix(v0)
N_iter = 10
for k in range(N_iter):
    # Form quadratic approximation of objective
    Jac_r_fcn.setInput(v_opt)
    Jac_r_fcn.evaluate()
    J_r_k = Jac_r_fcn.getOutput(0)
    r_k = Jac_r_fcn.getOutput(1)

    # Form quadratic approximation of constraints
    Jac_g_fcn.setInput(v_opt)
    Jac_g_fcn.evaluate()
    J_g_k = Jac_g_fcn.getOutput(0)
    g_k = Jac_g_fcn.getOutput(1)
    
    # Gauss-Newton Hessian
    H_k = mul(J_r_k.T, J_r_k)

    # Gradient of the objective function
    Grad_obj_k = mul(J_r_k.T, r_k)

    # Bounds on delta_v
    dv_min = vmin - v_opt
    dv_max = vmax - v_opt
    
    # Solve the QP
    dv = qpsolve(H_k, Grad_obj_k, dv_min, dv_max, J_g_k, -g_k, -g_k)

    # Take the full step
    v_opt += dv

    # Save objective and constraint violation
    obj_history.append(float(inner_prod(r_k,r_k)/2))
    con_history.append(float(norm_2(g_k)))

# Print result
print "solution found: ", v_opt

# Retrieve the solution
x0_opt = v_opt[0::3]
x1_opt = v_opt[1::3]
u_opt = v_opt[2::3]

# Plot the results
plt.figure(1)
plt.clf()
plt.subplot(121)
plt.plot(linspace(0,T,N+1),x0_opt,'--')
plt.plot(linspace(0,T,N+1),x1_opt,'-')
plt.step(linspace(0,T,N),u_opt,'-.')
plt.title("Solution: Gauss-Newton SQP")
plt.xlabel('time')
plt.legend(['x0 trajectory','x1 trajectory','u trajectory'])
plt.grid()

plt.subplot(122)
plt.title("SQP solver output")
plt.semilogy(obj_history)
plt.semilogy(con_history)
plt.xlabel('iteration')
plt.legend(['Objective value','Constraint violation'], loc='center right')
plt.grid()

plt.show()


« Mai 2025 »
Mai
MoDiMiDoFrSaSo
1234
567891011
12131415161718
19202122232425
262728293031
Benutzerspezifische Werkzeuge