# Writing an indicator function in JuMP

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:

``````@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.

A proposed solution, given help from @mbesancon:

``````@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

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

``````@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

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

1 Like

The objective has squares, but yeah 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.

1 Like

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

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

1 Like