# Writing an indicator function in JuMP

**URL:** <https://discourse.julialang.org/t/writing-an-indicator-function-in-jump/16145>\
**Category:** Optimization (Mathematical)\
**Tags:** jump\
**Created:** [October 11, 2018, 1:17am UTC](https://discourse.julialang.org/t/writing-an-indicator-function-in-jump/16145 "2018-10-11T01:17:14Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![shoshievass](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shoshievass/32/3260_2.png) [@shoshievass](https://discourse.julialang.org/u/shoshievass)\
**Post date:** [October 11, 2018, 1:17am UTC](https://discourse.julialang.org/t/writing-an-indicator-function-in-jump/16145/1 "2018-10-11T01:17:14Z")

</div>

I’d like to penalize negative values for a linear function of parameters without using an `@constraint` (since I’d like it to be possible, but costly to violate the constraint)

Is there a way to do this within JuMP w/o defining a custom function?

My model is something like the following:

```julia
@variables m begin
        coeff_0
        coeffs_X[j = 1:P]
    end

@NLexpression(
            m,
            B[i = 1:N],
            coeff_0 + sum( X[i, j] * coeffs_X[j] for j = 1:P)
)

@NLobjective(
            m,
            Min,
            sum( (y[i] - B[i]) for i = 1:N )^2
)

```

And I’d like to penalize `B[i]` being negative.

---

<div class="post-metadata">

**Author:** ![shoshievass](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shoshievass/32/3260_2.png) [@shoshievass](https://discourse.julialang.org/u/shoshievass)\
**Post date:** [October 11, 2018, 1:54pm UTC](https://discourse.julialang.org/t/writing-an-indicator-function-in-jump/16145/2 "2018-10-11T13:54:24Z")

</div>

A proposed solution, given help from @mbesancon:

```julia
@variables m begin
       coeff_0
       coeffs_X[j = 1:P]
       negative_indicator[i = 1:N], Bin
   end

@NLexpression(
           m,
           B[i = 1:N],
           coeff_0 + sum( X[i, j] * coeffs_X[j] for j = 1:P)
)

@NLconstraint(
           m,
           i in 1:N,
           -M * negative_indicator[i] <= B[i]
)

@NLobjective(
           m,
           Min,
           sum( (y[i] - B[i]) for i = 1:N )^2 + sum(c * negative_indicator[i] for i = 1:N)
)

```

where `M` is chosen to be large enough that it bounds the lowest value of `B` and `c` is a penalty coefficient

---

<div class="post-metadata">

**Author:** ![shoshievass](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shoshievass/32/3260_2.png) [@shoshievass](https://discourse.julialang.org/u/shoshievass)\
**Post date:** [October 11, 2018, 2:09pm UTC](https://discourse.julialang.org/t/writing-an-indicator-function-in-jump/16145/3 "2018-10-11T14:09:09Z")

</div>

An alternative solution that penalizes the extent of the negativity of each `B[i]`.

```julia
@variables m begin
       coeff_0
       coeffs_X[j = 1:P]
       negative_penalizer[i = 1:N] >= 0
   end

@NLexpression(
           m,
           B[i = 1:N],
           coeff_0 + sum( X[i, j] * coeffs_X[j] for j = 1:P)
)

@NLconstraint(
           m,
           i in 1:N,
           negative_penalizer[i] + B[i] >= 0
)

@NLobjective(
           m,
           Min,
           sum( (y[i] - B[i]) for i = 1:N )^2 + sum(c * negative_penalizer[i] for i = 1:N)
)

```

where `c > 0` is a penalty coefficient

---

<div class="post-metadata">

**Author:** ![mbesancon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbesancon/32/6528_2.png) [@mbesancon](https://discourse.julialang.org/u/mbesancon)\
**Post date:** [October 11, 2018, 2:31pm UTC](https://discourse.julialang.org/t/writing-an-indicator-function-in-jump/16145/4 "2018-10-11T14:31:26Z")

</div>

I think all constraints and the objective are linear expressions, you can replace the constraint with `@constraint ...` and the objective with `@objective`

---

<div class="post-metadata">

**Author:** ![shoshievass](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shoshievass/32/3260_2.png) [@shoshievass](https://discourse.julialang.org/u/shoshievass)\
**Post date:** [October 11, 2018, 2:32pm UTC](https://discourse.julialang.org/t/writing-an-indicator-function-in-jump/16145/5 "2018-10-11T14:32:13Z")

</div>

The objective has squares, but yeah 🙂

---

<div class="post-metadata">

**Author:** ![mbesancon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbesancon/32/6528_2.png) [@mbesancon](https://discourse.julialang.org/u/mbesancon)\
**Post date:** [October 11, 2018, 2:37pm UTC](https://discourse.julialang.org/t/writing-an-indicator-function-in-jump/16145/6 "2018-10-11T14:37:47Z")

</div>

Oops sorry I had missed this one! In case of quadratic expressions, JuMP supports them directly, see [Expressions and Constraints — JuMP -- Julia for Mathematical Optimization 0.18 documentation](http://www.juliaopt.org/JuMP.jl/0.18/refexpr.html#constraint-references).

---

<div class="post-metadata">

**Author:** ![shoshievass](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shoshievass/32/3260_2.png) [@shoshievass](https://discourse.julialang.org/u/shoshievass)\
**Post date:** [October 11, 2018, 2:44pm UTC](https://discourse.julialang.org/t/writing-an-indicator-function-in-jump/16145/7 "2018-10-11T14:44:59Z")

</div>

Is there a particular benefit to defining quadratic expressions like this vs writing them out the way I did? Just an efficiency thing?

---

<div class="post-metadata">

**Author:** ![mbesancon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbesancon/32/6528_2.png) [@mbesancon](https://discourse.julialang.org/u/mbesancon)\
**Post date:** [October 11, 2018, 2:46pm UTC](https://discourse.julialang.org/t/writing-an-indicator-function-in-jump/16145/8 "2018-10-11T14:46:39Z")

</div>

Not sure there,but I think you can get more information from the solving process and solution (dual values of constraints for instance).  
JuMP will also pretty-print the constraints, which it will not do with non-linear expression I believe
