MODEL:
 TITLE Dunbrmin mining problem;
! Keywords: mining / scheduling / multi-period; 
! Problem:  Which blocks to mine each year so we are
   within yearly capacity, produce a steady flow of
   useable material(e.g., precious metal), and 
   satisfy removal precedence constraints;
SETS:
   BLOCK: VALUE;
  YR: VSHORT;
  BXY( BLOCK, YR): Y; ! Y(b,t)=1 if block b removed in year t;
  BXB( BLOCK, BLOCK); ! Need pairs of blocks for precedences;
 ENDSETS

 DATA:
 ! Yearly target for value removed;
   YTARG = 1.1;
! Penalty/unit short of target in each year;
   TPEN = 2.1;
! Capacity/year in blocks removed;
   YCAP = 3;
! The years;
  YR = Y0 Y1 Y2 Y3 Y4 Y5 Y6 ;
! The individual blocks and their value;
 BLOCK = B01 B02 B03 B04 B05 B06  B07  B08  B09  B10 
         B11 B12 B13 B14 B15 ;
 VALUE =  0   0   .1   2  .1  .1  1.2  .2   .1   .9 
         .1  1.2   0  .1 1.1;
! Precedence pairs.  Must do 1st block in same or earlier
    period than 2nd block of pair;
  BXB = B01,B02 B02,B03 B03,B04 B04,B05 B05,B11 B06,B07
        B07,B08 B08,B09 B09,B10 B10,B11 B11,B12 B13,B14
        B14,B15;
! Graphically, the blocks are arranged as follows:
         1    6    13
         2    7    14
         3    8    15
         4    9
         5   10
          \  /
           11
           12
;
 ENDDATA

! Minimize the cost of shortfalls over planning horizon;
MIN = @SUM( YR: TPEN * VSHORT);

! For each year t;
  @FOR( YR( t):
!  Compute yearly short fall;
   [TARG]  VSHORT( t) >= YTARG - @SUM( BLOCK( b): VALUE( b)* Y( b, t));
!  Enforce capacity each year;
    [CAPY] @SUM( BLOCK( b): Y( b, t)) <= YCAP;
      );
    
! Precedence constraints. Year of removal of block b is <= that of b1;
!  (There may be alternate/better, but less compact,
     ways of representing this precedence.);
 NYR = @SIZE( YR);
@FOR( BXB( b, b1):
 [Prec] @SUM( YR( t): (NYR-t)*( Y(b,t)-Y(b1,t))) >= 0;
     );

! A block can be removed at most once;
 @FOR( BLOCK( b):
  [ONCE] @SUM( YR( t): Y( b, t)) <= 1;
     );
! You either do the block or you do not;
@FOR( BXY( b, t): @BIN( Y( b, t)););

! Complications not considered here:
   Target value and capacity may vary from year to year.
   Work required to remove a block may vary among blocks.
   There may be a distinct removal cost for each block.
   Time value of money may be important.
   Precedence relations may be more complicated;
END
