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();!CaseSS UCost = @OLE();!CaseSS AllOrNoth= @OLE(); ! The names of finished goods; !CaseSS FG = @OLE(); !CaseSS ReqMax= @OLE();!CaseSS ReqMin= @OLE();!CaseSS Price = @OLE();! Here are the quality measures; !CaseSS QM = @OLE(); !CaseSS QLL = @OLE(); !CaseSS QUL = @OLE(); ! 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 !CaseGas01; UCost = 7.3 18.2 12.5!CaseGas01; AllOrNoth= 0 0 0! The names of finished goods; !CaseGas01; FG = REGULAR PREMIUM!CaseGas01; ReqMax= 8000 6000!CaseGas01; ReqMin= 4000 2000!CaseGas01; Price = 18.4 22! Here are the quality measures; !CaseGas01; QM = OCTANE VAPOR VOLATILITY; ! Names of quality measure components; !CaseGas01; QLL = !CaseGas01; 90 95 8 8 17 17 ; !CaseGas01;QUL = !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;!CaseAlmn UCost = 1000 1100 900 1300;!CaseAlmn AllOrNoth= 0;! The names of finished goods; !CaseAlmn FG = ALINGOT; !CaseAlmn ReqMax = 100;!CaseAlmn ReqMin = 100;!CaseAlmn Price = 2000;! Here are the quality measures; !CaseAlmn QM = AL SI FE CU MN MG ZN ; ! Names of quality measure components!CaseAlmn QLL = !CaseAlmn 81 9.6 0 1.5 0 0 0 ; !CaseAlmn QUL = !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;!CaseSS18_8 AllOrNoth= 0;!CaseSS18_8 UCost = 450 300 350 250 150 160 150 150 150 150 150 140 140 135 145 155 155 155 165 900;! 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;!CaseSS18_8 ReqMin = 15 15;!CaseSS18_8 Price = 700 700;! 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); @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