I am implementing a large scale nonlinear program solver using the JuMP interface to IPOPT.

The Nonlinear Modeling section of JuMP v0.21.0 documentation clearly explicates that all expressions used in NLconstraint and NLobjective must be scalar operations. http://www.juliaopt.org/JuMP.jl/stable/nlp/

For this particular appreciation, manual derivation of scalar NLconstraint expressions is prohibitive due to their quantity and complexity.

As an attempt to work around this limitation, scalar nonlinear expressions were derived and delivered as **strings** using meta programming/symbolic math packages; The thought being that these strings could be parsed, evaluated and passed to NLconstraint. In practice this does not work.

The question is thus -

# How can a string be parsed into an expression ingestible by NLconstraint/NLobjective?

With juliaâ€™s meta-programming faculty there must be a way to accomplish this without altering nonlinear modeling/autodiff source code.

The task is illustrated on the toy problem below.

## Suppose the nonlinear constraint has been delivered as a string taking one of the following forms, parse it such that it may be passed to NLconstraint

â€śx[1]^3 + 5.0*x[1]*x[2]â€ť

or

â€śx1^3 + 5.0*x1*x2â€ť

### Working Toy Problem

```
using JuMP
using Ipopt
m = Model(with_optimizer(Ipopt.Optimizer))
@variable(m, x[1:2])
set_lower_bound(x[1], 0.0)
set_upper_bound(x[1], 2.0)
set_lower_bound(x[2], -3000.0)
set_upper_bound(x[2], 3000.0)
@NLobjective(m, Max, 5*x[1]^2*x[2]-3*x[2]^2)
@NLconstraint(m, x[1]^3 + 5.0*x[1]*x[2] <= 3.0)
optimize!(m)
```

#### Optimal Solution

obj val: 1.5689952589360394

x[1] val: 1.0697545858077664

x[2] val: 0.3320013320392786

```
println("obj val: ", objective_value(m0))
println("x[1]: ", value(x[1]))
println("x[2]: ", value(x[2]))
```

### Here are three methods which are unsuccessful in converting a string to an expression ingestible by NLconstraint

#### Attempt 1

```
m = Model(with_optimizer(Ipopt.Optimizer))
@variable(m, x[1:2])
f = eval(Meta.parse("x[1]^3 + 5.0*x[1]*x[2]"))
@NLconstraint(m, f <= 3.0)
optimize!(m)
```

#### Attempt 2

```
m = Model(with_optimizer(Ipopt.Optimizer))
@variable(m, x[1:2])
@NLconstraint(m, eval(Meta.parse("x[1]^3 + 5.0*x[1]*x[2]")) <= 3.0)
optimize!(m)
```

#### Attempt 3

```
m = Model(with_optimizer(Ipopt.Optimizer))
@variable(m, x[1:2])
function f(x1, x2) eval(Meta.parse("x1^3 + 5.0*x1*x2")) end
register(m, :my_f, 2, f, autodiff=true)
@NLconstraint(m, my_f(x[1], x[2]) <= 3.0)
optimize!(m)
```