# Matrix inversion inside JuMP objective

**URL:** https://discourse.julialang.org/t/matrix-inversion-inside-jump-objective/104214
**Category:** Optimization (Mathematical)
**Tags:** jump
**Created:** [September 25, 2023, 10:20am UTC](https://discourse.julialang.org/t/matrix-inversion-inside-jump-objective/104214 "2023-09-25T10:20:24Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![lsablon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lsablon/32/47083_2.png) [@lsablon](https://discourse.julialang.org/u/lsablon)
#### Post date: [September 25, 2023, 10:20am UTC](https://discourse.julialang.org/t/matrix-inversion-inside-jump-objective/104214/1 "2023-09-25T10:20:24Z")

</div>

Hello,

I am trying to solve the following problem using JuMP: find a set of values `u` subject to different linear constraints (namely positivity and mass conservation) such that the distance to a know solution of a linear system is minimal: \min ||x\_{eq} + A(u)^{-1}b(u)||\_2  
However, I’ve tried several things but I am still unable to implement the inverse in the objective function without error.

Here is a chunk of my code:

```julia
using JuMP, LinearAlgebra
using Ipopt: Ipopt

age_model = Model(Ipopt.Optimizer)

vol = rand(9)
xeq = rand(5)

xinf = rand(4)

function exchange(u)
	[
		0 u[1] u[2] u[3] 0 0 0 0 0;
		u[4] 0 0 0 u[5] 0 0 0 0;
		u[6] 0 0 u[7] 0 u[8] 0 u[9] 0;
		u[10] 0 u[11] 0 u[12] 0 u[13] u[14] 0;
		0 u[15] 0 u[16] 0 0 0 0 u[17];
		0 0 u[18] 0 0 0 u[19] u[20] 0;
		0 0 0 u[21] 0 u[22] 0 u[23] 0;
		0 0 u[24] u[25] 0 u[26] u[27] 0 u[28];
		0 0 0 0 u[29] 0 0 u[30] 0
	]
end

function A(u)
	[
		-((u[1] + u[15]) / vol[2]) 0 u[5]/vol[2] 0 0;
		0 -((u[3] + u[7] + u[16] + u[21] + u[25]) / vol[4]) u[12]/vol[4] u[13]/vol[4] 0;
		u[15]/vol[5] u[16]/vol[5] -((u[5] + u[12] + u[29]) / vol[5]) 0 u[17]/vol[5];
		0 u[21]/vol[7] 0 -((u[13] + u[19] + u[27]) / vol[7]) 0;
		0 0 u[29]/vol[9] 0 -((u[17] + u[28]) / vol[9])
	]
end

function b(u)
	[
		(u[4] * xinf[1]) / vol[2],
		(u[10] * xinf[1] + u[11] * xinf[2] + u[14] * xinf[4]) / vol[4],
		0,
		(u[22] * xinf[3] + u[23] * xinf[4]) / vol[7],
		(u[30] * xinf[4]) / vol[9],
	]
end

function objfun(u)
    norm(xeq .+ A(u)\b(u))
end

@variable(age_model, u[1:30] >= 0)

@constraint(age_model, vec(sum(exchange(u), dims = 1)) .== vec(sum(exchange(u), dims = 2)))

register(age_model, :objfun, 1, objfun; autodiff=true)

@NLobjective(age_model, Min, objfun(u...))

optimize!(age_model)

```

Thanks,  
L.

---

<div class="post-metadata">

### Author: ![jd-foster](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jd-foster/32/35824_2.png) [@jd-foster](https://discourse.julialang.org/u/jd-foster)
#### Post date: [September 25, 2023, 10:53am UTC](https://discourse.julialang.org/t/matrix-inversion-inside-jump-objective/104214/2 "2023-09-25T10:53:12Z")

</div>

The good news is that any term of the type v = A^{-1} b can be written as a constraint A v = b with a new variable v. So roughly:

```julia
@variable(model, v[1:n])

@NLconstraint(model, A v .== b)

```

for a matrix `A` with `n` columns. You’ll likely need to expand the last line to work with the scalar nonlinear expressions that involve variables in the coefficients.

---

<div class="post-metadata">

### Author: ![lsablon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lsablon/32/47083_2.png) [@lsablon](https://discourse.julialang.org/u/lsablon)
#### Post date: [September 25, 2023, 12:38pm UTC](https://discourse.julialang.org/t/matrix-inversion-inside-jump-objective/104214/4 "2023-09-25T12:38:49Z")

</div>

Adding a variable did the trick, thanks !

Another (maybe not really related question), do you know if there is an ‘optimized’ method to launch many optimizations, each time with a perturbed starting point?

I.e: I have `start = u0[i])` when defining the variables, but is there a way to set it to `u0[i] + 0.1*rand()` without having to redefine the model in a loop?

---

<div class="post-metadata">

### Author: ![jd-foster](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jd-foster/32/35824_2.png) [@jd-foster](https://discourse.julialang.org/u/jd-foster)
#### Post date: [September 26, 2023, 12:11pm UTC](https://discourse.julialang.org/t/matrix-inversion-inside-jump-objective/104214/5 "2023-09-26T12:11:41Z")

</div>

You could probably use a Parameter:

> **[Overview · JuMP](https://jump.dev/JuMP.jl/stable/moi/submodules/Nonlinear/overview/#Nonlinear_Parameters)**
>
> Documentation for JuMP.

---

<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: [September 26, 2023, 8:05pm UTC](https://discourse.julialang.org/t/matrix-inversion-inside-jump-objective/104214/6 "2023-09-26T20:05:07Z")

</div>

You don’t need to use a parameter, just set a new start value:

```julia
for i in 1:30
    set_start_value(u[i], u0[i] + 0.1 * rand())
end
optimize!(age_model)

```

Docs: [Variables · JuMP](https://jump.dev/JuMP.jl/stable/manual/variables/#Start-values)
