Hello,
I am a first time user of SAS optmodel procedure in SAS Enterprise Guide. I am wondering if the following code is a valid syntax/expression of the constraint.
con worse_con{i in bucket, j in AMOUNTS, k1 in 0..(10-i), k2 in 0..(17000-j) by 1000}: IF Move[i,j] = 1 THEN Move[i+k1, j+k2] = 0;
I get this error and don't understand what it means:
ERROR: The NLP solver does not allow integer variables.
The full code is here for reference:
proc optmodel;
/* Index Sets */
set bucket;
set AMOUNTS=2000..17000 by 1000;
/* Parameters */
number orig_amount {bucket, AMOUNTS} init 0;
number loss_amount {bucket, AMOUNTS} init 0;
number profit {bucket, AMOUNTS} init 0;
/* Binary decision variables--approve (1) or deny (0) an amount per customer */
var Move {bucket, AMOUNTS} binary;
read data GRP1 nomiss
into bucket=[BK_Group]
{a in AMOUNTS} < loss_amount[BK_Group,a]=col("LO"||a)
profit[BK_Group,a]=col("PR"||a)>;
print loss_amount;
/* Set up amount max and profit max objectives */
min Total_delta_loss = sum{c in bucket, a in AMOUNTS} loss_amount[c,a] * Move[c,a];
/* Approve exactly one loan amount per customer */
con One_Amount_con{c in bucket}: sum{a in AMOUNTS} Move[c,a] <= 1;
con worse_con{i in bucket, j in AMOUNTS, k1 in 0..(10-i), k2 in 0..(17000-j) by 1000}: IF Move[i,j] = 1 THEN Move[i+k1, j+k2] = 0;
impvar Total_Profit = sum{c in bucket, a in AMOUNTS} profit[c,a] * Move[c,a];
/* profit constraint: loss no more than 200,000 of profit */
con profit_con: Total_Profit >= -200000;
problem Problem1 include
Move
Total_delta_loss
One_Amount_con worse_con profit_con;
use problem Problem1;
solve;
print Move;
create data solution
from [BK_Group LO]
={c in bucket, g in AMOUNTS: Move[c,g]^=0}
amount=Move;
quit;
Any help is appreciated!
Lucas
When you use an IF-THEN/ELSE expression in the body of a constraint, you introduce nonlinearity, so the default solver is NLP, which does not allow integer (in this case, binary) variables. To capture the desired logical implication between binary variables, you can use the following linear constraint instead:
Move[i,j] <= 1 - Move[i+k1, j+k2];
Check the two cases Move[i,j] = 1 and Move[i,j] = 0 to see how it works.
When you use an IF-THEN/ELSE expression in the body of a constraint, you introduce nonlinearity, so the default solver is NLP, which does not allow integer (in this case, binary) variables. To capture the desired logical implication between binary variables, you can use the following linear constraint instead:
Move[i,j] <= 1 - Move[i+k1, j+k2];
Check the two cases Move[i,j] = 1 and Move[i,j] = 0 to see how it works.
Hi Rob,
Thanks for the quick reply. The code ran without error, but produced a result seemed not correct. (all cells are 0's)
Without the following constraint,
Move[i,j] <= 1 - Move[i+k1, j+k2],
the optimal result seemed more reasonable (although not correct):
Move | ||||||||||||||||
| 2000 | 3000 | 4000 | 5000 | 6000 | 7000 | 8000 | 9000 | 10000 | 11000 | 12000 | 13000 | 14000 | 15000 | 16000 | 17000 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
9 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
10 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
What I want is that if a cell is 1, then all the cells to the right and below should not be 1. More precisely,
if cell[i,j] = 1, then cell[i+n, j+m] = 0 for all 1<=n<=9, 1<=m<=15 where n+i <= 10 and m+j <= 16
Something like the following table is my expected result:
Move | ||||||||||||||||
| 2000 | 3000 | 4000 | 5000 | 6000 | 7000 | 8000 | 9000 | 10000 | 11000 | 12000 | 13000 | 14000 | 15000 | 16000 | 17000 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
9 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
10 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
Do you know how can I modify my constraint statement in order to derive at this result?
Again, thanks for your help.
Lucas
Start k1 and k2 at 1 instead of 0. What you have now forces 2*Move[i,j] <= 1, which by integrality implies Move[i,j] = 0.
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
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.