! The how many facings problem.                    (NewsVendorFacings.lng)
Given 
  tsw = total shelf width available for facings,
  for each product p:
   c( p) = cost per unit,
   r( p) = revenue or selling price per unit,
   w( p) = width of a facing,
   f( p) = items per facing, e.g., stacked behind each other,
   mu( p) = mean demand per day (assume re-stock each night),
   sd( p) standard deviation in demand per day,

Question:
   How many facings should we allocate to each product?

Essential ideas:
  total facings cannot exceed tsw,
  Want to stock for each product mean demand + safety stock,
  We tend to give more safety stock to product p for which:
   r( p) - c( p) is high,
   f( p) is high,
   w( p) is low,
   sd( p) is high.

This can be done to optimize total expected profit.
! Computed parameters:
    phi( s, p) = Prob{ demand for product p is >= s}
  Variables:
     z( p, s) = 1 if we stock at least s, (thus z(s+1,p) <= z(s,p))
;
! Keywords:  Facings, Inventory, Newsboy problem, Newsvendor, Planogram, Uncertainty; 
SETS:
  prod : c, r, w, f, mu, sd, y;
  slvl;
  sxp( slvl, prod): v, z;
ENDSETS
DATA: prod = prod1 prod2; slvl = 1..60; tsw = 87; ! Total shelf width available; ! c( p) = cost per unit,; c = 40 50; ! r( p) = revenue or selling price per unit; r = 95 100; ! w( p) = width of a facing,; w = 4 5; ! f( p) = items per facing, e.g., stacked behind each other; f = 3 2; ! mu( p) = mean demand per day (assume re-stock each night),; mu = 20 15; ! sd( p) standard deviation in demand per day; sd = 2 3; ENDDATA submodel allocate:! Parameters: v( s, p) = expected sales of product p if we stock s units, ; ! Objective: maximize expected profit; MAX = @SUM( sxp( s, p): ( r( p) - c( p)) * v( s, p)* z( s, p)); ! Variables: z( s, p) = 1 if we carry at least s units of product p, y( p) = number of facings for product p. ! Can choose 1 stock level for each product; @FOR( prod( p): @SUM( slvl( s): z( s, p)) <= 1; ); ! Shelf capacity constraint; @SUM( prod( p): w( p) * y( p)) <= tsw; ! Must have enough facings to cover the amount stocked; @FOR( prod( p): [FACE] @SUM( slvl( s): s * z( s, p)) <= f( p) * y( p); ); ! Cannot choose fractional stock levels; @FOR( sxp( s, p): @BIN( z( s, p))); ! Number facings must be integer; @FOR( prod( p): @GIN( y( p))); ENDSUBMODEL
CALC: ! Compute v( s, p). ! First compute the probabilities of each level.; @FOR( prod( p): cumprev = 0; @FOR( slvl( s) : ! If we stock s, rather than s-1, marginal sales = Prob{D >= s}; cumnew = cumprev + 1 - @PNORMCDF( mu( p), sd( p), s - 0.5); v( s, p) = cumnew ; cumprev = cumnew; ); ); @SOLVE( allocate); ! Display a little report; @WRITE(' Product Facings NumToStock', @NEWLINE( 1)); @FOR( prod( p): stock = @SUM( slvl( s): s * z( s, p)) ; @WRITE( @FORMAT( prod( p), '9s'), ' ', @FORMAT( y( p), '5.0f'), ' ', @FORMAT( stock, '9.0f'), @NEWLINE( 1)); ); ENDCALC