ExaModels
ExaModels.ExaModels — ModuleExaModelsAn algebraic modeling and automatic differentiation tool in Julia Language, specialized for SIMD abstraction of nonlinear programs.
For more information, please visit https://github.com/exanauts/ExaModels.jl
ExaModels.AdjointNode1 — TypeAdjointNode1{F, T, I}A node with one child for first-order forward pass tree
Fields:
x::T: function valuey::T: first-order sensitivityinner::I: children
ExaModels.AdjointNode2 — TypeAdjointNode2{F, T, I1, I2}A node with two children for first-order forward pass tree
Fields:
x::T: function valuey1::T: first-order sensitivity w.r.t. first argumenty2::T: first-order sensitivity w.r.t. second argumentinner1::I1: children #1inner2::I2: children #2
ExaModels.AdjointNodeSource — TypeAdjointNodeSource{VT}A source of AdjointNode. adjoint_node_source[i] returns an AdjointNodeVar at index i.
Fields:
inner::VT: variable vector
ExaModels.AdjointNodeVar — TypeAdjointNodeVar{I, T}A variable node for first-order forward pass tree
Fields:
i::I: indexx::T: value
ExaModels.AdjointNull — TypeNullA null node
ExaModels.Compressor — TypeCompressor{I}Data structure for the sparse index
Fields:
inner::I: stores the sparse index as a tuple form
ExaModels.ExaCore — TypeExaCore([array_eltype::Type; backend = backend, minimize = true])
Returns an intermediate data object ExaCore, which later can be used for creating ExaModel
Example
julia> using ExaModels
julia> c = ExaCore()
An ExaCore
Float type: ...................... Float64
Array type: ...................... Vector{Float64}
Backend: ......................... Nothing
number of objective patterns: .... 0
number of constraint patterns: ... 0
julia> c = ExaCore(Float32)
An ExaCore
Float type: ...................... Float32
Array type: ...................... Vector{Float32}
Backend: ......................... Nothing
number of objective patterns: .... 0
number of constraint patterns: ... 0
julia> using CUDA
julia> c = ExaCore(Float32; backend = CUDABackend())
An ExaCore
Float type: ...................... Float32
Array type: ...................... CUDA.CuArray{Float32, 1, CUDA.DeviceMemory}
Backend: ......................... CUDA.CUDAKernels.CUDABackend
number of objective patterns: .... 0
number of constraint patterns: ... 0ExaModels.ExaModel — MethodExaModel(core)Returns an ExaModel object, which can be solved by nonlinear optimization solvers within JuliaSmoothOptimizer ecosystem, such as NLPModelsIpopt or MadNLP.
Example
julia> using ExaModels
julia> c = ExaCore(); # create an ExaCore object
julia> x = variable(c, 1:10); # create variables
julia> objective(c, x[i]^2 for i in 1:10); # set objective function
julia> m = ExaModel(c) # creat an ExaModel object
An ExaModel{Float64, Vector{Float64}, ...}
Problem name: Generic
All variables: ████████████████████ 10 All constraints: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0
free: ████████████████████ 10 free: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0
lower: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0 lower: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0
upper: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0 upper: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0
low/upp: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0 low/upp: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0
fixed: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0 fixed: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0
infeas: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0 infeas: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0
nnzh: ( 81.82% sparsity) 10 linear: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0
nonlinear: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0
nnzj: (------% sparsity)
julia> using NLPModelsIpopt
julia> result = ipopt(m; print_level=0) # solve the problem
"Execution stats: first-order stationary"
ExaModels.Node1 — TypeNode1{F, I}A node with one child for symbolic expression tree
Fields:
inner::I: children
ExaModels.Node2 — TypeNode2{F, I1, I2}A node with two children for symbolic expression tree
Fields:
inner1::I1: children #1inner2::I2: children #2
ExaModels.Null — TypeNullA null node
ExaModels.ParIndexed — TypeParIndexed{I, J}A parameterized data node
Fields:
inner::I: parameter for the data
ExaModels.ParSource — TypeParSourceA source of parameterized data
ExaModels.SIMDFunction — TypeSIMDFunction(gen::Base.Generator, o0 = 0, o1 = 0, o2 = 0)Returns a SIMDFunction using the gen.
Arguments:
gen: an iterable function specified inBase.Generatorformato0: offset for the function evaluationo1: offset for the derivative evalutiono2: offset for the second-order derivative evalution
ExaModels.SecondAdjointNode1 — TypeSecondAdjointNode1{F, T, I}A node with one child for second-order forward pass tree
Fields:
x::T: function valuey::T: first-order sensitivityh::T: second-order sensitivityinner::I: DESCRIPTION
ExaModels.SecondAdjointNode2 — TypeSecondAdjointNode2{F, T, I1, I2}A node with one child for second-order forward pass tree
Fields:
x::T: function valuey1::T: first-order sensitivity w.r.t. first argumenty2::T: first-order sensitivity w.r.t. first argumenth11::T: second-order sensitivity w.r.t. first argumenth12::T: second-order sensitivity w.r.t. first and second argumenth22::T: second-order sensitivity w.r.t. second argumentinner1::I1: children #1inner2::I2: children #2
ExaModels.SecondAdjointNodeSource — TypeSecondAdjointNodeSource{VT}A source of AdjointNode. adjoint_node_source[i] returns an AdjointNodeVar at index i.
Fields:
inner::VT: variable vector
ExaModels.SecondAdjointNodeVar — TypeSecondAdjointNodeVar{I, T}A variable node for first-order forward pass tree
Fields:
i::I: indexx::T: value
ExaModels.SecondAdjointNull — TypeNullA null node
ExaModels.Var — TypeVar{I}A variable node for symbolic expression tree
Fields:
i::I: (parameterized) index
ExaModels.VarSource — TypeVarSourceA source of variable nodes
ExaModels.WrapperNLPModel — MethodWrapperNLPModel(VT, m)Returns a WrapperModel{T,VT} wrapping m <: AbstractNLPModel{T}
ExaModels.WrapperNLPModel — MethodWrapperNLPModel(m)Returns a WrapperModel{Float64,Vector{64}} wrapping m
ExaModels.constraint! — Methodconstraint!(c, c1, expr, pars)Expands the existing constraint c1 in c by adding addtional constraints terms specified by expr and pars.
ExaModels.constraint! — Methodconstraint!(c::C, c1, gen::Base.Generator) where {C<:ExaCore}Expands the existing constraint c1 in c by adding additional constraint terms specified by a generator.
Arguments
c::C: The model to which the constraints are added.c1: An initial constraint value or expression.gen::Base.Generator: A generator that produces the pair of constraint index and term to be added.
Example
julia> using ExaModels
julia> c = ExaCore();
julia> x = variable(c, 10);
julia> c1 = constraint(c, x[i] + x[i+1] for i=1:9; lcon = -1, ucon = (1+i for i=1:9));
julia> constraint!(c, c1, i => sin(x[i+1]) for i=4:6)
Constraint Augmentation
s.t. (...)
g♭ ≤ (...) + ∑_{p ∈ P} h(x,θ,p) ≤ g♯
where |P| = 3ExaModels.constraint — Methodconstraint(core, n; start = 0, lcon = 0, ucon = 0)Adds empty constraints of dimension n, so that later the terms can be added with constraint!.
ExaModels.constraint — Methodconstraint(core, generator; start = 0, lcon = 0, ucon = 0)Adds constraints specified by a generator to core, and returns an Constraint object.
Keyword Arguments
start: The initial guess of the solution. Can either beNumber,AbstractArray, orGenerator.lcon: The constraint lower bound. Can either beNumber,AbstractArray, orGenerator.ucon: The constraint upper bound. Can either beNumber,AbstractArray, orGenerator.
Example
julia> using ExaModels
julia> c = ExaCore();
julia> x = variable(c, 10);
julia> constraint(c, x[i] + x[i+1] for i=1:9; lcon = -1, ucon = (1+i for i=1:9))
Constraint
s.t. (...)
g♭ ≤ [g(x,θ,p)]_{p ∈ P} ≤ g♯
where |P| = 9ExaModels.constraint — Methodconstraint(core, expr [, pars]; start = 0, lcon = 0, ucon = 0)Adds constraints specified by a expr and pars to core, and returns an Constraint object.
ExaModels.drpass — Methoddrpass(d::D, y, adj)Performs dense gradient evaluation via the reverse pass on the computation (sub)graph formed by forward pass
Arguments:
d: first-order computation (sub)graphy: result vectoradj: adjoint propagated up to the current node
ExaModels.gradient! — Methodgradient!(y, f, x, adj)Performs dense gradient evalution
Arguments:
y: result vectorf: the function to be differentiated inSIMDFunctionformatx: variable vectoradj: initial adjoint
ExaModels.grpass — Methodgrpass(d::D, comp, y, o1, cnt, adj)Performs dsparse gradient evaluation via the reverse pass on the computation (sub)graph formed by forward pass
Arguments:
d: first-order computation (sub)graphcomp: aCompressor, which helps map counter to sparse vector indexy: result vectoro1: index offsetcnt: counteradj: adjoint propagated up to the current node
ExaModels.hdrpass — Methodhdrpass(t1::T1, t2::T2, comp, y1, y2, o2, cnt, adj)Performs sparse hessian evaluation ((df1/dx)(df2/dx)' portion) via the reverse pass on the computation (sub)graph formed by second-order forward pass
Arguments:
t1: second-order computation (sub)graph regarding f1t2: second-order computation (sub)graph regarding f2comp: aCompressor, which helps map counter to sparse vector indexy1: result vector #1y2: result vector #2 (only used when evaluating sparsity)o2: index offsetcnt: counteradj: second adjoint propagated up to the current node
ExaModels.jrpass — Methodjrpass(d::D, comp, i, y1, y2, o1, cnt, adj)Performs sparse jacobian evaluation via the reverse pass on the computation (sub)graph formed by forward pass
Arguments:
d: first-order computation (sub)graphcomp: aCompressor, which helps map counter to sparse vector indexi: constraint index (this isi-th constraint)y1: result vector #1y2: result vector #2 (only used when evaluating sparsity)o1: index offsetcnt: counteradj: adjoint propagated up to the current node
ExaModels.multipliers — Methodmultipliers(result, y)Returns the multipliers for constraints y associated with result, obtained by solving the model.
Example
julia> using ExaModels, NLPModelsIpopt
julia> c = ExaCore();
julia> x = variable(c, 1:10, lvar = -1, uvar = 1);
julia> objective(c, (x[i]-2)^2 for i in 1:10);
julia> y = constraint(c, x[i] + x[i+1] for i=1:9; lcon = -1, ucon = (1+i for i=1:9));
julia> m = ExaModel(c);
julia> result = ipopt(m; print_level=0);
julia> val = multipliers(result, y);
julia> val[1] ≈ 0.81933930
trueExaModels.multipliers_L — Methodmultipliers_L(result, x)Returns the multipliers_L for variable x associated with result, obtained by solving the model.
Example
julia> using ExaModels, NLPModelsIpopt
julia> c = ExaCore();
julia> x = variable(c, 1:10, lvar = -1, uvar = 1);
julia> objective(c, (x[i]-2)^2 for i in 1:10);
julia> m = ExaModel(c);
julia> result = ipopt(m; print_level=0);
julia> val = multipliers_L(result, x);
julia> isapprox(val, fill(0, 10), atol=sqrt(eps(Float64)), rtol=Inf)
trueExaModels.multipliers_U — Methodmultipliers_U(result, x)Returns the multipliers_U for variable x associated with result, obtained by solving the model.
Example
julia> using ExaModels, NLPModelsIpopt
julia> c = ExaCore();
julia> x = variable(c, 1:10, lvar = -1, uvar = 1);
julia> objective(c, (x[i]-2)^2 for i in 1:10);
julia> m = ExaModel(c);
julia> result = ipopt(m; print_level=0);
julia> val = multipliers_U(result, x);
julia> isapprox(val, fill(2, 10), atol=sqrt(eps(Float64)), rtol=Inf)
trueExaModels.objective — Methodobjective(core::ExaCore, generator)Adds objective terms specified by a generator to core, and returns an Objective object. Note: it is assumed that the terms are summed.
Example
julia> using ExaModels
julia> c = ExaCore();
julia> x = variable(c, 10);
julia> objective(c, x[i]^2 for i=1:10)
Objective
min (...) + ∑_{p ∈ P} f(x,θ,p)
where |P| = 10ExaModels.objective — Methodobjective(core::ExaCore, expr [, pars])Adds objective terms specified by a expr and pars to core, and returns an Objective object.
ExaModels.parameter — Methodparameter(core, start::AbstractArray)Adds parameters with initial values specified by start, and returns Parameter object.
Example
julia> using ExaModels
julia> c = ExaCore();
julia> θ = parameter(c, ones(10))
Parameter
θ ∈ R^{10}ExaModels.set_parameter! — Methodset_parameter!(core, param, values)Updates the values of parameters in the core.
Example
julia> using ExaModels
julia> c = ExaCore();
julia> p = parameter(c, ones(5))
Parameter
θ ∈ R^{5}
julia> set_parameter!(c, p, rand(5)) # Update with new valuesExaModels.sgradient! — Methodsgradient!(y, f, x, adj)
Performs sparse gradient evalution
Arguments:
y: result vectorf: the function to be differentiated inSIMDFunctionformatx: variable vectoradj: initial adjoint
ExaModels.shessian! — Methodshessian!(y1, y2, f, x, adj1, adj2)Performs sparse jacobian evalution
Arguments:
y1: result vector #1y2: result vector #2 (only used when evaluating sparsity)f: the function to be differentiated inSIMDFunctionformatx: variable vectoradj1: initial first adjointadj2: initial second adjoint
ExaModels.sjacobian! — Methodsjacobian!(y1, y2, f, x, adj)Performs sparse jacobian evalution
Arguments:
y1: result vector #1y2: result vector #2 (only used when evaluating sparsity)f: the function to be differentiated inSIMDFunctionformatx: variable vectoradj: initial adjoint
ExaModels.solution — Methodsolution(result, x)Returns the solution for variable x associated with result, obtained by solving the model.
Example
julia> using ExaModels, NLPModelsIpopt
julia> c = ExaCore();
julia> x = variable(c, 1:10, lvar = -1, uvar = 1);
julia> objective(c, (x[i]-2)^2 for i in 1:10);
julia> m = ExaModel(c);
julia> result = ipopt(m; print_level=0);
julia> val = solution(result, x);
julia> isapprox(val, fill(1, 10), atol=sqrt(eps(Float64)), rtol=Inf)
trueExaModels.variable — Methodvariable(core, dims...; start = 0, lvar = -Inf, uvar = Inf)Adds variables with dimensions specified by dims to core, and returns Variable object. dims can be either Integer or UnitRange.
Keyword Arguments
start: The initial guess of the solution. Can either beNumber,AbstractArray, orGenerator.lvar: The variable lower bound. Can either beNumber,AbstractArray, orGenerator.uvar: The variable upper bound. Can either beNumber,AbstractArray, orGenerator.
Example
julia> using ExaModels
julia> c = ExaCore();
julia> x = variable(c, 10; start = (sin(i) for i=1:10))
Variable
x ∈ R^{10}
julia> y = variable(c, 2:10, 3:5; lvar = zeros(9,3), uvar = ones(9,3))
Variable
x ∈ R^{9 × 3}
ExaModels.@register_bivariate — Macroregister_bivariate(f, df1, df2, ddf11, ddf12, ddf22)Register a bivariate function f to ExaModels, so that it can be used within objective and constraint expressions
Arguments:
f: functiondf1: derivative function (w.r.t. first argument)df2: derivative function (w.r.t. second argument)ddf11: second-order derivative funciton (w.r.t. first argument)ddf12: second-order derivative funciton (w.r.t. first and second argument)ddf22: second-order derivative funciton (w.r.t. second argument)
Example
julia> using ExaModels
julia> relu23(x,y) = (x > 0 || y > 0) ? (x + y)^3 : zero(x)
relu23 (generic function with 1 method)
julia> drelu231(x,y) = (x > 0 || y > 0) ? 3 * (x + y)^2 : zero(x)
drelu231 (generic function with 1 method)
julia> drelu232(x,y) = (x > 0 || y > 0) ? 3 * (x + y)^2 : zero(x)
drelu232 (generic function with 1 method)
julia> ddrelu2311(x,y) = (x > 0 || y > 0) ? 6 * (x + y) : zero(x)
ddrelu2311 (generic function with 1 method)
julia> ddrelu2312(x,y) = (x > 0 || y > 0) ? 6 * (x + y) : zero(x)
ddrelu2312 (generic function with 1 method)
julia> ddrelu2322(x,y) = (x > 0 || y > 0) ? 6 * (x + y) : zero(x)
ddrelu2322 (generic function with 1 method)
julia> @register_bivariate(relu23, drelu231, drelu232, ddrelu2311, ddrelu2312, ddrelu2322)ExaModels.@register_univariate — Macro@register_univariate(f, df, ddf)Register a univariate function f to ExaModels, so that it can be used within objective and constraint expressions
Arguments:
f: functiondf: derivative functionddf: second-order derivative funciton
Example
julia> using ExaModels
julia> relu3(x) = x > 0 ? x^3 : zero(x)
relu3 (generic function with 1 method)
julia> drelu3(x) = x > 0 ? 3*x^2 : zero(x)
drelu3 (generic function with 1 method)
julia> ddrelu3(x) = x > 0 ? 6*x : zero(x)
ddrelu3 (generic function with 1 method)
julia> @register_univariate(relu3, drelu3, ddrelu3)