BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
Kaushansky
Obsidian | Level 7

I don't understand why the my CON 7 is causing the problem to be infeasible?

 

Here's my code  LOG:

 

OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
72
73 /*===============================================================================
73 ! ==========================================================*/
74 /* 8. Perform the optimization to allocate the daily budget per campaign line
74 ! item based on the WAMM media allocation and maximize iROAS */
75 /*===============================================================================
75 ! ==========================================================*/
76 proc optmodel;
77
78 setOBS;
79
80 /* Define the in character variables from the input dataset to be used in the
80 ! optimization model */
81
82 strCampaign_Line_Item {OBS};
83 strMedia_Tactics {OBS};
84
85 set TACTICS = setof {i in OBS} Campaign_Line_Item[i];
86 set TACTICS2 = setof {j in OBS} Media_Tactics[j];
87
88 /* Define the numeric variables from the input dataset to be used in the
88 ! optimization model */
89
90 numInput_Budget {OBS};
91 num Cost_Adj_Input_Budget {OBS};
92 numiROAS {OBS};
93 numUnique_Media_Tactics {OBS};
94 numInput_Min_Number_of_Days {OBS};
95 numPct_WAMM_Optimized_Spend {OBS};
96 numAvg_Pct_WAMM_Optimized_Spend {OBS};
97 numPct_WAMM_Optimized_by_Line_Item {OBS};
98 numInput_End_Date {OBS};
99 numInput_Start_Date {OBS};
100 numCost_Per_Imp_Or_Click {OBS};
101 numSaturation_Point {OBS};
102 numInflection_Point {OBS};
103
104 /* Read in the input dataset to be used in the optimization model */
105
106 read data CI_Optimization_Data_2 into OBS=[_N_]
107
108 /* Include the variables from the input dataset to be used in the optimization
108 ! model */
109
110 Campaign_Line_Item
111 Input_Budget
112 Cost_Adj_Input_Budget
113 Media_Tactics
114 iROAS
115 Unique_Media_Tactics
116 Input_Min_Number_of_Days
117 Pct_WAMM_Optimized_Spend
118 Avg_Pct_WAMM_Optimized_Spend
119 Pct_WAMM_Optimized_by_Line_Item
120 Input_End_Date
121 Input_Start_Date
122 Cost_Per_Imp_Or_Click
123 Saturation_Point
124 Inflection_Point;
NOTE: There were 37 observations read from the data set WORK.CI_OPTIMIZATION_DATA_2.
125
126 /* Set the optimization variable to be maximized for the model */
127
128 var Optimized_Budget {OBS} >= 0;
129
130 /* Create additional variables to be used for optimization and/or contraints
130 ! in the model */
131
132 impvar Input_Incremental_Sales {i in OBS}=iROAS[i] * Input_Budget[i];
133 impvar Optimized_Incremental_Sales {i in OBS}=iROAS[i] * Optimized_Budget[i];
134
135 impvar Optimized_iROAS {i in OBS} =if Cost_Adj_Input_Budget[i] >0 and
135 ! Optimized_Incremental_Sales[i]>0
136 then Optimized_Incremental_Sales[i] /
136 ! Cost_Adj_Input_Budget[i]
137 else Input_Incremental_Sales[i]
137 ! / Input_Budget[i];
138
139 impvar Input_Number_of_Days {i in
139 ! OBS}=max(Input_End_Date[i]-Input_Start_Date[i],1);
140 impvar Total_Campaign_Days {i in OBS}=&Total_Campaign_Days;
141 impvarDaily_Spend_Per_Min_Days {i in OBS}=Optimized_Budget[i] /
141 ! Input_Min_Number_of_Days[i];
142
143 /***
144 impvar Offsite_Budget {i in OBS}=if Media_Tactics[i]='Offsite Display
144 ! Walmart Network' then Input_Budget[i] else 0;
145 impvar SP_KWB_Budget {i in OBS}=if Media_Tactics[i]='SP KWB' then
145 ! Input_Budget[i] else 0;
146 impvar Search_Budget {i in OBS}=SP_KWB_Budget[i] + SP_Auto_Budget [i] +
146 ! SBA_Budget [i];
147 ***/
148
149 /*-------------------------------------------------------------------------*/
150 /* Optimization function */
151 /*-------------------------------------------------------------------------*/
152 max Total_iROAS = sum {i in OBS} iROAS[i] * Optimized_Budget[i];
153
154 /* MAXIMUM BUDGET ALLOWED -> Optimized Budget to comply with the maximum WAMM
154 ! budget allowed */
155 con Mycon1 {i in OBS}:
156 sum {j in OBS} Optimized_Budget[j] <= &overall_input_budget *
157 (1+&allowed_budget_inc) *
158 (1-&value_add_pct);
159
160 con Mycon2 {i in OBS}:
161 Optimized_Budget[i] <= Input_Budget[i] *
162 (1+&wamm_deviation_pct) *
163 (1-&value_add_pct);
164
165 /* ONLY WHEN ALL WAMM TACTICS ARE CONSIDERED -> Optimized Budget to comply with
165 ! the WAMM % allocation plus an allowed increase ratio */
166 *con Mycon2 {i in OBS}:
167 Optimized_Budget[i] <= Input_Budget[i] *
168 Pct_WAMM_Optimized_by_Line_Item[i] *
169 (&total_input_ci_allocation) *
170 (1+&wamm_deviation_pct) *
171 (1+&allowed_budget_inc) *
172 (1-&value_add_pct);
173
174 /* ONLY WHEN NO INPUT BUDGET GIVEN AND ALL WAMM TACTICS ARE CONSIDERED ->
174 ! Optimized Budget to comply with the overall WAMM budget */
175 *con Mycon2 {i in OBS}:
176 Optimized_Budget[i] <= &overall_input_budget *
177 Pct_WAMM_Optimized_by_Line_Item[i] *
178 (&total_input_ci_allocation) *
179 (1+&wamm_deviation_pct) *
180 (1+&allowed_budget_inc) *
181 (1-&value_add_pct);
182
183 /* SATURATION -> Ensure each tactic does not exceed the Point of Saturation
183 ! based on WAMM */
184 con Mycon3 {i in OBS}:
185 Optimized_Budget[i]<=Saturation_Point[i] *
186 Total_Campaign_Days[i] *
187 (1+&allowed_budget_inc);
188
189 /*-------------------------------------------------------------------------*/
190 /* Tactic Specific Mininum Constraints not to exceed 50000 or greater than */
191 /*-------------------------------------------------------------------------*/
192 /* MINIMUM SPEND BY TACTIC -> Ensure every tactic has at least a certain % of
192 ! the Inout Budget contraint */
193 con Mycon4 {i in OBS}:
194 Optimized_Budget[i]>=if Media_Tactics[i] ne ' ' and Media_Tactics[i]
194 ! ne 'Onsite Display Run-Of-Site'
195 then Input_Budget[i]*&wamm_deviation_pct;
196
197 /* MINIMUM SPEND BY TACTIC -> Ensure every tactic has at least a certain $ of
197 ! the Inout Budget contraint */
198 con Mycon5 {i in OBS}:
199 Optimized_Budget[i]>=if Media_Tactics[i] ne ' ' and Media_Tactics[i]
199 ! ne 'Onsite Display Run-Of-Site'
200 then 10000;
201
202 /* MAXIMUM SPEND BY TACTIC -> Ensure every tactic has at least a certain $ of
202 ! the Inout Budget contraint */
203 *con Mycon6 {i in OBS}:
204 Optimized_Budget[i]<=if Media_Tactics[i] ne ' ' then 20900;
205
206 /* MAXIMUM SPEND BY TACTIC -> Onsite Display Contextual Targeting contraint */
207 con Mycon7 {i in OBS}:
208 Optimized_Budget[i]<=if Media_Tactics[i]='Offsite Display Walmart
208 ! Network' then 2000000;
209
210 /* sum of Search_Budget not to exceed 150000 */
211 *con Mycon10 {i in OBS}:
212 sum {j in OBS} Search_Budget[j] <= 149000;
213
214 solve;
NOTE: Problem generation will use 4 threads.
NOTE: The problem has 37 variables (0 free, 0 fixed).
NOTE: The problem has 222 linear constraints (148 LE, 0 EQ, 74 GE, 0 range).
NOTE: The problem has 1554 linear constraint coefficients.
NOTE: The problem has 0 nonlinear constraints (0 LE, 0 EQ, 0 GE, 0 range).
NOTE: The OPTMODEL presolver is disabled for linear problems.
NOTE: The LP presolver value AUTOMATIC is applied.
NOTE: The LP presolver time is 0.00 seconds.
NOTE: Constraint Mycon7[1] causes the problem to be infeasible.
NOTE: The LP presolver found this problem to be infeasible.
NOTE: Infeasible.
NOTE: The IIS= option can be used to help diagnose the cause of infeasibility.
215
216 create data CI_Optimization_Data_3(drop=i) from [i]=OBS
217
218 Media_Tactics
219 Campaign_Line_Item
220 Optimized_Budget
221 Input_Budget
222 Cost_Adj_Input_Budget
223 iROAS
224 Unique_Media_Tactics
225 Pct_WAMM_Optimized_Spend
226 Avg_Pct_WAMM_Optimized_Spend
227 Pct_WAMM_Optimized_by_Line_Item
228 Input_Number_of_Days
229 Input_Min_Number_of_Days
230 Saturation_Point
231 Inflection_Point
232
233 Input_Incremental_Sales
234 Optimized_Incremental_Sales
235 Optimized_iROAS
236
237 Total_Campaign_Days
238 Daily_Spend_Per_Min_Days
239 ;
NOTE: Division by zero at line 137 column 82.
NOTE: The data set WORK.CI_OPTIMIZATION_DATA_3 has 37 observations and 19 variables.
240 quit;
NOTE: PROCEDURE OPTMODEL used (Total process time):
real time 0.20 seconds
cpu time 0.03 seconds
 
 
241
242
243 OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
255
 
User: Michael Kaushansky
Messages: 77
 
 
 
 
1 ACCEPTED SOLUTION

Accepted Solutions
RobPratt
SAS Super FREQ

Yes, as long as 50000 is <= Input_Budget[j] for campaign j.

View solution in original post

13 REPLIES 13
RobPratt
SAS Super FREQ

It is hard to tell for sure from just looking at your log, but here is what I suspect is going on.  You declared this constraint:

   con Mycon7 {i in OBS}:
      Optimized_Budget[i]<=if Media_Tactics[i]='Offsite Display Walmart Network' then 2000000;

For the IF-THEN/ELSE expression, there is a default of ELSE 0, so what you declared is equivalent to this:

   con Mycon7 {i in OBS}:
      Optimized_Budget[i]<=if Media_Tactics[i]='Offsite Display Walmart Network' then 2000000 else 0;

Because Optimized_Budget[i] is declared with >= 0 and this constraint forces that variable to be <= 0 if Media_Tactics[i] is not 'Offsite Display Walmart Network', the effect is that Optimized_Budget[i] = 0 in that case.

 

I think you instead meant for the constraint to be enforced only if the condition is satisfied, which you can do as follows:

   con Mycon7 {i in OBS: Media_Tactics[i]='Offsite Display Walmart Network'}:
      Optimized_Budget[i] <= 2000000;

And for a constraint with only one variable, it is more efficient to instead omit the constraint and just change the variable bounds:

   for {i in OBS: Media_Tactics[i]='Offsite Display Walmart Network'}
      Optimized_Budget[i].ub = 2000000;

If I guessed wrong about your intent, I recommend trying the suggestion in the log to use the IIS= option to help diagnose infeasibility:

   solve with lp / iis=1;
   expand / iis;
Kaushansky
Obsidian | Level 7
Thank you for your email. This was very helpful.

How can I set global constraints, for several rows as a group Vs by each
Obs (row from the input dataset).
RobPratt
SAS Super FREQ

Your Mycon1 looks like an attempt to do that:

 

   con Mycon1 {i in OBS}:
      sum {j in OBS} Optimized_Budget[j] <= &overall_input_budget * (1+&allowed_budget_inc) * (1-&value_add_pct);

This family of constraints is indexed by i, but nothing in the constraint refers to i, so you end up with the exact same constraint over and over again.  Instead, I think you intended to declare a single constraint:

 

   con Mycon1:
      sum {j in OBS} Optimized_Budget[j] <= &overall_input_budget * (1+&allowed_budget_inc) * (1-&value_add_pct);
Kaushansky
Obsidian | Level 7

Thank you.

And assuming I can set global constraint (if/then) conditions using this single constraint?

RobPratt
SAS Super FREQ

Not sure I follow.  Do you mean that you want to use a logical condition with respect to the input data to determine whether to impose a single constraint?

Kaushansky
Obsidian | Level 7

Meaning - could I do this:

 

con Mycon1 {sum {j in OBS} Optimized_Budget[j]='Offsite Display Walmart Network'}: Optimized_Budget[i]<=200000;

RobPratt
SAS Super FREQ

No, that syntax will yield errors, and the logical condition compares a sum of decision variables to a string, so it would never be true.

 

Do you maybe want the following?

con Mycon1: sum {i in OBS: Media_Tactics[i]='Offsite Display Walmart Network'} Optimized_Budget[i] <= 200000;

 

If not, what is the business rule that you are trying to enforce?

Kaushansky
Obsidian | Level 7

Here's the example of data I am trying to model:

 

I would like to set a global constraint for  Media_Tactics Offsite Display Walmart Network to be less than $350K, but also additional sub-constraints Campaign_Line_Item criteria.

 

 Media_Tactics  Campaign_Line_Item  Input_Budget 
Offsite Display Walmart NetworkWalmart DSP|Display|Cross Device|Standard Audience|In Market Ornaments|47490|7974158 $   25,000.00
Offsite Display Walmart NetworkWalmart DSP|Display|Cross Device|Custom Audience|Ornaments Heavy Spenders|47490|7974159 $   30,000.00
Offsite Display Walmart NetworkWalmart DSP|Display|Cross Device|Propensity Audience|Ornaments|47490|7974160 $   30,000.00
Offsite Display Walmart NetworkWalmart DSP|Display|Cross Device|Standard Audience|Persona Gifters|47490|7974165 $   25,000.00
Offsite Display Walmart NetworkWalmart DSP|Display|Cross Device|Custom Audience|Ornaments Previous Purchasers|47490|7974169 $   25,000.00
Offsite Display Walmart NetworkWalmart DSP|Display|Cross Device|Custom Audience|Collectibles Heavy Spenders|47490|7974171 $   25,000.00
Offsite Display Walmart NetworkWalmart DSP|Display|Cross Device|Custom Audience|Families with Kids+Previous Ornaments Purchasers|47490|7974174 $   25,000.00
Offsite Display Walmart NetworkWalmart DSP|Display|Cross Device|Propensity Audience|Gifting Supplies|47490|7974175 $   25,000.00
Offsite Display Walmart NetworkWalmart DSP|Display|Cross Device|Custom Audience|Nov&DecShoppers|47490|7974178 $   25,000.00
Offsite Display Walmart NetworkWalmart DSP|Display|Cross Device|Custom Audience|GenZMillenial&PopCulture|47490|7974179 $   20,000.00
Offsite Display Walmart NetworkWalmart DSP|Display|Cross Device|Custom Audience|Heavy Spenders Home Decor|47490|8003807 $   20,000.00
Offsite Display Walmart NetworkWalmart DSP|Display|Cross Device|Propensity Audience|Holiday Decor|47490|8005360 $   25,000.00
Offsite Display Walmart NetworkWalmart DSP|Display|Cross Device|Standard Audience|In Market Christmas|47490|7974163 $   25,000.00
Offsite Display Walmart NetworkWalmart DSP|Display|Cross Device|Custom Audience|Contextual Holidays and Celebrations|47490|7974199 $   20,000.00
Offsite Display Walmart NetworkWalmart DSP|Pre-roll|Cross Device|Standard Audience|In Market Ornaments|47490|7974313 $   20,000.00
Offsite Display Walmart NetworkWalmart DSP|Pre-roll|Cross Device|Propensity Audience| Ornaments|47490|7974314 $   20,000.00
Offsite Display Walmart NetworkWalmart DSP|Pre-roll|Cross Device|Custom Audience|Ornaments Heavy Spenders|47490|7974315 $   20,000.00
RobPratt
SAS Super FREQ

OK, I think you want the following:

con Mycon1: sum {i in OBS: Media_Tactics[i]='Offsite Display Walmart Network'} Optimized_Budget[i] <= 350000;

con Mycon2 {j in CAMPAIGNS}: sum {i in OBS: Campaign_Line_Item[i]=j} Optimized_Budget[i] <= Input_Budget[j];
Kaushansky
Obsidian | Level 7

Got it.

So this will ensure that:

1. Overall Offsite Display Walmart Network will be less/eq $350K

2. Campaign_Line_Item = to something can be > $50K if needed?

RobPratt
SAS Super FREQ

Yes, as long as 50000 is <= Input_Budget[j] for campaign j.

Kaushansky
Obsidian | Level 7

This is giving me an error? Do you know why?

 

con Mycon9: sum {i in OBS: Campaign_Line_Item[i] in
187 ('Walmart DSP|Display|Cross Device|Standard Audience|In Market
187 ! Christmas|47490|7974163'
188 ,'Walmart DSP|Display|Cross Device|Custom Audience|Heavy Spenders Home
_
22
76
188 ! Decor|47490|8003807'
ERROR 22-322: Syntax error, expecting one of the following: !, !!, &, ), *, **, +, -, .., /,
<, <=, <>, =, >, ><, >=, AND, BY, CROSS, DIFF, ELSE, IN, INTER, NOT, OR,
SYMDIFF, TO, UNION, WITHIN, ^, ^=, |, ||, ~, ~=.
ERROR 76-322: Syntax error, statement will be ignored.
189 ,'Walmart DSP|Display|Cross Device|Propensity Audience|Holiday
189 ! Decor|47490|8005360'
190 ,'Walmart DSP|Display|Cross Device|Propensity
190 ! Audience|Ornaments|47490|7974160'
191 ,'Walmart DSP|Display|Cross Device|Custom
191 ! Audience|Nov&DecShoppers|47490|7974178'
192 ,'Walmart|Display|Cross Device|Contextual Targeting|Holiday
192 ! Decor|CY23|47490|7974064')} Optimized_Budget[i] <= 140000;
193
194 /*-------------------------------------------------------------------------*/
195 /* CONDITIONAL CONSTRAINTS BY Tactic Specific Mininums and Maximums */
196 /*-------------------------------------------------------------------------*/
197
198 /* OVERALL MAXIMUM SPEND BY TACTIC -> Ensure every tactic has at LEAST a certain %
198 ! of the Input Budget contraint */
199 con Mycon2: sum {i in OBS: Media_Tactics[i]='Offsite Display Walmart Network'}
199 ! Optimized_Budget[i] <= 450000;
200 con Mycon3: sum {i in OBS: Media_Tactics[i]='Offsite Display Social Media'}
200 ! Optimized_Budget[i] <= 60000;
201 con Mycon4: sum {i in OBS: find(Campaign_Line_Item[i],'Pre-roll')<=0}
201 ! Optimized_Budget[i] >= 100000;
202
203 *con Mycon8: sum {i in OBS: find(Media_Tactics[i],'In Market
203 ! Christmas|47490|7974163')>0 or
204 find(Media_Tactics[i],'Standard Audience|In Market
204 ! Christmas|47490|7974163')>0 or
205 find(Media_Tactics[i],'Audience|Heavy Spenders Home Decor|47490|8003807')>0
205 ! or
206 find(Media_Tactics[i],'Audience|Holiday Decor|47490|8005360')>0 or
207 find(Media_Tactics[i],'Audience|Ornaments|47490|7974160')>0 or
208 find(Media_Tactics[i],'Audience|Nov&DecShoppers|47490|7974178')>0 or
209 find(Media_Tactics[i],'Targeting|Holiday Decor|CY23|47490|7974064')>0}
209 ! Optimized_Budget[i] <= 140000;
 
RobPratt
SAS Super FREQ

You have parentheses where you should instead use curly braces.  Here is correct syntax:

con Mycon9: sum {i in OBS: Campaign_Line_Item[i] in
{'Walmart DSP|Display|Cross Device|Standard Audience|In Market Christmas|47490|7974163'
,'Walmart DSP|Display|Cross Device|Custom Audience|Heavy Spenders Home Decor|47490|8003807'
,'Walmart DSP|Display|Cross Device|Propensity Audience|Holiday Decor|47490|8005360'
,'Walmart DSP|Display|Cross Device|Propensity Audience|Ornaments|47490|7974160'
,'Walmart DSP|Display|Cross Device|Custom Audience|Nov&DecShoppers|47490|7974178'
,'Walmart|Display|Cross Device|Contextual Targeting|Holiday Decor|CY23|47490|7974064'}} Optimized_Budget[i] <= 140000;

I recommend instead defining the set separately to make the code easier for human consumption:

set CAMPAIGNS = {'Walmart DSP|Display|Cross Device|Standard Audience|In Market Christmas|47490|7974163'
,'Walmart DSP|Display|Cross Device|Custom Audience|Heavy Spenders Home Decor|47490|8003807'
,'Walmart DSP|Display|Cross Device|Propensity Audience|Holiday Decor|47490|8005360'
,'Walmart DSP|Display|Cross Device|Propensity Audience|Ornaments|47490|7974160'
,'Walmart DSP|Display|Cross Device|Custom Audience|Nov&DecShoppers|47490|7974178'
,'Walmart|Display|Cross Device|Contextual Targeting|Holiday Decor|CY23|47490|7974064'};

con Mycon9: sum {i in OBS: Campaign_Line_Item[i] in CAMPAIGNS} Optimized_Budget[i] <= 140000;

 

SAS INNOVATE 2024

Innovate_SAS_Blue.png

Registration is open! SAS is returning to Vegas for an AI and analytics experience like no other! Whether you're an executive, manager, end user or SAS partner, SAS Innovate is designed for everyone on your team. Register for just $495 by 12/31/2023.

If you are interested in speaking, there is still time to submit a session idea. More details are posted on the website. 

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
  • 13 replies
  • 547 views
  • 7 likes
  • 2 in conversation