Julia 使用NLsolve.jl的拉格朗日乘子法
我想在Julia 使用NLsolve.jl的拉格朗日乘子法,julia,Julia,我想在g(z)=0的约束下最小化距离函数|dz-z | |。 我想用拉格朗日乘数来解决这个问题。然后我用NLsolve.jl来解我最后得到的非线性方程 using NLsolve using ForwardDiff function ProjLagrange(dz, g::Function) λ_init = ones(size(g(dz...),1)) initial_x = vcat(dz, λ_init) function gradL!(F, x)
g(z)=0
的约束下最小化距离函数|dz-z | |
。
我想用拉格朗日乘数来解决这个问题。然后我用NLsolve.jl
来解我最后得到的非线性方程
using NLsolve
using ForwardDiff
function ProjLagrange(dz, g::Function)
λ_init = ones(size(g(dz...),1))
initial_x = vcat(dz, λ_init)
function gradL!(F, x)
len_dz = length(dz)
z = x[1:len_dz]
λ = x[len_dz+1:end]
F = Array{Float64}(undef, length(x))
my_distance(z) = norm(dz - z)
∇f = z -> ForwardDiff.gradient(my_distance, z)
F[1:len_dz] = ∇f(z) .- dot(λ, g(z...))
if length(λ) == 1
F[end] = g(z...)
else
F[len_dz+1:end] = g(z)
end
end
nlsolve(gradL!, initial_x)
end
g_test(x1, x2, x3) = x1^2 + x2 - x2 + 5
z = [1000,1,1]
ProjLagrange(z, g_test)
但我总是以零结尾:[NaN,NaN,NaN,NaN]
和收敛:false
。
正如你所知道的,我已经通过使用Optim.jl
并最小化以下函数来解方程:Proj(z)=b*sum(abs.(g(z))+a*norm(dz-z)
。
但我真的很想知道NLsolve是否可以做到这一点。非常感谢您的帮助 我修改了您的代码,如下所示(请参见此处的注释),并获得了以下输出。它不再抛出
NaN
s,减少目标并收敛。这与您的Optim.jl
结果是否不同
Results of Nonlinear Solver Algorithm
* Algorithm: Trust-region with dogleg and autoscaling
* Starting Point: [1000.0, 1.0, 1.0, 1.0]
* Zero: [9.80003, -49.5203, 51.5203, -0.050888]
* Inf-norm of residuals: 0.000000
* Iterations: 10
* Convergence: true
* |x - x'| < 0.0e+00: false
* |f(x)| < 1.0e-08: true
* Function Calls (f): 11
* Jacobian Calls (df/dx): 11
[编辑:调整了解决方案,将正确的梯度计算纳入g()]几乎从零开始,维基百科的,因为它对我有好处,下面的代码似乎可以工作。我加了一个
λ₀s
参数设置为ProjLagrange
函数,这样它就可以接受初始乘法器λ
值的向量(我看到您将它们初始化为1.0
,但我认为这更通用)。(请注意,这尚未针对性能进行优化!)
给我
julia> res = ProjLagrange(x₀_test, λ₀s_test, gs_test, n_it)
Results of Nonlinear Solver Algorithm
* Algorithm: Trust-region with dogleg and autoscaling
* Starting Point: [1000.0, 1.0, 1.0, 1.0]
* Zero: [9.800027199717013, -49.52026655749088, 51.520266557490885, -0.050887973682118504]
* Inf-norm of residuals: 0.000000
* Iterations: 10
* Convergence: true
* |x - x'| < 0.0e+00: false
* |f(x)| < 1.0e-08: true
* Function Calls (f): 11
* Jacobian Calls (df/dx): 11
julia>res=ProjLagrange(x₀_试验,λ₀s_测试、gs_测试、n_测试)
非线性求解算法的结果
*算法:带狗腿和自动缩放的信赖域
*起点:[1000.0,1.0,1.0,1.0]
*零:[9.800027199717013,-49.52026655749088,51.520266557490885,-0.0508879736682118504]
*残差的Inf范数:0.000000
*迭代次数:10次
*收敛性:正确
*| x-x'|<0.0e+00:错误
*| f(x)|<1.0e-08:正确
*函数调用(f):11
*雅可比调用(df/dx):11
using NLsolve, ForwardDiff, LinearAlgebra
function ProjLagrange(x₀, λ₀s, gs, n_it)
# distance function from x₀ and its gradients
f(x) = norm(x - x₀)
∇f(x) = ForwardDiff.gradient(f, x)
# gradients of the constraints
∇gs = [x -> ForwardDiff.gradient(g, x) for g in gs]
# Form the auxiliary function and its gradients
ℒ(x,λs) = f(x) - sum(λ * g(x) for (λ,g) in zip(λs,gs))
∂ℒ∂x(x,λs) = ∇f(x) - sum(λ * ∇g(x) for (λ,∇g) in zip(λs,∇gs))
∂ℒ∂λ(x,λs) = [g(x) for g in gs]
# as a function of a single argument
nx = length(x₀)
ℒ(v) = ℒ(v[1:nx], v[nx+1:end])
∇ℒ(v) = vcat(∂ℒ∂x(v[1:nx], v[nx+1:end]), ∂ℒ∂λ(v[1:nx], v[nx+1:end]))
# and solve
v₀ = vcat(x₀, λ₀s)
nlsolve(∇ℒ, v₀, iterations=n_it)
end
# test
gs_test = [x -> x[1]^2 + x[2] - x[3] + 5]
λ₀s_test = [1.0]
x₀_test = [1000.0, 1.0, 1.0]
n_it = 100
res = ProjLagrange(x₀_test, λ₀s_test, gs_test, n_it)
julia> res = ProjLagrange(x₀_test, λ₀s_test, gs_test, n_it)
Results of Nonlinear Solver Algorithm
* Algorithm: Trust-region with dogleg and autoscaling
* Starting Point: [1000.0, 1.0, 1.0, 1.0]
* Zero: [9.800027199717013, -49.52026655749088, 51.520266557490885, -0.050887973682118504]
* Inf-norm of residuals: 0.000000
* Iterations: 10
* Convergence: true
* |x - x'| < 0.0e+00: false
* |f(x)| < 1.0e-08: true
* Function Calls (f): 11
* Jacobian Calls (df/dx): 11