Lindo Systems

! Consumer Choice and Assortment model,  (ProdPortStrict.lng)
  with consumer strict preference order. Choose a product
  portfolio, taking into account consumer preferences.
1) Consumer Choice portion of model:
 Each market segment i has preference
 RP(i,j), for buying product type j. Consumer
 i buys that product j for which: j is offered,
 and i's preference for j is higher than for
 any other offered product, and RP(i,j) > 0.
2) Assortment portion of model:
 Given the set of all possible products a vendor might
 carry, what subset should be carried, taking into account
 the consumer's preferences?
 It costs money to introduce lots of products, so we
 want to offer a product only if profitable to do so.
 Each segment i has a size, NUM(i), the total unit sales 
 to that segment if it buys.
 Specifically, if the vendor carries only product j,
 then the unit sales to segment i will be
    NUM(i) if RP(i,j) > 0, else 0;
! This model takes into account that adding more products may
    help by capturing demand otherwise going to a competitor, but may
    hurt by "cannibalizing" sales of one of our more profitable products;
! Keywords: Consumer Choice, Marketing, Demand Substitution, Assortment Planning,
     Preference ordering;
SETS:
  SEG: NUM;            ! Market segments;
  PROD: PC, FXC, Y, VOL;  ! Products possible;
  SXP( SEG, PROD): RP, ZPR;! Combinations;
  ENDSETS
DATA:
  SEG = 1..8;  ! The market segments;
 ! and their sizes;
  NUM  = 19  13  24  39  11  12  14  19;
  PROD =  A   B   C   D   E   F; ! The products;
  ! Profit contribution per unit each product;
  PC  =  16  16  15  18  14  19;
  ! Fixed cost of introducing each product;
  FXC =  10  10  10  10  10  10;
  ! Relative preference of customer segment i 
    for product j. Bigger => more preferred.
    A 0 means will not buy, e.g., prefers competitor;
   RP =   5   2   4   3   9   0 ! Segment 1;
          0   0   9   0   4   0
          0   5   9   0   0   0
          3   4   0   0   9   0 ! Segment 4;
          0   0   0   9   0   6
          9   0   5   2   0   3
          0   6   0   0   4   0
          9   0   0   0   0   0;! Segment 8;    

   NPT = 4;  ! We want to carry at most NPT products;
ENDDATA

SUBMODEL CHUZPRODS:
! Parameters:
   NUM(i) = number people in segment i,
   PC(j) = profit contribution per unit of
            product j sold,
   FXC(j) = fixed cost of introducing product j,
   RP(i,j) = relative attractiveness to segment i
             of product j,
   NPT = number products that can be carried.
  Variables:
    Y(j) = 1 if we carry product j, else 0,
    VOL(j) = volume, or units, sold of product j,
    ZPR(i,j) = 1 if segment i buys product j (and
                j only)

! Model Seller behavior;
! Maximize profit contribution from sales minus
    fixed cost of introducing the products;
  MAX = OBJ1;
   OBJ1 = @SUM( PROD(j): PC(j)*VOL(j) - FXC(j)*Y(j));

! Y(j) = 1 if we introduce product j, else 0;
  @FOR( PROD(j): @BIN(Y(j)));

! Volume sold of product j;
   @FOR( PROD(j):
      VOL(j) = @SUM( SEG(i): NUM(i)*ZPR(i,j));
       ); 

! Limit on products carried;
   @SUM( PROD(j): Y(j)) <= NPT;

! Modeling customer behavior;
   @FOR( SXP(i,j):
!    If product j is available, then customer i will
     not buy any product k that is less preferable than j.
     Customer i buys at most one product;
      @SUM( PROD( k) | RP(i,k) #LT# RP(i,j): ZPR(i,k)) <= 1 - Y(j);
!    If customer segment i buys product j, then j must be available;
          ZPR(i,j) <= Y( j);
        @BIN( ZPR(i,j)); ! Must be 0 or 1;
       );
! Cannot sell customer i a product not liked;
   @FOR( SEG(i):
     @SUM( SXP(i,j) | RP(i,j) #EQ# 0: ZPR(i,j)) = 0;
       );
 ENDSUBMODEL
 CALC:
  @SET( 'TERSEO',3);   ! Output level (0:verb,1:terse,2:errors,3:none);
  @SOLVE( CHUZPRODS);
  @WRITE(' Choosing which products to offer, given consumer preferences.', @NEWLINE(1));
   @WRITE('            Profit contribution', @NEWLINE(1));
   @WRITE('                   Product', @NEWLINE(1), 'Segment');
    @FOR( PROD(j):
      @WRITE( @FORMAT( PROD(j), '9s'));
         );
    @WRITE( @NEWLINE(1));
    @FOR( SEG( i):
      @WRITE( @FORMAT( SEG(i), '6s'),':');
      @FOR( PROD( j):
        @IFC( ZPR( i,j) #GT# 0.5:
           @WRITE( ' ',@FORMAT( PC( j)*NUM(i),'8.0f'));
          @ELSE 
           @WRITE( '         ');
             );
          );
        @WRITE( @NEWLINE(1));
        ); 
   @WRITE(' Total fixed cost=             ', @FORMAT( @SUM( PROD(j): FXC(j)*Y(j)),'8.0f'), @NEWLINE(1));
   @WRITE(' Net total profit contribution=', @FORMAT( OBJ1, '8.0f'), @NEWLINE(1));
  ENDCALC