proc optmodel;
var xc1w1, xc1w2, xt1w1, xt1w2, xfw1, xfw2, xc2w1, xc2w2, xt2w1, xt2w2 >=0 integer;
var yc2 binary;
var yt2 binary;
maximize z=82*xc1w1+83*xc1w2+45*xt1w1+49*xt1w2+30*xfw1+35*xfw2+84*xc2w1+81*xc2w2+42*xt2w1+54*xt2w2+41000*yc2+21700*yt2;
con Demand1: xc1w1+xc2w1+xt1w1+xt2w1+xfw1=6000;
con Demand2: xc1w2+xc2w2+xt1w2+xt2w2+xfw2=5200;
con china1: xc1w1+xc1w2<=1500;
con china2: xc2w1+xc2w2<=2000;
con turkey1: xt1w1+xt1w2<=1800;
con turkey2: xt2w1+xt2w2<=2200;
con france: xfw1+xfw2<=6000;
con linkc2: xc2w1+xc2w2-2000*yc2<=0;
con linkt2: xt2w1+xt2w2-2200*yc2<=0;
con Fixc2: xc2w1+xc2w2<=1000000*yc2;
con Fixt2: xt2w1+xt2w2<=1000000*yt2;
con repurpose: yc2+yt2<=1;
solve;
print xc1w1 xc1w2 xt1w1 xt1w2 xfw1 xfw2 xc2w1 xc2w2 xt2w1 xt2w2 z;
quit;
I suspect that you meant for all the x* variables to be >= 0 and integer, but your first VAR statement imposes those restrictions on only the last one. The log provides a hint:
NOTE: The problem has 12 variables (9 free, 0 fixed).
NOTE: The problem has 2 binary and 1 integer variables.
You can see the detail by using the EXPAND statement:
SAS Output
Var xc1w1 Var xc1w2 Var xt1w1 Var xt1w2 Var xfw1 Var xfw2 Var xc2w1 Var xc2w2 Var xt2w1 Var xt2w2 INTEGER >= 0 Var yc2 BINARY Var yt2 BINARY Maximize z=82*xc1w1 + 83*xc1w2 + 45*xt1w1 + 49*xt1w2 + 30*xfw1 + 35*xfw2 + 84*xc2w1 + 81*xc2w2 + 42*xt2w1 + 54*xt2w2 + 41000*yc2 + 21700*yt2 Constraint Demand1: xc1w1 + xc2w1 + xt1w1 + xt2w1 + xfw1 = 6000 Constraint Demand2: xc1w2 + xc2w2 + xt1w2 + xt2w2 + xfw2 = 5200 Constraint china1: xc1w1 + xc1w2 <= 1500 Constraint china2: xc2w1 + xc2w2 <= 2000 Constraint turkey1: xt1w1 + xt1w2 <= 1800 Constraint turkey2: xt2w1 + xt2w2 <= 2200 Constraint france: xfw1 + xfw2 <= 6000 Constraint linkc2: xc2w1 + xc2w2 - 2000*yc2 <= 0 Constraint linkt2: xt2w1 + xt2w2 - 2200*yc2 <= 0 Constraint Fixc2: xc2w1 + xc2w2 - 1000000*yc2 <= 0 Constraint Fixt2: xt2w1 + xt2w2 - 1000000*yt2 <= 0 Constraint repurpose: yc2 + yt2 <= 1 |
The simplest fix is the following:
var xc1w1 >=0 integer, xc1w2 >=0 integer, xt1w1 >=0 integer, xt1w2 >=0 integer, xfw1 >=0 integer, xfw2 >=0 integer, xc2w1 >=0 integer, xc2w2 >=0 integer, xt2w1 >=0 integer, xt2w2 >=0 integer;
But your code would be more readable and less error-prone if you instead use index sets. For example, you could declare x as follows:
set ISET = /c1 t1 f c2 t2/;
set JSET = /w1 w2/;
var x {ISET, JSET} >=0 integer;
Also, arbitrarily large values like 1000000 tend to cause unnecessary numerical difficulty. In this case, you can just omit the Fix* constraints because they are implied by the link* constraints.
It mean that given the constraints you have provided there is no solution.
I would be strongly tempted to graph the constraint areas China2 LInkC2 and Fixc2 to see if one or more of those is actually redundant,
Similar with Turkey2 LinkT2 and Fixt2
and consider if you actually want your demand functions to be equalities.
I suspect that you meant for all the x* variables to be >= 0 and integer, but your first VAR statement imposes those restrictions on only the last one. The log provides a hint:
NOTE: The problem has 12 variables (9 free, 0 fixed).
NOTE: The problem has 2 binary and 1 integer variables.
You can see the detail by using the EXPAND statement:
SAS Output
Var xc1w1 Var xc1w2 Var xt1w1 Var xt1w2 Var xfw1 Var xfw2 Var xc2w1 Var xc2w2 Var xt2w1 Var xt2w2 INTEGER >= 0 Var yc2 BINARY Var yt2 BINARY Maximize z=82*xc1w1 + 83*xc1w2 + 45*xt1w1 + 49*xt1w2 + 30*xfw1 + 35*xfw2 + 84*xc2w1 + 81*xc2w2 + 42*xt2w1 + 54*xt2w2 + 41000*yc2 + 21700*yt2 Constraint Demand1: xc1w1 + xc2w1 + xt1w1 + xt2w1 + xfw1 = 6000 Constraint Demand2: xc1w2 + xc2w2 + xt1w2 + xt2w2 + xfw2 = 5200 Constraint china1: xc1w1 + xc1w2 <= 1500 Constraint china2: xc2w1 + xc2w2 <= 2000 Constraint turkey1: xt1w1 + xt1w2 <= 1800 Constraint turkey2: xt2w1 + xt2w2 <= 2200 Constraint france: xfw1 + xfw2 <= 6000 Constraint linkc2: xc2w1 + xc2w2 - 2000*yc2 <= 0 Constraint linkt2: xt2w1 + xt2w2 - 2200*yc2 <= 0 Constraint Fixc2: xc2w1 + xc2w2 - 1000000*yc2 <= 0 Constraint Fixt2: xt2w1 + xt2w2 - 1000000*yt2 <= 0 Constraint repurpose: yc2 + yt2 <= 1 |
The simplest fix is the following:
var xc1w1 >=0 integer, xc1w2 >=0 integer, xt1w1 >=0 integer, xt1w2 >=0 integer, xfw1 >=0 integer, xfw2 >=0 integer, xc2w1 >=0 integer, xc2w2 >=0 integer, xt2w1 >=0 integer, xt2w2 >=0 integer;
But your code would be more readable and less error-prone if you instead use index sets. For example, you could declare x as follows:
set ISET = /c1 t1 f c2 t2/;
set JSET = /w1 w2/;
var x {ISET, JSET} >=0 integer;
Also, arbitrarily large values like 1000000 tend to cause unnecessary numerical difficulty. In this case, you can just omit the Fix* constraints because they are implied by the link* constraints.
I did not notice in that in the notes. That helped.
Thanks a lot 🙂
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
Learn how to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.
Find more tutorials on the SAS Users YouTube channel.