Affine expression in objective function

Hi, In a linear programming problem, I am trying to optimize a constraint, essentially replacing the objective function with LHS of the constraint to minimize. The error from JuMP suggests that it does not support affine expression of this type. I have given an example below and also code for where the same expression works fine if only included in a constraint.

I have also tried to reformulate the problem by defining the objective function as @objective(model, Min,collect(LowerTriangular(ones(8,8)))*((Liab_CFs - cashFlows*x).*Disc) ./ Disc) but this gives the same error.

Is there anything wrong in my definition of the constraint? Essentially I am trying to determine the minimum possible value of the constraint.

using JuMP, Clp, LinearAlgebra
model = Model(Clp.Optimizer)
prices = [99.74, 91.22, 98.71, 103.75, 97.15]
cashFlows = [4 5 2.5 5 4; 4 5 2.5 5 4; 4 5 2.5 5 4; 4 5 2.5 5 4; 4 5 102.5 5 4;4 5 0 105 104;4 105 0 0 0; 104 0 0 0 0]
Liab_CFs = [5, 7, 7, 6, 8, 7, 20, 0]*1000
Rates = [0.01, 0.015, 0.017, 0.019, 0.02, 0.025, 0.027, 0.029]
Disc= [0.99009901, 0.970661749, 0.950686094, 0.927477246, 0.90573081, 0.862296866, 0.829863942, 0.795567442]'
nBonds = [10, 100, 20, 30, 5]*1000
@variable(model, 0<= x[b = 1:length(nBonds)] <= nBonds[b])
#@objective(model,Min,prices' *x) 
A= @expression(model, Liab_CFs - cashFlows * x)
M=[AffExpr(0.0) for k = 1:8]
M[1] = A[1]*Disc[1]
for k = 2:length(A)
    add_to_expression!(M[k], A[k] * Disc[k])
    add_to_expression!(M[k], M[k-1])
end
@objective(model, Min, M./Disc)
@constraint(model, M./Disc .<=0.05*53.844)
optimize!(model)
ERROR: LoadError: The objective function `GenericAffExpr{Float64,VariableRef}[-4 x[1] - 5 x[2] - 2.5 x[3] - 5 x[4] - 4 x[5] + 5000 -4.080099008825782 x[1] - 5.100123761032227 x[2] - 2.5500618805161137 x[3] - 5.100123761032227 x[4] - 4.080099008825782 x[5] + 5100.123761032228 -4.1658293573399 x[1] - 5.207286696674875 x[2] - 2.6036433483374375 x[3] - 5.207286696674875 x[4] - 4.1658293573399 x[5] + 5207.286696674875 -4.270073532348415 x[1] - 5.337591915435518 x[2] - 2.668795957717759 x[3] - 5.337591915435518 x[4] - 4.270073532348415 x[5] + 5337.591915435519 -4.372597240012184 x[1] - 5.46574655001523 x[2] - 2.732873275007615 x[3] - 5.46574655001523 x[4] - 4.372597240012184 x[5] + 5465.746550015231 -4.592845220894031 x[1] - 5.7410565261175375 x[2] - 2.8705282630587687 x[3] - 5.7410565261175375 x[4] - 4.592845220894031 x[5] + 5741.056526117538 -4.772343801871078 x[1] - 5.9654297523388475 x[2] - 2.9827148761694238 x[3] - 5.9654297523388475 x[4] - 4.772343801871078 x[5] + 5965.429752338849 -4.9780770691719685 x[1] - 6.222596336464961 x[2] - 3.1112981682324805 x[3] - 6.222596336464961 x[4] - 4.9780770691719685 x[5] + 6222.5963364649615; -7.9214734655678525 x[1] - 9.901841831959816 x[2] - 4.950920915979908 x[3] - 9.901841831959816 x[4] - 7.9214734655678525 x[5] + 11862.578564743744 -8.080099008825782 x[1] - 10.100123761032227 x[2] - 5.050061880516114 x[3] - 10.100123761032227 x[4] - 8.080099008825782 x[5] + 12100.12376103223 -8.2498766790629 x[1] - 10.312345848828626 x[2] - 5.156172924414313 x[3] - 10.312345848828626 x[4] - 8.2498766790629 x[5] + 12354.369509690127 -8.45631854563039 x[1] - 10.570398182037989 x[2] - 5.2851990910189945 x[3] - 10.570398182037989 x[4] - 8.45631854563039 x[5] + 12663.520688678977 -8.659353253092936 x[1] - 10.82419156636617 x[2] - 5.412095783183085 x[3] - 10.82419156636617 x[4] - 8.659353253092936 x[5] + 12967.569572906548 -9.095525387193046 x[1] - 11.369406733991308 x[2] - 5.684703366995654 x[3] - 11.369406733991308 x[4] - 9.095525387193046 x[5] + 13620.746817140816 -9.450998698772239 x[1] - 11.813748373465298 x[2] - 5.906874186732649 x[3] - 11.813748373465298 x[4] - 9.450998698772239 x[5] + 14153.075821915878 -9.858426353249383 x[1] - 12.32303294156173 x[2] - 6.161516470780865 x[3] - 12.32303294156173 x[4] - 9.858426353249383 x[5] + 14763.207583600439; -11.762245284943775 x[1] - 14.70280660617972 x[2] - 7.35140330308986 x[3] - 14.70280660617972 x[4] - 11.762245284943775 x[5] + 18583.92924865161 -11.997781332166207 x[1] - 14.99722666520776 x[2] - 7.49861333260388 x[3] - 14.99722666520776 x[4] - 11.997781332166207 x[5] + 18956.067826877974 -12.2498766790629 x[1] - 15.312345848828626 x[2] - 7.656172924414313 x[3] - 15.312345848828626 x[4] - 12.2498766790629 x[5] + 19354.369509690125 -12.55641306805709 x[1] - 15.695516335071364 x[2] - 7.847758167535682 x[3] - 15.695516335071364 x[4] - 12.55641306805709 x[5] + 19838.6861029257 -12.857890317322871 x[1] - 16.07236289665359 x[2] - 8.036181448326795 x[3] - 16.07236289665359 x[4] - 12.857890317322871 x[5] + 20315.009435308933 -13.505543010984342 x[1] - 16.88192876373043 x[2] - 8.440964381865214 x[3] - 16.88192876373043 x[4] - 13.505543010984342 x[5] + 21338.277658775583 -14.033369595422187 x[1] - 17.541711994277733 x[2] - 8.770855997138867 x[3] - 17.541711994277733 x[4] - 14.033369595422187 x[5] + 22172.224891053287 -14.63834088373868 x[1] - 18.29792610467335 x[2] - 9.148963052336676 x[3] - 18.29792610467335 x[4] - 14.63834088373868 x[5] + 23128.058011956706; -15.509253358409076 x[1] - 19.386566698011347 x[2] - 9.693283349005673 x[3] - 19.386566698011347 x[4] - 15.509253358409076 x[5] + 24204.44135884956 -15.8198223138182 x[1] - 19.774777892272752 x[2] - 9.887388946136376 x[3] - 19.774777892272752 x[4] - 15.8198223138182 x[5] + 24689.129299355962 -16.15222573772074 x[1] - 20.19028217215093 x[2] - 10.095141086075465 x[3] - 20.19028217215093 x[4] - 16.15222573772074 x[5] + 25207.89309767689 -16.55641306805709 x[1] - 20.695516335071364 x[2] - 10.347758167535682 x[3] - 20.695516335071364 x[4] - 16.55641306805709 x[5] + 25838.6861029257 -16.953929607407307 x[1] - 21.192412009259133 x[2] - 10.596206004629567 x[3] - 21.192412009259133 x[4] - 16.953929607407307 x[5] + 26459.068370435587 -17.807900041700954 x[1] - 22.259875052126194 x[2] - 11.129937526063097 x[3] - 22.259875052126194 x[4] - 17.807900041700954 x[5] + 27791.813204850503 -18.503872284162938 x[1] - 23.129840355203676 x[2] - 11.564920177601838 x[3] - 23.129840355203676 x[4] - 18.503872284162938 x[5] + 28877.978924164418 -19.30156462586864 x[1] - 24.126955782335802 x[2] - 12.063477891167901 x[3] - 24.126955782335802 x[4] - 19.30156462586864 x[5] + 30122.89362515165; -19.16840583044316 x[1] - 23.96050728805395 x[2] - 103.4590654448791 x[3] - 23.96050728805395 x[4] - 19.16840583044316 x[5] + 31522.74630291773 -19.55224840739037 x[1] - 24.440310509237964 x[2] - 105.53080759392323 x[3] - 24.440310509237964 x[4] - 19.55224840739037 x[5] + 32153.981486500303 -19.963076935466358 x[1] - 24.953846169332948 x[2] - 107.74820302830685 x[3] - 24.953846169332948 x[4] - 19.963076935466358 x[5] + 32829.59549316812 -20.462625598472094 x[1] - 25.57828199809012 x[2] - 110.44445425942018 x[3] - 25.57828199809012 x[4] - 20.462625598472094 x[5] + 33651.11116375571 -20.953929607407307 x[1] - 26.192412009259133 x[2] - 113.09620600462958 x[3] - 26.192412009259133 x[4] - 20.953929607407307 x[5] + 34459.06837043559 -22.009380277627034 x[1] - 27.511725347033792 x[2] - 118.79286857166892 x[3] - 27.511725347033792 x[4] - 22.009380277627034 x[5] + 36194.773676702665 -22.869555689166212 x[1] - 28.586944611457767 x[2] - 123.43555743081075 x[3] - 28.586944611457767 x[4] - 22.869555689166212 x[5] + 37609.345734170965 -23.85545037927784 x[1] - 29.819312974097304 x[2] - 128.75680032227865 x[3] - 29.819312974097304 x[4] - 23.85545037927784 x[5] + 39230.665131970054; -22.652085168734793 x[1] - 28.31510646091849 x[2] - 115.4070899182093 x[4] - 109.7440686260256 x[5] - 103.4590654448791 x[3] + 37619.18514492809 -23.105687561198007 x[1] - 28.882109451497506 x[2] - 117.7180882966884 x[4] - 111.9416664063889 x[5] - 105.53080759392323 x[3] + 38372.50000566366 -23.591180350219787 x[1] - 29.488975437774734 x[2] 
- 120.19156080661047 x[4] - 114.29376571905553 x[5] - 107.74820302830685 x[3] + 39178.77646898662 -24.18151733287913 x[1] - 30.226896666098913 x[2] - 123.19919002627478 x[4] - 117.153810693055 x[5] - 110.44445425942018 x[3] + 40159.17169896802 -24.762111272332675 x[1] - 30.95263909041584 x[2] - 126.15718071354998 x[4] - 119.96665289546681 x[5] - 113.09620600462958 x[3] + 41123.38628405498 -26.009380277627034 x[1] - 32.511725347033796 x[2] - 132.5117253470338 x[4] - 126.00938027762703 
x[5] - 118.79286857166892 x[3] + 43194.773676702665 -27.025884563616817 x[1] - 33.78235570452102 x[2] - 137.69057756578607 x[4] - 130.9341064248819 x[5] - 123.43555743081075 x[3] + 44882.921264459525 -28.190956436852282 x[1] - 35.23869554606535 x[2] - 143.6263469854263 x[4] - 136.57860787621323 x[5] - 128.75680032227865 x[3] + 46817.800732725314; -26.00473549407953 x[1] - 116.3221775012178 x[2] - 115.4070899182093 x[4] - 109.7440686260256 x[5] - 103.4590654448791 x[3] + 54382.43677165176 -26.52547387854263 x[1] - 118.65150028179386 x[2] - 117.7180882966884 x[4] - 111.9416664063889 x[5] - 105.53080759392323 x[3] + 55471.431592386776 -27.082822637773855 x[1] - 121.14458548606898 x[2] - 120.19156080661047 x[4] - 114.29376571905553 x[5] - 107.74820302830685 x[3] + 56636.98790675695 -27.760533187247596 x[1] - 124.1760628432711 x[2] - 123.19919002627478 x[4] - 117.153810693055 x[5] - 110.44445425942018 x[3] + 58054.25097081034 -28.427058662164757 x[1] - 127.15750807350808 x[2] - 126.15718071354998 x[4] - 119.96665289546681 x[5] - 113.09620600462958 x[3] + 59448.1232332154 -29.85893128364913 x[1] - 133.56243925511382 x[2] - 132.5117253470338 x[4] - 126.00938027762703 x[5] - 118.79286857166892 x[3] + 62442.528706813144 -31.02588456361682 x[1] - 138.78235570452102 x[2] - 137.69057756578607 x[4] - 130.9341064248819 x[5] - 123.43555743081075 x[3] + 64882.92126445952 -32.36339436323993 x[1] - 144.76519111374094 x[2] - 143.6263469854263 x[4] - 136.57860787621323 x[5] - 128.75680032227865 x[3] + 67679.99036466352; -109.57113959340289 x[1] - 116.3221775012178 x[2] - 115.4070899182093 x[4] - 109.7440686260256 x[5] - 103.4590654448791 x[3] + 54382.43677165176 -111.76527451273863 x[1] - 118.65150028179386 x[2] - 117.7180882966884 x[4] - 111.9416664063889 x[5] - 105.53080759392323 
x[3] + 55471.431592386776 -114.1136675088465 x[1] - 121.14458548606898 x[2] - 120.19156080661047 x[4] - 114.29376571905553 x[5] - 107.74820302830685 x[3] + 56636.98790675695 -116.96920577176078 x[1] - 124.1760628432711 x[2] - 123.19919002627478 x[4] - 117.153810693055 x[5] - 110.44445425942018 x[3] + 58054.25097081034 -119.77761564277581 x[1] - 127.15750807350808 x[2] - 126.15718071354998 x[4] - 119.96665289546681 x[5] - 113.09620600462958 x[3] + 59448.1232332154 -125.81082120736828 x[1] - 133.56243925511382 x[2] - 132.5117253470338 x[4] - 126.00938027762703 x[5] - 118.79286857166892 x[3] + 62442.528706813144 -130.72778722563174 x[1] - 138.78235570452102 x[2] - 137.69057756578607 x[4] - 130.9341064248819 x[5] - 123.43555743081075 x[3] + 64882.92126445952 -136.36339436323993 x[1] - 144.76519111374094 x[2] - 143.6263469854263 x[4] - 136.57860787621323 x[5] - 128.75680032227865 x[3] + 67679.99036466352]` is not supported by JuMP.
Stacktrace:
 [1] set_objective(::Model, ::MathOptInterface.OptimizationSense, ::Array{GenericAffExpr{Float64,VariableRef},2}) at C:\Users\.julia\packages\JuMP\CZ8vV\src\objective.jl:117
 [2] top-level scope at C:\Users\.julia\packages\JuMP\CZ8vV\src\macros.jl:747
in expression starting at untitled-19bf476df2e148864ae2f856a0a63149:20

Code for original optimisation problem, where that expression in the constraint works fine.

using JuMP
using Clp
using LinearAlgebra
model = Model(Clp.Optimizer)
prices = [99.74, 91.22, 98.71, 103.75, 97.15]
cashFlows = [4 5 2.5 5 4; 4 5 2.5 5 4; 4 5 2.5 5 4; 4 5 2.5 5 4; 4 5 102.5 5 4;4 5 0 105 104;4 105 0 0 0; 104 0 0 0 0]
Liab_CFs = [5, 7, 7, 6, 8, 7, 20, 0]*1000
Rates = [0.01, 0.015, 0.017, 0.019, 0.02, 0.025, 0.027, 0.029]
Disc= [0.99009901, 0.970661749, 0.950686094, 0.927477246, 0.90573081, 0.862296866, 0.829863942, 0.795567442]'
nBonds = [10, 100, 20, 30, 5]*1000
@variable(model, 0<= x[b = 1:length(nBonds)] <= nBonds[b])
@objective(model,Min,prices' *x) 
A= @expression(model, Liab_CFs - cashFlows * x)
M=[AffExpr(0.0) for k = 1:8]
M[1] = A[1]*Disc[1]
for k = 2:length(A)
    add_to_expression!(M[k], A[k] * Disc[k])
    add_to_expression!(M[k], M[k-1])
end
@constraint(model, M./Disc .<=0.05*53.844)
optimize!(model)

Your objective is a vector. Do you mean @objective(model, Min, sum(M ./ Disc))?

I think @objective(model, Min, sum(M ./ Disc)) will not be equivalent to my intended objective function. The objective function without any reformulation is
@objective(model, Min, Max(M ./ Disc))

Does JuMP reformulate any max functions or are there are workarounds?

For the constraint, it was easy to make the maximum function linear: The actual constraint is Max(M./Disc) <=0.05*53.844. It is linearized by setting each element to be less than or equal to RHS, i.e. M./Disc .<=0.05*53.844

JuMP does not reformulate max.

model = Model()
@variable(model, x[1:2])
@objective(model, Min, max(x[1], x[2]))

becomes

model = Model()
@variable(model, x[1:2])
@variable(model, z)
@constraint(model, [i=1:2], z >= x[i])
@objective(model, Min, z)
1 Like

Thank you. It works.
In your reformulation, should the constraint be defined as z .>= x[i] instead of z >= x[i]?

This is how I have applied the guidance you kindly provided:

@variable(model,z)
@constraint(model, [i=1:5], z .>= M./Disc)
@objective(model, Min, z)

should the constraint be defined as z .>= x[i] instead of z >= x[i] ?

No.

See the docs for the difference between constraint containers (https://www.juliaopt.org/JuMP.jl/stable/constraints/#Constraint-containers-1) and vectorized constraints (https://www.juliaopt.org/JuMP.jl/stable/constraints/#Vectorized-constraints-1).

Apologies, for my ignorance! I realised later after posting that .>= is only needed for vectorized constraints.

On a separate note, I have observed that in the non-vectorized version, name for a constraint cannot be defined within the @constraint macro

@constraint(model, con1, [i=1:5], z >= M[i]/Disc[i]) will give an error of too many arguments, where as @constraint(model, con1, z .>= M ./ Disc) will work as expected. The work-around is to define the name as: con1 = @constraint(model, con1, [i=1:5], z >= M[i]/Disc[i])

The work-around is to define the name as

This is not correct.

Re-read the docs on constraint containers: https://www.juliaopt.org/JuMP.jl/stable/constraints/#Constraint-containers-1.

You want

@constraint(model, con1[i=1:5], z >= M[i]/Disc[I])

Thank you.