Getting Started

ExaModels can create nonlinear prgogramming models and allows solving the created models using NLP solvers (in particular, those that are interfaced with NLPModels, such as NLPModelsIpopt and MadNLP. This documentation page will describe how to use ExaModels to model and solve nonlinear optimization problems.

We will first consider the following simple nonlinear program [3]:

\[\begin{aligned} \min_{\{x_i\}_{i=0}^N} &\sum_{i=2}^N 100(x_{i-1}^2-x_i)^2+(x_{i-1}-1)^2\\ \text{s.t.} & 3x_{i+1}^3+2x_{i+2}-5+\sin(x_{i+1}-x_{i+2})\sin(x_{i+1}+x_{i+2})+4x_{i+1}-x_i e^{x_i-x_{i+1}}-3 = 0 \end{aligned}\]

We will follow the following Steps to create the model/solve this optimization problem.

  • Step 0: import ExaModels.jl
  • Step 1: create a ExaCore object, wherein we can progressively build an optimization model.
  • Step 2: create optimization variables with variable, while attaching it to previously created ExaCore.
  • Step 3 (interchangable with Step 3): create objective function with objective, while attaching it to previously created ExaCore.
  • Step 4 (interchangable with Step 2): create constraints with constraint, while attaching it to previously created ExaCore.
  • Step 5: create an ExaModel based on the ExaCore.

Now, let's jump right in. We import ExaModels via (Step 0):

using ExaModels

Now, all the functions that are necessary for creating model are imported to into Main.

An ExaCore object can be created simply by (Step 1):

c = ExaCore()
An ExaCore

  Float type: ...................... Float64
  Array type: ...................... Vector{Float64}
  Backend: ......................... Nothing

  number of objective patterns: .... 0
  number of constraint patterns: ... 0

This is where our optimziation model information will be progressively stored. This object is not yet an NLPModel, but it will essentially store all the necessary information.

Now, let's create the optimziation variables. From the problem definition, we can see that we will need $N$ scalar variables. We will choose $N=10$, and create the variable $x\in\mathbb{R}^{N}$ with the follwoing command:

N = 10
x = variable(c, N; start = (mod(i, 2) == 1 ? -1.2 : 1.0 for i = 1:N))
Variable

  x ∈ R^{10}

This creates the variable x, which we will be able to refer to when we create constraints/objective constraionts. Also, this modifies the information in the ExaCore object properly so that later an optimization model can be properly created with the necessary information. Observe that we have used the keyword argument start to specify the initial guess for the solution. The variable upper and lower bounds can be specified in a similar manner.

The objective can be set as follows:

objective(c, 100 * (x[i-1]^2 - x[i])^2 + (x[i-1] - 1)^2 for i = 2:N)
Objective

  min (...) + ∑_{p ∈ P} f(x,p)

  where |P| = 9

The constraints can be set as follows:

constraint(
    c,
    3x[i+1]^3 + 2 * x[i+2] - 5 + sin(x[i+1] - x[i+2])sin(x[i+1] + x[i+2]) + 4x[i+1] -
    x[i]exp(x[i] - x[i+1]) - 3 for i = 1:N-2
)
Constraint

  s.t. (...)
       g♭ ≤ [g(x,p)]_{p ∈ P} ≤ g♯

  where |P| = 8

Finally, we are ready to create an ExaModel from the data we have collected in ExaCore. Since ExaCore includes all the necessary information, we can do this simply by:

m = ExaModel(c)
An ExaModel{Float64, Vector{Float64}, ...}

  Problem name: Generic
   All variables: ████████████████████ 10     All constraints: ████████████████████ 8     
            free: ████████████████████ 10                free: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
           lower: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                lower: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
           upper: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                upper: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
         low/upp: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0              low/upp: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
           fixed: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                fixed: ████████████████████ 8     
          infeas: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0               infeas: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
            nnzh: (-36.36% sparsity)   75              linear: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
                                                    nonlinear: ████████████████████ 8     
                                                         nnzj: ( 70.00% sparsity)   24    

Now, we got an optimization model ready to be solved. This problem can be solved with for example, with the Ipopt solver, as follows.

using NLPModelsIpopt
result = ipopt(m)
"Execution stats: first-order stationary"

Here, result is an AbstractExecutionStats, which typically contains the solution information. We can check several information as follows.

println("Status: $(result.status)")
println("Number of iterations: $(result.iter)")
Status: first_order
Number of iterations: 6

The solution values for variable x can be inquired by:

sol = solution(result, x)
10-element view(::Vector{Float64}, 1:10) with eltype Float64:
 -0.9505563573613093
  0.9139008176388945
  0.9890905176644905
  0.9985592422681151
  0.9998087408802769
  0.9999745932450963
  0.9999966246997642
  0.9999995512524277
  0.999999944919307
  0.999999930070643

ExaModels provide several APIs similar to this:

This concludes a short tutorial on how to use ExaModels to model and solve optimization problems. Want to learn more? Take a look at the following examples, which provide further tutorial on how to use ExaModels.jl. Each of the examples are designed to instruct a few additional techniques.


This page was generated using Literate.jl.