The BOM Procedure

Example 3.10 Aggregating Forecasts Using PROC BOM

In this example, the BOM procedure is used in a nonstandard application. Recall that the input data for the procedure requires items that are related in a parent-child hierarchy. The procedure uses this information to create an output data set that lists the items in a top-down order that can be used to aggregate information in a variety of ways. Suppose, for example, that the ABC Lamp Company has forecasts that are available for lamps to be stocked at various stores. The stores are served by warehouses that are, in turn, served by distribution centers. In other words, the different units of business are organized as a tree. If the company wishes to aggregate the forecasts to calculate the overall forecast at the distribution center, it can do so using the BOM procedure as follows.

/* The input data set */
data demand10;
format parent $14. child $14. code $2. ;
input parent & child & code $ pct nitems;
datalines;
Dist.Center 1  Warehouse 1    DC   1    .  
Dist.Center 1  Warehouse 2    DC   1    .  
Dist.Center 2  Warehouse 3    DC   1    .   
Dist.Center 2  Warehouse 4    DC   1    .   
Dist.Center 2  Warehouse 5    DC   1    .   
Warehouse 1    Store 01       WH   1    .   
Warehouse 1    Store 02       WH   1    .   
Warehouse 1    Store 03       WH   1    .   
Warehouse 2    Store 04       WH   1    .   
Warehouse 2    Store 05       WH   1    .    
Warehouse 3    Store 06       WH   1    .   
Warehouse 3    Store 07       WH   1    .   
Warehouse 3    Store 08       WH   1    .   
Warehouse 4    Store 09       WH   1    .   
Warehouse 4    Store 10       WH   .5   .   
Warehouse 5    Store 11       WH   1    .   
Warehouse 5    Store 10       WH   .5   .  
Store 01       .              ST   .   10  
Store 02       .              ST   .   20  
Store 03       .              ST   .   10  
Store 04       .              ST   .   20  
Store 05       .              ST   .   10  
Store 06       .              ST   .   20  
Store 07       .              ST   .   10  
Store 08       .              ST   .   20  
Store 09       .              ST   .   10  
Store 10       .              ST   .   20  
Store 11       .              ST   .   10  
;

The data set demand10 defines the parent-child relationships of the company’s business units. It also specifies the forecasts, via the nitems variable, for each store. The code variable specifies the type of the business unit identified by the parent variable: 'DC' for distribution center, 'WH' for warehouse, and 'ST' for store. Note that some business units may be stocked from more than one parent unit. The pct variable specifies the percentage of the items in the unit identified by the child variable that are from the parent unit. For example, 'Store 10' is stocked evenly (50 percent each) from 'Warehouse 4' and 'Warehouse 5'.

The following code constructs the hierarchical structure of the ABC Lamp Company and aggregates the forecasts for stores up to each distribution center. The aggregated forecasts for stores, warehouses, and distribution centers are displayed in Output 3.10.1, Output 3.10.2, and Output 3.10.3, respectively.

  /* Create the hierarchy structure */
proc bom data=demand10 out=indbom10;
   structure / part=parent
               parent=parent 
               component=child
               quantity=pct
               id=(nitems code);
run;

  /* Sort the output data set in reverse order */
proc sort data=indbom10;
   by descending part_id;
run;
  /* Aggregate forecasts through the hierarchy structure */
data accumulate10;
   set indbom10;
   array items[3] dcitems whitems stitems;
   retain dcitems whitems stitems 0;

   do i=1 to _level_;
      if nitems then items[i]=items[i] + pct * nitems;
   end;

   if nitems then items[_level_+1]=items[_level_+1] + nitems;

   output;

   do i=_level_+1 to 3;
     items[i]=0;
   end; 
run;
  /* Display the forecast for each store */
proc sort data=accumulate10(where=(code="ST")) 
          out=stores10
          nodupkey;
   by _part_;
run;

proc print data=stores10 noobs;
   title1 'ABC Lamp Company';
   title3 'Totals for Stores';
   var _Part_ code stitems;
run;
  /* Display the aggregated forecast for each warehouse */
proc sort data=accumulate10(where=(code="WH")) 
          out=houses10
          nodupkey;
   by _part_;
run;

proc print data=houses10 noobs;
   title1 'ABC Lamp Company';
   title3 'Totals for Warehouses';
   var _Part_ code whitems;
run;
  /* Display the aggregated forecast for each distribution center */
proc sort data=accumulate10(where=(code="DC")) 
          out=dcs10
          nodupkey;
   by _part_;
run;

proc print data=dcs10 noobs;
   title1 'ABC Lamp Company';
   title3 'Totals for Distribution Centers';
   format _Part_ $14. ;
   var _Part_ code dcitems;
run;

Output 3.10.1: Forecasts for Stores

ABC Lamp Company
 
Totals for Stores

_Part_ code stitems
Store 01 ST 10
Store 02 ST 20
Store 03 ST 10
Store 04 ST 20
Store 05 ST 10
Store 06 ST 20
Store 07 ST 10
Store 08 ST 20
Store 09 ST 10
Store 10 ST 20
Store 11 ST 10


Output 3.10.2: Aggregated Forecasts for Warehouses

ABC Lamp Company
 
Totals for Warehouses

_Part_ code whitems
Warehouse 1 WH 40
Warehouse 2 WH 30
Warehouse 3 WH 50
Warehouse 4 WH 20
Warehouse 5 WH 20


Output 3.10.3: Aggregated Forecasts for Distribution Centers

ABC Lamp Company
 
Totals for Distribution Centers

_Part_ code dcitems
Dist.Center 1 DC 70
Dist.Center 2 DC 90