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