# JuMP abs in expression macro

**URL:** https://discourse.julialang.org/t/jump-abs-in-expression-macro/49196
**Category:** Optimization (Mathematical)
**Created:** [October 28, 2020, 6:22pm UTC](https://discourse.julialang.org/t/jump-abs-in-expression-macro/49196 "2020-10-28T18:22:26Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![Paul\_McVay](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paul_mcvay/32/4307_2.png) [@Paul\_McVay](https://discourse.julialang.org/u/Paul_McVay)
#### Post date: [October 28, 2020, 6:22pm UTC](https://discourse.julialang.org/t/jump-abs-in-expression-macro/49196/1 "2020-10-28T18:22:26Z")

</div>

I am hoping to extend the expression/objective JuMP macro to automatically introduce the necessary slack variable when using absolute values. I don’t have a lot of experience with JuMP internals and was hoping for some pointers. Essentially, if have two vectors `x` and `y` and I would like the to extend the macro so that

```julia
@expression m sum(abs.(x .- y))

```

becomes

```julia
@constraint m z .>= (x .- y)
@constraint m z .>= -(x .- y)
@expression m sum(z)
```

---

<div class="post-metadata">

### Author: ![joaquimg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joaquimg/32/223_2.png) [@joaquimg](https://discourse.julialang.org/u/joaquimg)
#### Post date: [October 28, 2020, 9:36pm UTC](https://discourse.julialang.org/t/jump-abs-in-expression-macro/49196/2 "2020-10-28T21:36:02Z")

</div>

Hi,

One big issue with that is that does not always work.

A simple case is:

```julia
model = Model()
@variable(model, -1 <= x <= 1)
@objective(model, Max, abs(x))

```

your `z` would go to infinity in this case.

You might want to consider converting:  
`@constraint(model, λ >= norm(x,1))`  
into its current JuMP form  
`@constraint(model, [λ, x] in MOI.NormOneCone(1 + length(x)))`

Note that `λ` can be a scalar expression and `x` a vector expression.

The absolute value case requires `x` to be a scalar expression.  
`@constraint(model, λ >= abs(x))`  
would become the valid JuMP constraint:  
`@constraint(model, [λ, x] in MOI.NormOneCone(2))`

---

<div class="post-metadata">

### Author: ![Paul\_McVay](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paul_mcvay/32/4307_2.png) [@Paul\_McVay](https://discourse.julialang.org/u/Paul_McVay)
#### Post date: [October 29, 2020, 4:09pm UTC](https://discourse.julialang.org/t/jump-abs-in-expression-macro/49196/3 "2020-10-29T16:09:19Z")

</div>

That is certainly an excellent point. I was more trying to create a small solution I could use personally understanding the limitations than suggesting it be used widespread where everyone expects it to be correct in every instance.

I apologize for this next question. It might be better placed in the first steps area as it is more about how to write macros as I am not very good at it.

So my current attempt is to write the macro

```julia
macro sumAbs(m, ex, name)
    slackVar = Symbol("slackVar", randstring(12))
    return quote
        @variable $m $slackVar[1:$(length(ex))]
        @constraint $m $slackVar .>= $ex
        @constraint $m $slackVar .>= -$ex

        $name = @expression $m sum($slackVar)
    end         
end

```

It’s not quite working just yet. Surprisingly to me, it does work if you make `slackVar` a scalar and not an array (so just delete `[1:$(length(ex))]`). But I can’t figure out how to define it as an array in the macro.

Any help?

---

<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: [October 29, 2020, 6:08pm UTC](https://discourse.julialang.org/t/jump-abs-in-expression-macro/49196/4 "2020-10-29T18:08:48Z")

</div>

There’s no need to write a macro for this.

```nohighlight
function sumAbs(model, expr::Vector)
    slack = @variable(model, [1:length(expr)], lower_bound = 0.0)
    @constraint(model, slack .>= expr)
    @constraint(model, slack .>= -expr)
    return @expression(model, sum(slack))
end

model = Model()
@variable(model, x[1:3])
@variable(model, y[1:3])
ex = @expression(model, [a = 1:3], x[a] - y[a])
z = sumAbs(model, ex)

```

In general, you should almost never need to write a macro. They are difficult to write, and functions have the benefit of having typed arguments.
