# JuMP Non-Linear Optimization

**URL:** <https://discourse.julialang.org/t/jump-non-linear-optimization/94020>\
**Category:** Optimization (Mathematical)\
**Created:** [February 3, 2023, 9:21pm UTC](https://discourse.julialang.org/t/jump-non-linear-optimization/94020 "2023-02-03T21:21:57Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![mdogan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mdogan/32/47244_2.png) [@mdogan](https://discourse.julialang.org/u/mdogan)\
**Post date:** [February 3, 2023, 9:21pm UTC](https://discourse.julialang.org/t/jump-non-linear-optimization/94020/1 "2023-02-03T21:21:57Z")

</div>

I am trying to optimize the below equation, but it throws out an error.

```julia
sqrt(transpose(x) * [0.00076204 0.00051972; 0.00051972 0.00546173] * x)

```

```julia
model = Model(HiGHS.Optimizer)

@variable(model, x[1:2])
@NLobjective(model, Min, sqrt(transpose(x) * [0.00076204 0.00051972; 0.00051972 0.00546173] * x))

```

@NLobjective(…) is throwing the below error.

```julia
ERROR: Unexpected array VariableRef[x[1], x[2]] in nonlinear expression. Nonlinear expressions may contain only scalar expressions.

```

I set the x[1:2], but potentially it may be more than 2 variables. I used a different solver (Ipopt) but got the same error.

Would you mind helping me with this issue?

I appreciate any help you can provide.

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [February 3, 2023, 9:33pm UTC](https://discourse.julialang.org/t/jump-non-linear-optimization/94020/2 "2023-02-03T21:33:46Z")

</div>

See this part of the documentation [Nonlinear Modeling · JuMP](https://jump.dev/JuMP.jl/stable/manual/nlp/#Syntax-notes)

You can either construct the quadratic term independently:

```julia
using JuMP, Ipopt
model = Model(Ipopt.Optimizer)
@variable(model, x[1:2])
A = [0.00076204 0.00051972; 0.00051972 0.00546173]
@expression(model, quad_expr, x' * A * x)
@NLobjective(model, Min, sqrt(quad_expr))

```

Or write out the scalarized summation:

```julia
using JuMP, Ipopt
model = Model(Ipopt.Optimizer)
A = [0.00076204 0.00051972; 0.00051972 0.00546173]
N = size(A, 1)
@variable(model, x[1:N])
@NLobjective(model, Min, sqrt(sum(x[i] * A[i, j] * x[j] for i in 1:N, j in 1:N)))

```

---

<div class="post-metadata">

**Author:** ![mdogan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mdogan/32/47244_2.png) [@mdogan](https://discourse.julialang.org/u/mdogan)\
**Post date:** [February 3, 2023, 9:50pm UTC](https://discourse.julialang.org/t/jump-non-linear-optimization/94020/3 "2023-02-03T21:50:09Z")

</div>

> [@odow](#):
>
> ```julia
> using JuMP, Ipopt
> model = Model(Ipopt.Optimizer)
> @variable(model, x[1:2])
> A = [0.00076204 0.00051972; 0.00051972 0.00546173]
> @expression(model, quad_expr, x' * A * x)
> @NLobjective(model, Min, sqrt(quad_expr))
> 
> ```

@edow  
Thank you so much for your very prompt answer. That works perfectly - I was trying to solve it for the last 5 hours :). Just have one more question, my apologies for writing in installments. I want to add a constraint that the sum of elements of x will equal 1. Individual elements will be greater than 0 and less than 1

```julia
@NLconstraint(model, sum(x) = 1)
@NLconstraint(model, 0 <= x <= 1)

```

I hope it makes sense. Is there any way to implement this too?

Thank you so much for your attention and participation.  
Best regards  
Mehmet

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [February 3, 2023, 9:57pm UTC](https://discourse.julialang.org/t/jump-non-linear-optimization/94020/4 "2023-02-03T21:57:16Z")

</div>

Here you go:

```julia
using JuMP, Ipopt
model = Model(Ipopt.Optimizer)
@variable(model, 0 <= x[1:2] <= 1)
@constraint(model, sum(x) == 1)
A = [0.00076204 0.00051972; 0.00051972 0.00546173]
@expression(model, quad_expr, x' * A * x)
@NLobjective(model, Min, sqrt(quad_expr))

```

---

<div class="post-metadata">

**Author:** ![mdogan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mdogan/32/47244_2.png) [@mdogan](https://discourse.julialang.org/u/mdogan)\
**Post date:** [February 3, 2023, 10:02pm UTC](https://discourse.julialang.org/t/jump-non-linear-optimization/94020/5 "2023-02-03T22:02:44Z")

</div>

Thanks very much. Works like a charm!

---

<div class="post-metadata">

**Author:** ![mdogan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mdogan/32/47244_2.png) [@mdogan](https://discourse.julialang.org/u/mdogan)\
**Post date:** [February 21, 2023, 5:36pm UTC](https://discourse.julialang.org/t/jump-non-linear-optimization/94020/6 "2023-02-21T17:36:05Z")

</div>

> [@JuMP Non-Linear Optimization](https://discourse.julialang.org/t/jump-non-linear-optimization/94020/4):
>
> Here you go: using JuMP, Ipopt model = Model(Ipopt.Optimizer) @variable(model, 0 \<= x[1:2] \<= 1) @constraint(model, sum(x) == 1) A = [0.00076204 0.00051972; 0.00051972 0.00546173] @expression(model, quad\_expr, x' \* A \* x) @NLobjective(model, Min, sqrt(quad\_expr))

@odow,  
Thanks for helping me with the optimization problem earlier (Feb 3). Indeed thank you for _ **JuMP** _ in the very first place. It’s a great package.

_ **JuMP.jl** _ is a dependency for _ **PortoflioAnalytics.jl** _ which I am actively developing. I will soon make a second release and want to improve the **portfolio optimization** function in it and wondering if you could make a **sanity check** for the below function.

Function either _ **minimizes the portfolio variance** _ or _ **maximizes the Sharpe ratio** _. I want users to define (if they want) a _ **target portfolio mean return** _ so that they can _ **move across the efficient frontier** _.

 ![image](https://global.discourse-cdn.com/julialang/original/3X/b/e/bea05c0b0afc2bfa186d4b3d616ef63fcecbfefb.png)

_Sorry for the ugly pictures!_

The output looks reasonable, but I am unsure if it is doing what I think it is.

I am placing the code here - I hope it will be easy to reproduce.

```julia
using JuMP
using Ipopt
using Statistics
using TSFrames
using NamedArrays

bond = [0.06276629, 0.03958098, 0.08456482,0.02759821,0.09584956,0.06363253,0.02874502,0.02707264,0.08776449,0.02950032]
stock = [0.1759782,0.20386651,0.21993588,0.3090001,0.17365969,0.10465274,0.07888138,0.13220847,0.28409742,0.14343067]

R = TSFrame([bond stock], colnames = [:bond, :stock])

function PortfolioOptimize(R::TSFrame, objective::String = "minumum variance"; target = Nothing, Rf::Number = 0)
    

    means = mean.(eachcol(Matrix(R)))
    covMatrix = cov(Matrix(R))
    
    model = Model(Ipopt.Optimizer)
    # set_silent(model)

    @variable(model, 0 <= w[1:size(R)[2]] <= 1)
    @constraint(model, sum(w) == 1)
    
    
    if objective == "minumum variance"
        @expression(model, quad_expr, w' * covMatrix * w)
        @NLobjective(model, Min, sqrt(quad_expr))
        if target != Nothing
            @NLconstraint(model, sum(w[i] * means[i] for i in 1:size(R)[2]) >= target)
        end
    elseif objective == "maximum sharpe"
        
        # Equation should be transformed to either scalar values or expressed in the form of expressions. 
        # N = size(covMatrix, 1) # either 
        # @NLobjective(model, Max, (sum(w[i] * means[i] for i in 1:N) - Rf) / sqrt(sum(w[i] * covMatrix[i, j] * w[j] for i in 1:N, j in 1:N))) # either
        @expression(model, quad_expr1, w' * means) # or
        @expression(model, quad_expr2, w' * covMatrix * w) # or
        @NLobjective(model, Max, (quad_expr1 - Rf)/sqrt(quad_expr2))
        if target != Nothing
            # @NLconstraint(model, sum(w[i] * means[i] for i in 1:size(R)[2]) >= target) # either
            @NLconstraint(model, quad_expr1 >= target) # or
        end
    else
        throw(ArgumentError("one of the available objective must be chosen"))
    end

    
    optimize!(model)

    portobj = objective_value(model)
    
    weights = value.(w)
    
    pmreturn = weights' * means

    colnames = names(R) # used only for naming array
    weights = NamedArray(weights, colnames, "Optimal Weights")

    return (preturn = pmreturn, obj = portobj, pweights = weights)
end

opt1 = PortfolioOptimize(R, "minumum variance", target = 0.1)
opt2 = PortfolioOptimize(R, "maximum sharpe", target = 0.15)

```

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [February 21, 2023, 6:36pm UTC](https://discourse.julialang.org/t/jump-non-linear-optimization/94020/7 "2023-02-21T18:36:25Z")

</div>

You can actually solve this using the new multi-objective support in JuMP: [Multi-objective knapsack · JuMP](https://jump.dev/JuMP.jl/stable/tutorials/linear/multi_objective_knapsack/)

```plaintext
using JuMP
import DataFrames
import Gurobi
import MultiObjectiveAlgorithms as MOA
import Plots
import Statistics
df = DataFrames.DataFrame(
    bond = [0.06276629, 0.03958098, 0.08456482,0.02759821,0.09584956,0.06363253,0.02874502,0.02707264,0.08776449,0.02950032],
    stock = [0.1759782,0.20386651,0.21993588,0.3090001,0.17365969,0.10465274,0.07888138,0.13220847,0.28409742,0.14343067],
)
R = Matrix(df)
μ = vec(Statistics.mean(R; dims = 1))
Q = Statistics.cov(R)
model = Model(() -> MOA.Optimizer(Gurobi.Optimizer))
set_optimizer_attribute(model, MOA.Algorithm(), MOA.EpsilonConstraint())
set_optimizer_attribute(model, MOA.EpsilonConstraintStep(), 0.0001)
set_silent(model)
@variable(model, 0 <= w[1:size(R, 2)] <= 1)
@constraint(model, sum(w) == 1)
@variable(model, 0 <= variance <= sum(Q))
@constraint(model, variance >= w' * Q * w)
@expression(model, mean_return, μ' * w)
@objective(model, Min, [variance, -mean_return])
optimize!(model)
solution_summary(model)
Plots.scatter(
    [value(variance; result = i) for i in 1:result_count(model)],
    [value(mean_return; result = i) for i in 1:result_count(model)];
    xlabel = "Variance",
    ylabel = "Return",
    label = "",
)

```

 ![image](https://global.discourse-cdn.com/julialang/original/3X/1/d/1d00053c1d683326d961650eaeea75d70920707a.png)

Because it’s new there are a couple of bugs with Ipopt that I need to fix, so you’ll need to use Gurobi for now.

- [No method matching \_scalarize(::VectorQuadratic · Issue #43 · jump-dev/MultiObjectiveAlgorithms.jl · GitHub](https://github.com/jump-dev/MultiObjectiveAlgorithms.jl/issues/43)
- [Some solvers don't support delete · Issue #44 · jump-dev/MultiObjectiveAlgorithms.jl · GitHub](https://github.com/jump-dev/MultiObjectiveAlgorithms.jl/issues/44)

---

<div class="post-metadata">

**Author:** ![mdogan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mdogan/32/47244_2.png) [@mdogan](https://discourse.julialang.org/u/mdogan)\
**Post date:** [February 21, 2023, 7:03pm UTC](https://discourse.julialang.org/t/jump-non-linear-optimization/94020/8 "2023-02-21T19:03:32Z")

</div>

> [@odow](#):
>
> `Gurobi`

Thanks very much for the answer. Could you please let me know which version of _ **Gurobi** _ you use? It cannot load for some reason. I’m using _ **Julia** _ version _ **1.8.5** _

```julia
julia> import Gurobi
[Info: Precompiling Gurobi [2e9cd046-0924-5485-92f1-d5272153d98b]
ERROR: LoadError: SystemError: opening file "C:\\Users\\ploot\\.julia\\packages\\Gurobi\\FliRK\\deps\\deps.jl": No such file or directory
Stacktrace:
  [1] systemerror(p::String, errno::Int32; extrainfo::Nothing)
    @ Base .\error.jl:176
  [2] #systemerror#80
    @ .\error.jl:175 [inlined]
  [3] systemerror
    @ .\error.jl:175 [inlined]
  [4] open(fname::String; lock::Bool, read::Nothing, write::Nothing, create::Nothing, truncate::Nothing, append::Nothing)
    @ Base .\iostream.jl:293
  [5] open
    @ .\iostream.jl:275 [inlined]
  [6] open(f::Base.var"#387#388"{String}, args::String; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Base .\io.jl:382
  [7] open
    @ .\io.jl:381 [inlined]
  [8] read
    @ .\io.jl:462 [inlined]
  [9] _include(mapexpr::Function, mod::Module, _path::String)
    @ Base .\loading.jl:1484
 [10] include(mod::Module, _path::String)
    @ Base .\Base.jl:419
 [11] include(x::String)
    @ Gurobi C:\Users\ploot\.julia\packages\Gurobi\FliRK\src\Gurobi.jl:7
 [12] top-level scope
    @ C:\Users\ploot\.julia\packages\Gurobi\FliRK\src\Gurobi.jl:14
 [13] include
    @ .\Base.jl:419 [inlined]
 [14] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt64}}, source::Nothing)
    @ Base .\loading.jl:1554
 [15] top-level scope
    @ stdin:1
in expression starting at C:\Users\ploot\.julia\packages\Gurobi\FliRK\src\Gurobi.jl:7
in expression starting at stdin:1
ERROR: Failed to precompile Gurobi [2e9cd046-0924-5485-92f1-d5272153d98b] to C:\Users\ploot\.julia\compiled\v1.8\Gurobi\jl_BBC4.tmp.
Stacktrace:
  [1] error(s::String)
    @ Base .\error.jl:35
  [2] compilecache(pkg::Base.PkgId, path::String, internal_stderr::IO, internal_stdout::IO, keep_loaded_modules::Bool)
    @ Base .\loading.jl:1707
  [3] compilecache
    @ .\loading.jl:1651 [inlined]
  [4] _require(pkg::Base.PkgId)
    @ Base .\loading.jl:1337
  [5] _require_prelocked(uuidkey::Base.PkgId)
    @ Base .\loading.jl:1200
  [6] macro expansion
    @ .\loading.jl:1180 [inlined]
  [7] macro expansion
    @ .\lock.jl:223 [inlined]
  [8] require(into::Module, mod::Symbol)
    @ Base .\loading.jl:1144
  [9] eval
    @ .\boot.jl:368 [inlined]
 [10] eval
    @ .\Base.jl:65 [inlined]
 [11] repleval(m::Module, code::Expr, #unused#::String)
    @ VSCodeServer c:\Users\ploot\.vscode\extensions\julialang.language-julia-1.38.2\scripts\packages\VSCodeServer\src\repl.jl:222
 [12] (::VSCodeServer.var"#107#109"{Module, Expr, REPL.LineEditREPL, REPL.LineEdit.Prompt})()
    @ VSCodeServer c:\Users\ploot\.vscode\extensions\julialang.language-julia-1.38.2\scripts\packages\VSCodeServer\src\repl.jl:186
 [13] with_logstate(f::Function, logstate::Any)
    @ Base.CoreLogging .\logging.jl:511
 [14] with_logger
    @ .\logging.jl:623 [inlined]
 [15] (::VSCodeServer.var"#106#108"{Module, Expr, REPL.LineEditREPL, REPL.LineEdit.Prompt})()
    @ VSCodeServer c:\Users\ploot\.vscode\extensions\julialang.language-julia-1.38.2\scripts\packages\VSCodeServer\src\repl.jl:187
 [16] #invokelatest#2
    @ .\essentials.jl:729 [inlined]
 [17] invokelatest(::Any)
    @ Base .\essentials.jl:726
 [18] macro expansion
    @ c:\Users\ploot\.vscode\extensions\julialang.language-julia-1.38.2\scripts\packages\VSCodeServer\src\eval.jl:34 [inlined]
 [19] (::VSCodeServer.var"#61#62")()
    @ VSCodeServer .\task.jl:484

```

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [February 21, 2023, 7:13pm UTC](https://discourse.julialang.org/t/jump-non-linear-optimization/94020/9 "2023-02-21T19:13:06Z")

</div>

Gurobi requires a license, so you probably didn’t install it correctly. Try `import Pkg; Pkg.build("Gurobi")`.

Otherwise, if you wait an hour, you’ll be able to use Ipopt. I have it working locally, just adding tests and then I’ll push the fix.

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [February 21, 2023, 7:56pm UTC](https://discourse.julialang.org/t/jump-non-linear-optimization/94020/10 "2023-02-21T19:56:44Z")

</div>

Once [New version: MultiObjectiveAlgorithms v0.1.3 by JuliaRegistrator · Pull Request #78209 · JuliaRegistries/General · GitHub](https://github.com/JuliaRegistries/General/pull/78209) is merged, you can update your packages to install `MultiObjectiveAlgorithms` v0.1.3. (It can sometimes take a while for the package servers to update, so if it doesn’t update to the new version, try again in an hour or so.)

Then this will work:

```julia
using JuMP
import DataFrames
import Ipopt
import MultiObjectiveAlgorithms as MOA
import Plots
import Statistics
df = DataFrames.DataFrame(
    bond = [0.06276629, 0.03958098, 0.08456482,0.02759821,0.09584956,0.06363253,0.02874502,0.02707264,0.08776449,0.02950032],
    stock = [0.1759782,0.20386651,0.21993588,0.3090001,0.17365969,0.10465274,0.07888138,0.13220847,0.28409742,0.14343067],
)
R = Matrix(df)
μ = vec(Statistics.mean(R; dims = 1))
Q = Statistics.cov(R)
model = Model(() -> MOA.Optimizer(Ipopt.Optimizer))
set_optimizer_attribute(model, MOA.Algorithm(), MOA.EpsilonConstraint())
set_optimizer_attribute(model, MOA.SolutionLimit(), 50)
set_silent(model)
@variable(model, 0 <= w[1:size(R, 2)] <= 1)
@constraint(model, sum(w) == 1)
@expression(model, variance, w' * Q * w)
@expression(model, expected_return, μ' * w)
@objective(model, Min, [variance, -expected_return])
optimize!(model)
solution_summary(model)
Plots.scatter(
    [value(variance; result = i) for i in 1:result_count(model)],
    [value(expected_return; result = i) for i in 1:result_count(model)];
    xlabel = "Variance",
    ylabel = "Return",
    label = "",
)

```

It’s a nice example, so I will add it to the JuMP documentation: [[docs] add multiobjective portfolio example by odow · Pull Request #3227 · jump-dev/JuMP.jl · GitHub](https://github.com/jump-dev/JuMP.jl/pull/3227)

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [February 21, 2023, 10:27pm UTC](https://discourse.julialang.org/t/jump-non-linear-optimization/94020/11 "2023-02-21T22:27:44Z")

</div>

The tutorial in [[docs] add multiobjective portfolio example by odow · Pull Request #3227 · jump-dev/JuMP.jl · GitHub](https://github.com/jump-dev/JuMP.jl/pull/3227) has some additional code that helps you plot the allocation of each stock over the frontier.

It can produce graphs that look like:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/f/b/fb3241f8a8105e4a2fa1a7566f460bc4d97cc528.png)

---

<div class="post-metadata">

**Author:** ![mdogan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mdogan/32/47244_2.png) [@mdogan](https://discourse.julialang.org/u/mdogan)\
**Post date:** [February 21, 2023, 10:34pm UTC](https://discourse.julialang.org/t/jump-non-linear-optimization/94020/12 "2023-02-21T22:34:32Z")

</div>

Thank you so much. It’s very kind of you …

I’m very excited. I am testing it now, and hopefully, I will complete it tomorrow and share the result here. Will definitely add the plotting functionality to the function definition so that users can display it. The function will become way more advanced than I was ever imagining.

Once more, many thanks.

---

<div class="post-metadata">

**Author:** ![mdogan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mdogan/32/47244_2.png) [@mdogan](https://discourse.julialang.org/u/mdogan)\
**Post date:** [February 22, 2023, 2:14pm UTC](https://discourse.julialang.org/t/jump-non-linear-optimization/94020/13 "2023-02-22T14:14:59Z")

</div>

Thanks very much, @odow,

It perfectly works; my understanding is that:

_it gives the **maximum expected\_return** for **each level of variance** , which is essentially the **efficient frontier**._

Before releasing the next version of _ **PortfolioAnalytics.jl** _ I want to ask one more question.

If I would like to add a non-linear expression, in case I want to add new functionalities to the function, is it possible? I want to do the same but with different objectives. If I want to obtain the maximum _ **expected\_return** _ per given _ **Sharpe ratio** _ defined as `expected_return / sqrt(variance)` assuming the `risk-free rate` is `zero`.

For example, it fails when I want to add the below expression and objective. It is because of the square root, I believe. I think there is a specific syntax for `MultiObjectiveAlgorithms`, but I could not find it in the documentation.

```julia
@NLexpression(model, sharpe, expected_return / sqrt(variance))
@NLobjective(model, Max, [sharpe, expected_return])

```

Or should I use the output of this optimization, which will automatically give the expected\_return per level of Sharpe something like the one below? But I am still curious whether there is any possible way of defining non-linear expressions and objectives.

```julia
[value(expected_return; result = i) for i in 1:result_count(model)] ./ sqrt([value(variance; result = i) for i in 1:result_count(model)])

```

![image](https://global.discourse-cdn.com/julialang/original/3X/1/e/1e69db126efb377ddfcf408ca85957221539062a.png)

Thank you

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [February 22, 2023, 6:27pm UTC](https://discourse.julialang.org/t/jump-non-linear-optimization/94020/14 "2023-02-22T18:27:36Z")

</div>

You can’t define a vector-valued nonlinear objective in JuMP yet (although I have plans to fix this).

You can work-around the issue using an epigraph variable. Instead of `max f(x)`, use `max t; t <= f(x)`.

```plaintext
model = Model(() -> MOA.Optimizer(Ipopt.Optimizer))
set_optimizer_attribute(model, MOA.Algorithm(), MOA.EpsilonConstraint())
set_optimizer_attribute(model, MOA.SolutionLimit(), 50)
set_silent(model)
@variable(model, 0 <= w[1:size(R, 2)] <= 1)
@constraint(model, sum(w) == 1)
@expression(model, variance, w' * Q * w)
@expression(model, expected_return, μ' * w)
@variable(model, sharpe)
@NLconstraint(model, sharpe <= expected_return / sqrt(variance))
@objective(model, Max, [sharpe, expected_return])
optimize!(model)
solution_summary(model)

```

---

<div class="post-metadata">

**Author:** ![mdogan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mdogan/32/47244_2.png) [@mdogan](https://discourse.julialang.org/u/mdogan)\
**Post date:** [February 22, 2023, 8:46pm UTC](https://discourse.julialang.org/t/jump-non-linear-optimization/94020/15 "2023-02-22T20:46:17Z")

</div>

@odow , I am just writing to **THANK YOU**.

Everything is way beyond what I imagined. The below is just a demonstration of my excitement. Hopefully, starting from the next week, the wider Julia community will enjoy this and other financial functions to perform quantitative portfolio analytics.

Thanks very much again. I wouldn’t be able to do it without your and **[JuMP.jl](https://jump.dev/JuMP.jl/stable/)**’s help.

```julia
opt1 = PortfolioOptimize(R, "minumum variance")
opt1.plt

```

![image](https://global.discourse-cdn.com/julialang/original/3X/9/0/90e73827a8215ec6e123515ee577ddeac56649d5.png)

```julia
opt2 = PortfolioOptimize(R, "maximum sharpe", target = 0.04)
opt2.plt

```

![image](https://global.discourse-cdn.com/julialang/original/3X/a/6/a694826edb66a70eea6d1cf0d99ae3fd0707c090.png)

```julia
julia> opt_weights = opt2.pweights
2-element Named Vector{Float64}
Optimal Weights │
─────────────────┼───────
bond │ 0.6481
stock │ 0.3519

Plots.bar(names(opt_weights), opt_weights, labels = false)

```

![image](https://global.discourse-cdn.com/julialang/original/3X/1/7/17c7db487bf2deefe26cb9eadc19754c449a59f5.png)
