Lindo Systems

MODEL:      
! General purpose blending and product mix application.      
 We have a set of raw materials (RM) available,      
which we want to blend together into one or more finished goods (FG).      
There are a set of quality measures (QM) associated with each raw material.      
Each FG has lower and upper limits on each QM.      
We want to decide how much of each raw material to use in      
the blend so that the final blend satisfies the quality       
requirements and maximizes revenue minus cost. 
 Some of the RM's may in fact decrease the batch size because
the addition of the RM removes some components, e.g.,
injecting oxygen into molten steel may burn of carbon.
Adding lime to molten steel allows the removal of sulfur as slag.     
   Keywords: Blending, Feed blending, Food blending, Gas blending,
      Metals blending, Octane, Petroleum refining ;      
!                              ;      
SETS:      
  RM : Prod, UCost, Avail, AllOrNoth, VolAdd;  !Set of Raw Material sources;      
  QM ;   ! Set of quality features;  
  ! Each f. g. has min & max sellable, profit
    contr./unit and batch size to be determined;
  FG : ReqMin, ReqMax, Price, BSize;
  RXQ( RM, QM) : RMQ; ! Each RM has a vector of qualities;
 !For each combo QM, FG there are upper &
lower limits on quality, slack on quality
to be determined;
   QXF( QM, FG): QUL, QLL, S, Actual;
!Each combination of RM and FG has an amount
    used, to be determined;
   RXF( RM, FG): XUSE, UseBnry;  
ENDSETS      
DATA: 
! Get Blending input data from the (only) open spreadsheet;
! Get names of candidate raw materials;
!CaseSS  RM = @OLE();
! Get volume contribution per unit of each.
Note that there may be some treatments, which if applied to a batch,
decrease the batch size, e.g.,
adding O and CaO a steel blend decreases batch size by removing C and S,
or if you add a liter of ethanol to a liter of water, it will increase
the volume by only about 0.98;
!CaseSS  VolAdd = @OLE();     
!CaseSS  Avail =  @OLE();! Units available from each RM;
!CaseSS  UCost =  @OLE();! Relative Cost/unit by RM;      
!CaseSS   AllOrNoth= @OLE(); ! 0: use any amount, 1:use all or none;   
! The names of finished goods;
!CaseSS   FG  = @OLE();        
!CaseSS   ReqMax= @OLE();! Get maximum amount allowed in the blended batch;      
!CaseSS   ReqMin= @OLE();! Get minimum amount allowed in the blended batch;  
!CaseSS   Price = @OLE();! Price/unit at which we sell the final batch;      
! Here are the quality measures;    
!CaseSS   QM = @OLE(); ! Names of quality measure components;
!CaseSS   QLL = @OLE(); ! Lower limits on each quality, each FG  ;
!CaseSS   QUL = @OLE(); ! Upper limits on quality, each FG ;
! The quality: For each QM, each RM;
!CaseSS   RMQ = @OLE();

! Case:  Gasoline blending;
! Get names of candidate raw materials;
!CaseGas01; RM = BUTANE CATREF NAPTHA;
! Get volume contribution per unit of each.
Note that there may be some treatments, which if applied to a batch,
decrease the batch size, e.g.,
adding O and CaO a steel blend decreases batch size by removing C and S,
or if you add a liter of ethanol to a liter of water, it will increase
the volume by only about 0.98;
!CaseGas01; VolAdd =    1    1    1 ;     
!CaseGas01; Avail =  1000  4000 5000  ;! Units available from each RM;
!CaseGas01; UCost =   7.3 18.2  12.5;! Relative Cost/unit by RM;       
!CaseGas01; AllOrNoth= 0    0     0; ! 0: use any amount, 1:use all or none; 
! The names of finished goods;
!CaseGas01; FG  =   REGULAR  PREMIUM;         
!CaseGas01; ReqMax=  8000     6000;! Get maximum amount allowed in the blended batch;      
!CaseGas01; ReqMin=  4000     2000;! Get minimum amount allowed in the blended batch; 
!CaseGas01; Price =  18.4      22;! Price/unit at which we sell the final batch;      
! Here are the quality measures;    
!CaseGas01; QM =
     OCTANE VAPOR VOLATILITY; ! Names of quality measure components;
!CaseGas01; QLL = ! Lower limits on each quality, each FG  ;
!CaseGas01; 90   95   
             8   8   
            17   17   
;      
!CaseGas01;QUL = ! Upper limits on quality, each FG ;
!CaseGas01; 110   110   
             11   11   
             25   25   
;
! The quality: For each QM, each RM;
!CaseGas01; RMQ= 
           120  60  105
           100 2.6  3
            74  4.1  12;
             
! Get names of candidate raw materials;      
!CaseAlmn   RM =      A     B    C    D;  
! Get volume contribution per unit of each.
Note that there may be some treatments, which if applied to a batch,
decrease the batch size, e.g.,
adding O and CaO a steel blend decreases batch size by removing C and S;
!CaseAlmn  VolAdd =    1    1    1    1  ;    
!CaseAlmn   Avail =  999  999  999  999;! Tons per day available from each RM;
!CaseAlmn   UCost = 1000 1100  900 1300;! Relative Cost/ton by RM;       
!CaseAlmn   AllOrNoth= 0;! = 1 if use all of it or none of it;   
! The names of finished goods;
!CaseAlmn   FG =  ALINGOT;         
!CaseAlmn   ReqMax   =  100;! Get maximum amount allowed in the blended batch;      
!CaseAlmn   ReqMin   =  100;! Get minimum amount allowed in the blended batch; 
!CaseAlmn   Price    = 2000;! Price/ton at which we sell the final batch;      
! Here are the quality measures;    
!CaseAlmn   QM =
     AL  SI  FE   CU   MN   MG   ZN ; ! Names of quality measure components;
!CaseAlmn   QLL = ! Lower limits on each qual, each FG of AL SI FE CU MN MG ZN ;
!CaseAlmn      81   9.6  0    1.5  0    0     0 ;      
 !CaseAlmn  QUL = ! Upper limits on qual, FG;
!CaseAlmn      86  12  1.3  3.5  0.5  0.3   1;   
! Note, these quality requirements are in percents; 
!     AL  SI  FE   CU   MN    MG   ZN ;          
!CaseAlmn   RMQ= 
     87.5  8   1    1.75 0.4  0.25  1.1
     97.4  0.5 0.5  0.3  0.4  0.5   0.4
      0.5 98   0.6  0    0    0     0
      1    0    0  99    0    0     0 ; 

! Get names of candidate raw materials;      
!CaseSS18_8   RM = 
Oxygen Lime  FerChrm  FerNick   RIDDHI  HeavyRM  HeavyBPF  METALAXRM 
 Asian  METLAXBPF  ABAD  GLOBALBPF1  GLOBALBPF2  GLOBALSHD  
GLOBALBOC1  GLOBALBOC2  GLOBALBOC3  ICD    H13SC Moly;  
! Get volume contribution per unit of each.
Note that adding O and CaO decrease the batch size by removing C and S;
!CaseSS18_8  VolAdd = -0.7  -0.55   1   1    1     1     1    1    1   1    1   1    1   1    1   1   1  1 1 1;    
!CaseSS18_8   Avail    = 100;! Tons per day available from each RM;      
!CaseSS18_8   AllOrNoth= 0;! = 1 if use all of it or none of it;      
!CaseSS18_8   UCost    = 450 300 350 250 150 160 150 150 150 150 150 140 140 135 145  155  155 155 165 900;! Relative Cost/ton by RM;    
! Here are the quality measures;    
!CaseSS18_8   QM =
     Cr  Ni    Mn   Si    P      Mo   Cu    C      S     Fe ; ! Names of quality measure components;
! The names of finished goods;
!CaseSS18_8   FG =     SS304L SS316L;         
!CaseSS18_8   ReqMax   =  35    35;! Get maximum amount allowed in the blended batch;      
!CaseSS18_8   ReqMin   =  15    15;! Get minimum amount allowed in the blended batch; 
!CaseSS18_8   Price    = 700   700;! Price/ton at which we sell the final batch;
! Lower limits on qual, each FG of Cr, Ni, Mn, Si, P, Mo, Cu, C, S, Fe;
!CaseSS18_8   QLL = 
  18  16 
   8  10  
   0   0   
   0   0  
   0   0 
   0   2 
   0   0  
   0   0    
   0   0   
   0   0; 
! Upper limits on qual, each FG, for Cr NI Mn SI P Mo Cu C S FE;     
 !CaseSS18_8  QUL = 
   20    18    
   10.5  13    
    2     2    
    0.75  0.75 
    0.045 0.45 
    2     2.5  
   0.5    1    
    0.03  0.03
    0.03   .03 
   74    74;   
! Note, these quality requirements are in percents; 
!   Cr    Ni    Mn    Si    P      Mo   Cu    C      S     Fe ; 
! Note that Adding Oxygen removes Carbon, Adding Lime removes Sulfur;         
!CaseSS18_8   RMQ= 
    0.0   0.0   0.0   0.0   0.0   0.0   0.0   -70   0.0    0.0  
    0.0   0.0   0.0   0.0   0.0   0.0   0.0   0.0   -55    0.0  
   60.0   0.0   0.0   0.0   0.0   0.0   0.0   5.0   0.0    35.0 
    0.0  35.0   0.0   0.0   0.0   0.0   0.0   0.0   0.0   65.0  
    0.0   0.007 0.350 0.040 0.020 0.010 0.0   0.070 0.010 99.493 
    0.010 0.007 0.710 0.190 0.040 0.0   0.0   0.200 0.021 98.822 
    0.060 0.004 0.420 0.200 0.020 0.0   0.010 0.160 0.011 99.115 
    0.100 0.035 0.600 0.250 0.040 0.010 0.010 0.450 0.030 98.475 
    0.010 0.007 0.0   0.350 0.010 0.020 0.050 0.060 0.001 99.492 
    0.180 0.030 0.600 0.250 0.030 0.0   0.070 0.580 0.020 98.240 
    0.150 0.008 0.550 0.270 0.040 0.020 0.010 0.010 0.030 98.912 
    0.040 0.010 1.130 0.170 0.020 0.040 0.020 0.090 0.010 98.470 
    0.050 0.010 1.010 0.210 0.020 0.040 0.020 0.130 0.010 98.500 
    0.060 0.010 1.100 0.250 0.020 0.040 0.020 0.140 0.040 98.320 
    0.100 0.020 1.190 0.140 0.020 0.040 0.020 0.0   0.0   98.470 
    0.070 0.020 0.800 0.020 0.030 0.040 0.010 0.0   0.0   99.010 
    0.070 0.010 0.850 0.030 0.020 0.020 0.040 0.0   0.0   98.960 
    0.110 0.070 0.470 0.350 0.020 0.010 0.110 0.0   0.0   98.860 
    5.17  0.69  0.39  0.91  0.007 1.33  0.09  0.5   0.011 90.87   
    0     0     0    0      0     100    0     0     0      0   ;

! Case: Weathering steel ASTM A588;
! Names of quality measure components;!
  Cr           Ni           Mn           Si            P         Mo      Cu           C           S           Fe            V   
0.40–0.65   0-0.40   0.80–1.25   0.30–0.50   0-0.030   0-1   0.25–0.40   0-0.16   0-0.030   97-98.2   0.02–0.10   
;

ENDDATA 
    
SUBMODEL BLEND:
! Variables:
    Prod( i) = amount of RM i used,
    XUSE( i, j) = amount of RM i used in FG j,
    BSize( j) = Batchsize/amount of FG j produced;          
 Max = Profit;
   Profit = Revenue - Cost;
   @FREE( Profit);  ! Profit might be < 0;       
! Total cost of RM bought (and sold);
  Cost = @Sum( RM(i): UCost(i) * @SUM( FG( j): XUSE( I, j)));
  Revenue =  @SUM( FG( j): Price( j) * BSize( j)); ! Total tons bought and sold; 
  
@For( RM(i) : 
   Prod( i) = @SUM( RXF( i, j): XUSE( i, j));
   Prod(i) <= Avail( i));      
      
! Enforce the all or nothing flag where appropriate;      
 @for( RM( i) | AllOrNoth( i) #eq# 1:  
   @SUM( RXF( i, j): UseBnry( i, j)) <= 1; ! Use on only one FG; 
   @FOR( RXF( i, j):   
     @bin( UseBnry( i, j));      
     XUSE( i, j) = UseBnry( i, j)* AVAIL( i);      
     ); 
    );  
   
  @FOR( FG( j):
!For each finished good, compute batch size.
  VolAdd( i) = volume added to final batch size of 1 unit of RM i;
     [BDEF] BSize( j) = @SUM( RM( I): VolAdd( i) * XUSE( i, j));
     ! Batch size limits;
          [BLO] BSize( j) > ReqMin( j);
          [BHI] BSize( j) < ReqMax( j);
   ! Quality restrictions for each quality;
   @FOR( QM( k):
     [QUP] @SUM( RM( I): RMQ( i, k) * XUSE(I, j)) <= QUL( k, j) * BSize( j);
     [QDN] @SUM( RM( I): RMQ( i, k) * XUSE(I, j)) >= QLL( k, j) * BSize(j);
        );
       );
      
ENDSUBMODEL      
    
PROCEDURE WriteTextReport:
  @write( @format( Revenue, '12.2f'),' = Revenue', @newline(1));      
  @write( @format( Cost, '12.2f'),' = Cost', @newline(1));      
  @write( @format( Revenue - Cost, '12.2f'),' = Profit', @newline(1));      
  @write( @newline(1));      
      
  @write('    FG       Quality    LowLimit      Actual     UpLimit', @newline(1)); 
  @for( FG( j):
    @FOR( QM( k):  
    @write( @format( FG( j), '8s'), @format( QM( k),'12s'),@format( QLL( k, j), '12.4f'),      
       @format( Actual( k, j), '12.4f'),      
       @format( QUL( k,j), '12.4f'), @newline(1));       
      ); );     
  @write( @newline(1));      
      
  @write('      Source    AmountUsed', @newline(1));      
  @for( RM( i):      
     @write( @format( RM( i),'12s'), @format( Prod( i), '13.2f'), @newline(1));      
      );    

  @write( @newline(1),'    FG/Blend      Source       Amount', @newline(1));
  @for( FG( j):
    @for( RM( i) | XUSE( i, j) #gt# 0:
      @write( @format( FG( j),'12s'), @format( RM( i), '12s'),@format( XUSE( i, j), '13.2f'),  @newline(1));      
       ););  
ENDPROCEDURE  
PROCEDURE WriteToSS:
! Send Results back to spreadsheet;      
  @ole( ) = Prod;       
  @ole( ) = Actual;  
  @ole( ) = XUSE;    
  @ole( ) = BSize;      
  @ole( ) = Revenue;      
  @ole( ) = Cost;      
  @ole( ) = Profit; 
ENDPROCEDURE
    
CALC:   
!  @gen( BLEND);   ! Show the model;
  @solve( BLEND);      
! Write a simple report;      
  Revenue = @SUM( FG( j): Price( j)* BSize( j));      
  Profit = Revenue - Cost;
! Compute actual amount of each QM quality;        
  @for( QXF( k, j):      
    Actual( k, j) = @Sum( RXQ(i,k) : RMQ(i,k) * XUSE( i, j))/ BSize( j);
      );      
! Optionally, write results to spreadsheet;
!CaseSS   WriteToSS;    
! Optionally, write a short text report;
  WriteTextReport;    
ENDCALC      
END      
TERSE      
GO      
QUIT