Optimization.jl
Optimization.jl copied to clipboard
NamedTuple parameters don't work with AutoModelingToolkit()
I defined an OptimizationFunction
and OptimizationProblem
which expect the parameters as a named tuple (which is convenient when there are a bunch of parameters, since they can be referred to by name inside the function). The following MWE, using AutoModelingForwardDiff()
, works fine:
using Optimization, OptimizationOptimJL, ModelingToolkit, ForwardDiff
ftest(u, params) = sum(abs2, params.y .- u' * params.M * u)
p = (;y = randn(5), M = randn(5, 5))
u0 = randn(5)
f = OptimizationFunction(ftest, Optimization.AutoForwardDiff())
prob = OptimizationProblem(f, u0, p)
sol = solve(prob, LBFGS())
but if I change it to use AutoModelingToolkit()
, attempting to solve the problem gives the following error:
f = OptimizationFunction(ftest, Optimization.AutoModelingToolkit())
prob = OptimizationProblem(f, u0, p)
sol = solve(prob, LBFGS())
ERROR: type Array has no field y
Stacktrace:
[1] getproperty
@ .\Base.jl:42 [inlined]
[2] ftest(u::Vector{Num}, params::Vector{Num})
@ Main .\REPL[43]:1
[3] (::OptimizationFunction{true, Optimization.AutoModelingToolkit, typeof(ftest), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing})(::Vector{Num}, ::Vararg{Vector{Num}})
@ SciMLBase C:\Users\sam.urmy\.julia\packages\SciMLBase\2oQlD\src\scimlfunctions.jl:3261
[4] modelingtoolkitize(prob::OptimizationProblem{true, OptimizationFunction{true, Optimization.AutoModelingToolkit, typeof(ftest), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}}, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ ModelingToolkit C:\Users\sam.urmy\.julia\packages\ModelingToolkit\YHIP8\src\systems\diffeqs\modelingtoolkitize.jl:235
[5] modelingtoolkitize(prob::OptimizationProblem{true, OptimizationFunction{true, Optimization.AutoModelingToolkit, typeof(ftest), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}}, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}})
@ ModelingToolkit C:\Users\sam.urmy\.julia\packages\ModelingToolkit\YHIP8\src\systems\diffeqs\modelingtoolkitize.jl:225
[6] instantiate_function(f::Function, x::Vector{Float64}, adtype::Optimization.AutoModelingToolkit, p::NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}}, num_cons::Int64)
@ Optimization C:\Users\sam.urmy\.julia\packages\Optimization\6nIwk\src\function\mtk.jl:10
[7] instantiate_function(f::Function, x::Vector{Float64}, adtype::Optimization.AutoModelingToolkit, p::NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}})
@ Optimization C:\Users\sam.urmy\.julia\packages\Optimization\6nIwk\src\function\mtk.jl:9
[8] ___solve(prob::OptimizationProblem{true, OptimizationFunction{true, Optimization.AutoModelingToolkit, typeof(ftest), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}}, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, opt::Newton{LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64,
Base.RefValue{Bool}}}, data::Base.Iterators.Cycle{Tuple{Optimization.NullData}}; callback::Function, maxiters::Nothing, maxtime::Nothing, abstol::Nothing, reltol::Nothing, progress::Bool, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ OptimizationOptimJL C:\Users\sam.urmy\.julia\packages\OptimizationOptimJL\fdrJg\src\OptimizationOptimJL.jl:94
[9] ___solve(prob::OptimizationProblem{true, OptimizationFunction{true, Optimization.AutoModelingToolkit, typeof(ftest), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}}, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, opt::Newton{LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64,
Base.RefValue{Bool}}}, data::Base.Iterators.Cycle{Tuple{Optimization.NullData}})
@ OptimizationOptimJL C:\Users\sam.urmy\.julia\packages\OptimizationOptimJL\fdrJg\src\OptimizationOptimJL.jl:69
[10] __solve(prob::OptimizationProblem{true, OptimizationFunction{true, Optimization.AutoModelingToolkit, typeof(ftest), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}}, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, opt::Newton{LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64, Base.RefValue{Bool}}}, data::Base.Iterators.Cycle{Tuple{Optimization.NullData}}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ OptimizationOptimJL C:\Users\sam.urmy\.julia\packages\OptimizationOptimJL\fdrJg\src\OptimizationOptimJL.jl:56
[11] __solve(prob::OptimizationProblem{true, OptimizationFunction{true, Optimization.AutoModelingToolkit, typeof(ftest), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}}, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, opt::Newton{LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64, Base.RefValue{Bool}}}, data::Base.Iterators.Cycle{Tuple{Optimization.NullData}}) (repeats 2 times)
@ OptimizationOptimJL C:\Users\sam.urmy\.julia\packages\OptimizationOptimJL\fdrJg\src\OptimizationOptimJL.jl:44
[12] solve(::OptimizationProblem{true, OptimizationFunction{true, Optimization.AutoModelingToolkit, typeof(ftest), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}}, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, ::Newton{LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64, Base.RefValue{Bool}}}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ SciMLBase C:\Users\sam.urmy\.julia\packages\SciMLBase\2oQlD\src\solve.jl:71
[13] solve(::OptimizationProblem{true, OptimizationFunction{true, Optimization.AutoModelingToolkit, typeof(ftest), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}}, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, ::Newton{LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64, Base.RefValue{Bool}}})
@ SciMLBase C:\Users\sam.urmy\.julia\packages\SciMLBase\2oQlD\src\solve.jl:71
[14] top-level scope
@ REPL[50]:1
It looks like the modeling-toolkitized OptimizationFunction
is calling ftest
with a vector of parameters instead of a NamedTuple. is this a bug?
It is indeed a bug,modelingtoolkitize
called when AutoModelingToolkit
is used, creates a new vector for the parameters and the names of the parameters are lost. For now you can rewrite ftest
as ftest(u, params) = sum(abs2, params[1] .- u' * params[2] * u)
and it should work.
Ok thanks, good to know. The workaround does not work either, however...defining ftest
as you suggest produces this error when calling solve
:
ERROR: DimensionMismatch("dimensions must match: a has dims (Base.OneTo(5), Base.OneTo(5)), must have singleton at dim 2")
Stacktrace:
[1] promote_shape
@ .\indices.jl:183 [inlined]
[2] promote_shape
@ .\indices.jl:174 [inlined]
[3] promote_shape(a::Vector{Float64}, b::Matrix{Float64})
@ Base .\indices.jl:169
[4] +(A::Vector{Float64}, Bs::Matrix{Float64})
@ Base .\arraymath.jl:45
[5] macro expansion
@ C:\Users\sam.urmy\.julia\packages\SymbolicUtils\vnuIf\src\code.jl:394 [inlined]
[6] macro expansion
@ C:\Users\sam.urmy\.julia\packages\Symbolics\9psaj\src\build_function.jl:504 [inlined]
[7] macro expansion
@ C:\Users\sam.urmy\.julia\packages\SymbolicUtils\vnuIf\src\code.jl:351 [inlined]
[8] macro expansion
@ C:\Users\sam.urmy\.julia\packages\RuntimeGeneratedFunctions\KrkGo\src\RuntimeGeneratedFunctions.jl:129 [inlined]
[9] macro expansion
@ .\none:0 [inlined]
[10] generated_callfunc
@ .\none:0 [inlined]
[11] (::RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2), Symbolics.var"#_RGF_ModTag", Symbolics.var"#_RGF_ModTag", (0x5ebc1601, 0xf66d7688, 0x616faa43, 0xc9fdb05a, 0x91c11a17)})(::Vector{Float64}, ::Vector{Float64}, ::NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}})
@ RuntimeGeneratedFunctions C:\Users\sam.urmy\.julia\packages\RuntimeGeneratedFunctions\KrkGo\src\RuntimeGeneratedFunctions.jl:117
[12] (::Optimization.var"#grad#106"{NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}}, RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2), Symbolics.var"#_RGF_ModTag", Symbolics.var"#_RGF_ModTag", (0x5ebc1601, 0xf66d7688, 0x616faa43, 0xc9fdb05a, 0x91c11a17)}})(J::Vector{Float64}, u::Vector{Float64})
@ Optimization C:\Users\sam.urmy\.julia\packages\Optimization\i9NGR\src\function\mtk.jl:16
[13] (::OptimizationOptimJL.var"#5#13"{OptimizationProblem{true, OptimizationFunction{true, Optimization.AutoModelingToolkit, typeof(ftest), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}}, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, OptimizationOptimJL.var"#4#12"{OptimizationProblem{true, OptimizationFunction{true, Optimization.AutoModelingToolkit, typeof(ftest), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}}, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, OptimizationFunction{true, Optimization.AutoModelingToolkit, typeof(ftest), Optimization.var"#grad#106"{NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}}, RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2), Symbolics.var"#_RGF_ModTag", Symbolics.var"#_RGF_ModTag", (0x5ebc1601, 0xf66d7688, 0x616faa43, 0xc9fdb05a, 0x91c11a17)}}, Optimization.var"#hess#107"{NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}}, RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2), Symbolics.var"#_RGF_ModTag", Symbolics.var"#_RGF_ModTag", (0xc01061cf, 0xd949a7ab, 0xc58284e0, 0x80ec5617, 0x3f698c48)}}, Optimization.var"#97#108"{Optimization.AutoModelingToolkit}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Expr, Nothing}}, OptimizationFunction{true, Optimization.AutoModelingToolkit, typeof(ftest), Optimization.var"#grad#106"{NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}}, RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2), Symbolics.var"#_RGF_ModTag", Symbolics.var"#_RGF_ModTag", (0x5ebc1601, 0xf66d7688, 0x616faa43, 0xc9fdb05a, 0x91c11a17)}}, Optimization.var"#hess#107"{NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}}, RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2), Symbolics.var"#_RGF_ModTag", Symbolics.var"#_RGF_ModTag", (0xc01061cf, 0xd949a7ab, 0xc58284e0, 0x80ec5617, 0x3f698c48)}}, Optimization.var"#97#108"{Optimization.AutoModelingToolkit}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Expr, Nothing}})(G::Vector{Float64}, θ::Vector{Float64})
@ OptimizationOptimJL C:\Users\sam.urmy\.julia\packages\OptimizationOptimJL\fdrJg\src\OptimizationOptimJL.jl:106
[14] value_gradient!!(obj::TwiceDifferentiable{Float64, Vector{Float64}, Matrix{Float64}, Vector{Float64}}, x::Vector{Float64})
@ NLSolversBase C:\Users\sam.urmy\.julia\packages\NLSolversBase\cfJrN\src\interface.jl:82
[15] initial_state(method::LBFGS{Nothing, LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64, Base.RefValue{Bool}}, Optim.var"#19#21"}, options::Optim.Options{Float64, OptimizationOptimJL.var"#_cb#11"{OptimizationOptimJL.var"#9#17", LBFGS{Nothing, LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64, Base.RefValue{Bool}}, Optim.var"#19#21"}, Base.Iterators.Cycle{Tuple{Optimization.NullData}}}}, d::TwiceDifferentiable{Float64, Vector{Float64}, Matrix{Float64}, Vector{Float64}}, initial_x::Vector{Float64})
@ Optim C:\Users\sam.urmy\.julia\packages\Optim\6Lpjy\src\multivariate\solvers\first_order\l_bfgs.jl:164
[16] optimize(d::TwiceDifferentiable{Float64, Vector{Float64}, Matrix{Float64}, Vector{Float64}}, initial_x::Vector{Float64}, method::LBFGS{Nothing, LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64, Base.RefValue{Bool}}, Optim.var"#19#21"}, options::Optim.Options{Float64, OptimizationOptimJL.var"#_cb#11"{OptimizationOptimJL.var"#9#17", LBFGS{Nothing, LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64, Base.RefValue{Bool}}, Optim.var"#19#21"}, Base.Iterators.Cycle{Tuple{Optimization.NullData}}}})
@ Optim C:\Users\sam.urmy\.julia\packages\Optim\6Lpjy\src\multivariate\optimize\optimize.jl:36
[17] ___solve(prob::OptimizationProblem{true, OptimizationFunction{true, Optimization.AutoModelingToolkit, typeof(ftest), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}}, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, opt::LBFGS{Nothing, LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64, Base.RefValue{Bool}}, Optim.var"#19#21"}, data::Base.Iterators.Cycle{Tuple{Optimization.NullData}}; callback::Function, maxiters::Nothing, maxtime::Nothing, abstol::Nothing, reltol::Nothing, progress::Bool, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ OptimizationOptimJL C:\Users\sam.urmy\.julia\packages\OptimizationOptimJL\fdrJg\src\OptimizationOptimJL.jl:143
[18] ___solve
@ C:\Users\sam.urmy\.julia\packages\OptimizationOptimJL\fdrJg\src\OptimizationOptimJL.jl:69 [inlined]
[19] #__solve#2
@ C:\Users\sam.urmy\.julia\packages\OptimizationOptimJL\fdrJg\src\OptimizationOptimJL.jl:56 [inlined]
[20] __solve (repeats 2 times)
@ C:\Users\sam.urmy\.julia\packages\OptimizationOptimJL\fdrJg\src\OptimizationOptimJL.jl:44 [inlined]
[21] #solve#492
@ C:\Users\sam.urmy\.julia\packages\SciMLBase\IJbT7\src\solve.jl:71 [inlined]
[22] solve(::OptimizationProblem{true, OptimizationFunction{true, Optimization.AutoModelingToolkit, typeof(ftest), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, NamedTuple{(:y, :M), Tuple{Vector{Float64}, Matrix{Float64}}}, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, ::LBFGS{Nothing, LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64, Base.RefValue{Bool}}, Optim.var"#19#21"})
@ SciMLBase C:\Users\sam.urmy\.julia\packages\SciMLBase\IJbT7\src\solve.jl:71
[23] top-level scope
@ REPL[14]:1
Oh yeah, looks like MTK has trouble with vector/matrix parameters. So as temporary workaround you can avoid passing p
to OptimizationProblem
and rewrite ftest
as ftest(u, params) = sum(abs2, p[1] .- u' * p[2] * u)
using the global p
and it should work
julia> f = OptimizationFunction(ftest, Optimization.AutoModelingToolkit())
(::OptimizationFunction{true, Optimization.AutoModelingToolkit, typeof(ftest), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}) (generic function with 1 method)
julia> prob = OptimizationProblem(f, u0, nothing)
OptimizationProblem. In-place: true
u0: 5-element Vector{Float64}:
-0.43014445861378714
0.43665425553480663
-0.18704907297838141
0.24850382091203801
-2.277854186675249
julia> sol = solve(prob, LBFGS())
u: 5-element Vector{Float64}:
-0.6086522984631275
0.6079328096708877
-0.5578515167049973
0.2941979554692975
-1.9204538047235244
julia> f = OptimizationFunction(ftest, Optimization.AutoForwardDiff())
(::OptimizationFunction{true, Optimization.AutoForwardDiff{nothing}, typeof(ftest), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}) (generic function with 1 method)
julia> prob = OptimizationProblem(f, u0, nothing)
OptimizationProblem. In-place: true
u0: 5-element Vector{Float64}:
-0.43014445861378714
0.43665425553480663
-0.18704907297838141
0.24850382091203801
-2.277854186675249
julia> sol = solve(prob, LBFGS())
u: 5-element Vector{Float64}:
-0.6086522984631274
0.6079328096708878
-0.5578515167049976
0.2941979554692975
-1.9204538047235242