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 :slight_smile:

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