# Load the packages using JuMP, MosekTools, Mosek, LinearAlgebra, SCS, COSMO, Literate, OffsetArrays # %% Some helper functions # %% construct e_i in R^n function e_i(n, i) e_i_vec = zeros(n, 1) e_i_vec[i] = 1 return e_i_vec end # %% construct symmetric outer product function āŠ™(a,b) return ((a*b')+(b*a')) ./ 2 end # %% Parameters to be tuned N = 5 L = 1 Ī¼ = 0 c_w = 1 c_f = 0 # define all the bold vectors # -------------------------- # define š°_0 š°_0 = e_i(N+2, 1) š°_star = zeros(N+2, 1) š _star = zeros(N+2,1) # define š _0, š _1, ā€¦, š _N # first we define š _Julia vectors and then š  vectors š  = OffsetArray(zeros(N+2, N+1), 1:N+2, 0:N) # š = [š _0 š _1 š _2 ... š _N] for i in 0:N š [:,i] = e_i(N+2, i+2) end šŸ_star = zeros(N+1,1) # time to define šŸ_0, šŸ_1, ā€¦, šŸ_N šŸ = OffsetArray(zeros(N+1, N+1), 1:N+1, 0:N) # šŸ = [šŸ_0, šŸ_1, ā€¦, šŸ_N] for i in 0:N šŸ[:,i] = e_i(N+1, i+1) end pep_model = Model(optimizer_with_attributes(Mosek.Optimizer, "MSK_DPAR_INTPNT_CO_TOL_PFEAS" => 1e-10)) # time to define all the variables # ------------------------------- # define Ī±ā€² (can be typed as \alpha[TAB]\prime[TAB]) @variable(pep_model, Ī±ā€²[1:N, 0:N-1]) # define Ī» variables @variable(pep_model, Ī»_i_ip1[0:N-1] >= 0) # this defines (Ī»_{i,i+1})_{iāˆˆ[0:N-1]} in Julia indexing @variable(pep_model, Ī»_star_i[0:N] >= 0) # this defines (Ī»_{ā‹†,i})_{iāˆˆ[0:N]} in Julia indexing # define Ļ„ @variable(pep_model, Ļ„ >= 0) # define objective @objective( pep_model, Min, Ļ„ ) # Add the linear equality constraint # ---------------------------------- @constraint(pep_model, Ļ„ * c_f .* šŸ[:,0] + sum(Ī»_i_ip1[i] .* (šŸ[:,i+1]-šŸ[:,i]) for i in 0:N-1) + sum(Ī»_star_i[i] .* (šŸ[:,i] - šŸ_star) for i in 0:N) .== šŸ[:,N] - šŸ_star ) # Add the giant LMI constraint step by step # ---------------------------------------- term_1 = c_w * Ļ„ * āŠ™(š°_0,š°_0) term_2_part_1 = sum(Ī»_i_ip1[i] .* āŠ™(š [:,i]-š [:,i+1],š [:,i]-š [:,i+1]) for i in 0:N-1) term_2_part_2 = sum(Ī»_star_i[i] .* āŠ™(š _star - š [:,i],š _star - š [:,i]) for i in 0:N) term_2 = (term_2_part_1 + term_2_part_2) ./ (2*L) term_3 = - Ī»_star_i[0] .* āŠ™(š [:,0],š°_0) term_4_part_1 = - sum( Ī»_i_ip1[i] .* āŠ™(š [:,i],š°_0) for i in 1:N-1) term_4_part_2 = (1/L) .* sum( sum(Ī±ā€²[i,j] .* āŠ™(š [:,i],š [:,j]) for j in 0:i-1) for i in 1:N-1) term_4 = term_4_part_1 + term_4_part_2 term_5 = - ( āŠ™(š [:,N],š°_0) - (1/L) .* sum(Ī±ā€²[N,j] .* āŠ™(š [:,N],š [:,j]) for j in 0:N-1)) term_6_part_1 = sum(Ī»_i_ip1[i] .* āŠ™(š [:,i+1],š°_0) for i in 0:N-1) term_6_part_2 = - (1/L) .* sum( sum( Ī±ā€²[i,j] .* āŠ™(š [:,i+1],š [:,j]) for j in 0:i-1) for i in 1:N-1) term_6 = term_6_part_1 + term_6_part_2 # oof, okay constructed the terms for the LMI constraint, let us hope that there is no mistake and add them together S_mat = term_1 + term_2 + term_3 + term_4 + term_5 + term_6 # add the LMI constraint now @constraint(pep_model, S_mat in PSDCone() ) # time to optimize! # ----------------- optimize!(pep_model) println("termination status =", termination_status(pep_model) ) # Collect the decision variables # ----------------------------- Ī±ā€²_opt = OffsetArray(value.(Ī±ā€²), 1:N, 0:N-1) Ī»_opt_i_ip1 = OffsetVector(value.(Ī»_i_ip1), 0:N-1) Ī»_opt_star_i = OffsetVector(value.(Ī»_star_i), 0:N) Ļ„_opt = value(Ļ„) # Recover Ī±_{i,j} from Ī±ā€²_{i,j} # ----------------------------- Ī±_opt = OffsetArray(zeros(size(Ī±ā€²_opt)), 1:N, 0:N-1) for i in 1:N-1 for j in 0:i-1 Ī±_opt[i,j] = (Ī±ā€²_opt[i,j] / Ī»_opt_i_ip1[i]) end end for j in 0:N-1 Ī±_opt[N,j] = Ī±ā€²_opt[N,j] end # Recover h_{i,j} from Ī±_{i,j} h_opt = OffsetArray(zeros(size(Ī±_opt)), 1:N, 0:N-1) # set h(1,0) h_opt[1,0] = Ī±_opt[1,0] for i in 2:N for j in 0:i-1 if j == i-1 h_opt[i,j] = Ī±_opt[i,j] else h_opt[i,j] = Ī±_opt[i,j] - Ī±_opt[i-1,j] end end end function full_pep_solver(N, L, Ī¼, c_w, c_f) # define all the bold vectors # -------------------------- # define š°_0 š°_0 = e_i(N+2, 1) š°_star = zeros(N+2, 1) š _star = zeros(N+2,1) # define š _0, š _1, ā€¦, š _N # first we define š _Julia vectors and then š  vectors š  = OffsetArray(zeros(N+2, N+1), 1:N+2, 0:N) # š = [š _0 š _1 š _2 ... š _N] for i in 0:N š [:,i] = e_i(N+2, i+2) end šŸ_star = zeros(N+1,1) # time to define šŸ_0, šŸ_1, ā€¦, šŸ_N šŸ = OffsetArray(zeros(N+1, N+1), 1:N+1, 0:N) # šŸ = [šŸ_0, šŸ_1, ā€¦, šŸ_N] for i in 0:N šŸ[:,i] = e_i(N+1, i+1) end # Define JuMP model # ---------------- pep_model = Model(optimizer_with_attributes(Mosek.Optimizer, "MSK_DPAR_INTPNT_CO_TOL_PFEAS" => 1e-10)) #define all the variables # ------------------------------- # define Ī±ā€² (can be typed as \alpha[TAB]\prime[TAB]) @variable(pep_model, Ī±ā€²[1:N, 0:N-1]) # define Ī» variables @variable(pep_model, Ī»_i_ip1[0:N-1] >= 0) # this defines (Ī»_{i,i+1})_{iāˆˆ[0:N-1]} in Julia indexing @variable(pep_model, Ī»_star_i[0:N] >= 0) # this defines (Ī»_{ā‹†,i})_{iāˆˆ[0:N]} in Julia indexing # define Ļ„ @variable(pep_model, Ļ„ >= 0) # define objective # ------------------ @objective( pep_model, Min, Ļ„ ) # Add the linear equality constraint # ---------------------------------- @constraint(pep_model, Ļ„ * c_f .* šŸ[:,0] + sum(Ī»_i_ip1[i] .* (šŸ[:,i+1]-šŸ[:,i]) for i in 0:N-1) + sum(Ī»_star_i[i] .* (šŸ[:,i] - šŸ_star) for i in 0:N) .== šŸ[:,N] - šŸ_star ) # Add the giant LMI constraint step by step # ---------------------------------------- # Define all the terms one by one term_1 = c_w * Ļ„ * āŠ™(š°_0,š°_0) term_2_part_1 = sum(Ī»_i_ip1[i] .* āŠ™(š [:,i]-š [:,i+1],š [:,i]-š [:,i+1]) for i in 0:N-1) term_2_part_2 = sum(Ī»_star_i[i] .* āŠ™(š _star - š [:,i],š _star - š [:,i]) for i in 0:N) term_2 = (term_2_part_1 + term_2_part_2) ./ (2*L) term_3 = - Ī»_star_i[0] .* āŠ™(š [:,0],š°_0) term_4_part_1 = - sum( Ī»_i_ip1[i] .* āŠ™(š [:,i],š°_0) for i in 1:N-1) term_4_part_2 = (1/L) .* sum( sum(Ī±ā€²[i,j] .* āŠ™(š [:,i],š [:,j]) for j in 0:i-1) for i in 1:N-1) term_4 = term_4_part_1 + term_4_part_2 term_5 = - ( āŠ™(š [:,N],š°_0) - (1/L) .* sum(Ī±ā€²[N,j] .* āŠ™(š [:,N],š [:,j]) for j in 0:N-1)) term_6_part_1 = sum(Ī»_i_ip1[i] .* āŠ™(š [:,i+1],š°_0) for i in 0:N-1) term_6_part_2 = - (1/L) .* sum( sum( Ī±ā€²[i,j] .* āŠ™(š [:,i+1],š [:,j]) for j in 0:i-1) for i in 1:N-1) term_6 = term_6_part_1 + term_6_part_2 # oof, okay constructed the terms for the LMI constraint, let us hope that there is no mistake and add them together S_mat = term_1 + term_2 + term_3 + term_4 + term_5 + term_6 # add the LMI constraint now @constraint(pep_model, S_mat in PSDCone() ) # time to optimize! # ----------------- optimize!(pep_model) println("termination status =", termination_status(pep_model) ) Ī±ā€²_opt = OffsetArray(value.(Ī±ā€²), 1:N, 0:N-1) Ī»_opt_i_ip1 = OffsetVector(value.(Ī»_i_ip1), 0:N-1) Ī»_opt_star_i = OffsetVector(value.(Ī»_star_i), 0:N) Ļ„_opt = value(Ļ„) # Recover Ī±_{i,j} from Ī±ā€²_{i,j} # ----------------------------- Ī±_opt = OffsetArray(zeros(size(Ī±ā€²_opt)), 1:N, 0:N-1) for i in 1:N-1 for j in 0:i-1 Ī±_opt[i,j] = (Ī±ā€²_opt[i,j] / Ī»_opt_i_ip1[i]) end end for j in 0:N-1 Ī±_opt[N,j] = Ī±ā€²_opt[N,j] end # Recover h_{i,j} from Ī±_{i,j} # ---------------------------- h_opt = OffsetArray(zeros(size(Ī±_opt)), 1:N, 0:N-1) # set h(1,0) h_opt[1,0] = Ī±_opt[1,0] # set the rest of the variables for i in 2:N for j in 0:i-1 if j == i-1 h_opt[i,j] = Ī±_opt[i,j] else h_opt[i,j] = Ī±_opt[i,j] - Ī±_opt[i-1,j] end end end # return all the outputs # ---------------------- return Ī±ā€²_opt, Ī»_opt_i_ip1, Ī»_opt_star_i, Ļ„_opt, Ī±_opt, h_opt end Ī±ā€²_opt, Ī»_opt_i_ip1, Ī»_opt_star_i, Ļ„_opt, Ī±_opt, h_opt = full_pep_solver(N, L, Ī¼, c_w, c_f)