! Mark down pricing, Two period, deterministic case;
! A single seller wants to set prices for a single product
in two periods. 
This is a full knowledge case.  The potential buyers know what 
the prices will be in each of the two periods.
Each buyer will buy the product in the period which gives the
greater consumer surplus, i.e. reservation price - purchase price.
Typically, a buyer will be willing to pay more, 
perhaps substantially, in the first period. E.g., the buyer is
willing to pay more for a ski parka at the beginning of ski season.
 If you are an economist, you can also think of this as a Stackelberg game in which the
seller is the leader who makes the first decisions: the prices,
and then the buyers optimize for themselves, given the prices.
! Parameters:
   Ri(c)= reservation price of customer group c for period i,
   NP(c)= number of people in customer group c,
   COST = vendor's cost per unit of the product.
  Decision variables:
   Pi   = price set for period i, (Seller decision)
   Yi(c)= 1 if customer group c buys in period i.(Buyer decision)
;
! Keywords: Mark Down, Revenue management, Pricing, Marketing,
  Stackelberg game;
MODEL:
SETS:
 CUSTG: R1, R2, NP, Y1, Y2, 
   P1Y1, P2Y2, P1Y2, P2Y1;
ENDSETS
DATA: ! Reservation prices for the customer groups in each period; CUSTG= CG1 CG2 CG3 CG4; R1 = 220 210 180 175; ! Period 1; R2 = 150 160 175 150; ! Period 2; ! Number of people in each group; NP = 50 90 110 35; ! Cost per unit to the vendor; COST = 60; ENDDATA SUBMODEL FINDPRICES: PMX1 = @MAX( CUSTG(c): R1(c)); PMX2 = @MAX( CUSTG(c): R2(c)); @FOR( CUSTG(c): ! Linearize PiYj(c) = Pi*Yj(c); P1Y1(c) <= P1; P1Y1(c) <= PMX1*Y1(c); P1Y1(c) >= P1 - PMX1*(1-Y1(c)); P2Y2(c) <= P2; P2Y2(c) <= PMX2*Y2(c); P2Y2(c) >= P2 - PMX2*(1-Y2(c)); P2Y1(c) <= P2; P2Y1(c) <= PMX2*Y1(c); P2Y1(c) >= P2 - PMX2*(1-Y1(c)); P1Y2(c) <= P1; P1Y2(c) <= PMX1*Y2(c); P1Y2(c) >= P1 - PMX1*(1-Y2(c)); ! Customer will buy at most once; Y1(c) + Y2(c) <= 1; @BIN(Y1(c)); @BIN(Y2(c)); ! If a customer buys in period i, then the consumer surplus, Ri(c) - Pi >= 0, i.e. customer will not buy if price is above reservation price, (Ri(c) - Pi)*Yi(c) >= 0; R1(c)*Y1(c) - P1Y1(c) >= 0; R2(c)*Y2(c) - P2Y2(c) >= 0; ! If a customer buys in period i, then the consumer surplus, Ri(c) - Pi must be greater than in the other period, e.g., (R1(c) - P1)*Y1(c) >= (R2(c)- P2)*Y1(c) >=0; ! Buys in 1 rather than 2; R1(c)*Y1(c) - P1Y1(c) >= R2(c)*Y1(c) - P2Y1(c); ! Buys in 2 rather than 1; R2(c)*Y2(c) - P2Y2(c) >= R1(c)*Y2(c) - P1Y2(c); ); ! Vendor wants to maximize revenue minus cost; MAX = TOTREV - TOTCOST; TOTREV = @SUM( CUSTG(c): NP(c)*(P1Y1(c) + P2Y2(c))); TOTCOST= @SUM( CUSTG(c): COST*NP(c)*(Y1(c)+ Y2(c))); ENDSUBMODEL
CALC: @SET('TERSEO',1); ! Set output level to terse; @SOLVE( FINDPRICES); ! Solve submodel; ! Display a little report; @WRITE( 'Two Period Pricing Problem.',@NEWLINE(1)); @WRITE( ' Reservation price',@NEWLINE(1),' by group.',@NEWLINE(1)); @WRITE( ' Period 1 Period 2',@NEWLINE(1)); @FOR( CUSTG(c): @WRITE( ' ',CUSTG(c), ' ', @FORMAT(R1(c),"8.2f"),' ',@FORMAT(R2(c),"8.2f"),@NEWLINE(1)); ); @WRITE(' Cost/unit= ',@FORMAT(COST, "6.2f"),@NEWLINE(1)); @WRITE(@NEWLINE(1),' Results: Period 1 Period 2',@NEWLINE(1)); @WRITE( ' Price: ', @FORMAT(P1,"8.2f"),' ',@FORMAT(P2,"8.2f"),@NEWLINE(1)); @WRITE(' Units purchased:',@NEWLINE(1)); @FOR( CUSTG(c): @WRITE( ' ',CUSTG(c), ' ', @FORMAT(NP(c)*Y1(c),"8.0f"),' ',@FORMAT(NP(c)*Y2(c),"8.0f"),@NEWLINE(1)); ); @WRITE(@NEWLINE(1),' Total revenue=', @FORMAT(TOTREV,'9.2f'),@NEWLINE(1)); @WRITE(' Total cost =', @FORMAT(TOTCOST,'9.2f'),@NEWLINE(1)); @WRITE(' Profit =', @FORMAT(TOTREV-TOTCOST,'9.2f'),@NEWLINE(1)); ENDCALC END