MODEL:
! A three stage college financing model in LINGO, www.lindo.com ;
! We want to decide how to allocate our initial wealth of 55,000
in each of three periods between bonds and stocks
so that at the end of three periods we are highly likely to
have at least 80,000. 
  Each period, there are two possible outcomes for the 
return on bonds and stocks. Ref. Birge & Louveax;

! 1) Core Model;
SETS:
   TIME;
   ASSETS: RETURN_1, RETURN_2, RETURN_3;
   TXA( TIME, ASSETS): RETURN, INVEST;
   Scenarios;
   RV( Scenarios, ASSETS, TIME ): SCENARIORETURNS;
   GV( Scenarios ): SOVER, SUNDER, PRBSCENE;
ENDSETS

DATA:
   TIME = @POINTER( 1 ); ! Time stages;
   ASSETS = @POINTER ( 2 ); ! Names of investments available; 
   INITIAL = @POINTER( 3 );  ! Initial capital;
   GOAL = @POINTER( 4 );     ! Goal after three stages;
   PENALTY = @POINTER( 5 );   ! Penalty/unit short of goal;
   Scenarios = 1..8;
ENDDATA

NP = @SIZE( TIME); ! Number of periods;
 
! Minize expected shortage penalty, minus overage;
 MIN = PENALTY * UNDER - OVER;

! Initial conditions on what we can invest;
 @SUM( ASSETS( A): INVEST( 1, A)) = INITIAL;
 @FOR( ASSETS( A): RETURN( 1, A) = 0);


! in each new period, the holdings of each commodity
  = random return * previous holdings;
@FOR( TIME( T) | T #GT# 1:
   @SUM( ASSETS( A): RETURN( T, A) * INVEST( T - 1, A)) =
   @SUM( ASSETS( A): INVEST( T, A))
);

! Summarize at the end,
  Our final wealth;
 FINAL = @SUM( ASSETS( A): INVEST( NP, A));
 ! Were we over or under our goal....;
 OVER - UNDER = FINAL - GOAL;

! SP Related Declarations;

! Step 2: Staging information;
! Specify the stage of each investment decision,
    with first stage always being 0;
@FOR( TXA( T, A): 
   @SPSTGVAR( T-1, INVEST( T, A));
 );

! Construct the outcome table;
SETS:
   OUTCOMES;
   SXA( OUTCOMES, ASSETS): O_RETURN;
   !ASSETS2(ASSETS): RETURN_1, RETURN_2, RETURN_3;
ENDSETS
DATA:
   OUTCOMES = @POINTER( 6 );
   O_RETURN = @POINTER( 7 );
ENDDATA 

! The Returns are random variables. Specify
  the stage of each;
@FOR( ASSETS( A): 
   @SPSTGRNDV( 1, RETURN_1( A));
   RETURN( @INDEX( T1), A) = RETURN_1( A);
   @SPSTGRNDV( 2, RETURN_2( A));
   RETURN( @INDEX( T2), A) = RETURN_2( A);
   @SPSTGRNDV( 3, RETURN_3( A));
   RETURN( @INDEX( T3), A) = RETURN_3( A);
);

@SPDISTTABLE( O_RETURN, RETURN_1);
@SPDISTTABLE( O_RETURN, RETURN_2);
@SPDISTTABLE( O_RETURN, RETURN_3);

CALC:
   @SET( 'TERSEO', 1);
   @SOLVE();
   I = 1;
   @WHILE( I #LE# @SPNUMSCENE():
      @SPLOADSCENE( I);
     PRBSCENE( I ) = @SPPRBSCENE( I);
      @FOR( TIME( T) | T #GT# @INDEX( T0): @FOR( ASSETS( A): 
                     SCENARIORETURNS( I, A, T - 1 ) = RETURN( T, A ) ) );
      SOVER( I ) = OVER;
      SUNDER( I ) = UNDER;
      I = I + 1;
   );

ENDCALC

DATA:
   @POINTER( 8 ) = SCENARIORETURNS;
   @POINTER( 9 ) = SOVER;
   @POINTER( 10 ) = SUNDER;
  @POINTER( 11 ) = PRBSCENE;
ENDDATA


END
