BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
vanpoecke
Calcite | Level 5

I think this is quite simple but given I have no experience with optimisation using proc optmodel I am struggling to find solution.

I have a list of customers that are eligible for various offers. I would like to assign offers with 2 constrains.
-One customer can only be assigned to 2 offers.
-for every customers -assigned offers can not be from the same conflict group

Objective is to maximize sum of ranking.

I have managed to do first constrain but I am struggling with second.

Here is the code. Would be great if someone could help on this.


data opti1;
input custid $ output_code $ conflict_group ranking;
datalines;
ab1 a 1 45
ab1 b 1 8
ab1 c 2 91
ab1 d 3 80
ab5 a 1 51
ab5 b 1 8
ab5 c 2 2
ab5 d 3 91
ab5 e 3 23
ab5 f 4 58
ab8 a 1 72
ab8 b 1 48
ab8 c 2 27
ab8 d 3 43
ab8 e 3 96
ab8 f 4 5
ab8 g 4 49
;

proc sort data=opti1 out=opti2 nodupkey;
by custid;
run;

proc optmodel;
set <str,str> CUST_camp;
num ranking {CUST_camp};
num conflict_group {CUST_camp};
read data opti1 into CUST_camp=[custid output_code] ranking conflict_group;
set <str> CUST;
read data opti2 into CUST=[custid];
var assign{cust_camp} binary;
*constrain 1- max 2 offers per customer;
con cust_max_con {i in cust}:
sum {<(i),j> in cust_camp} assign[i,j] <=2; *not more than 2 per custid;
/*
*constrain 2- 2 selected offers per custid can not be in the same conflict group;
con cust_conflict {i in cust}:
((setof{<(i),j> in cust_camp} conflict_group[i,j] * assign[i,j]) inter (setof{<(i),j> in cust_camp} conflict_group[i,j] * assign[i,j]))={0};
*/
max response=sum {<i,j> in cust_camp} ranking[i,j] * assign[i,j];
solve with milp;
quit;

1 ACCEPTED SOLUTION

Accepted Solutions
RobPratt
SAS Super FREQ

If I understand correctly, the following should do what you want:

   set CONFLICT_GROUPS {i in CUST} = setof {<(i),j> in CUST_CAMP} conflict_group[i,j];

   con cust_conflict {i in cust, g in CONFLICT_GROUPS}:

      sum {<(i),j> in CUST_CAMP: conflict_group[i,j] = g} assign[i,j] <= 1;

   expand cust_conflict;

View solution in original post

1 REPLY 1
RobPratt
SAS Super FREQ

If I understand correctly, the following should do what you want:

   set CONFLICT_GROUPS {i in CUST} = setof {<(i),j> in CUST_CAMP} conflict_group[i,j];

   con cust_conflict {i in cust, g in CONFLICT_GROUPS}:

      sum {<(i),j> in CUST_CAMP: conflict_group[i,j] = g} assign[i,j] <= 1;

   expand cust_conflict;

SAS Innovate 2025: Register Now

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!

Multiple Linear Regression in SAS

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.

Discussion stats
  • 1 reply
  • 1131 views
  • 0 likes
  • 2 in conversation