! LINGO MODEL for interior point/barrier primal-dual method. (IntPtAlg.lg4)
   Original version by Kipp Martin. See article by
    Marsten, et. al.(1990) in INTERFACES, vol. 20, no. 4.;
 ! Keywords: Interior Point Method, Barrier Method;
SETS:
   ROW  : B, Y, DY;
   COL  : C, DX, X, DZ, Z;
   MATRIX( ROW, COL) : A;
ENDSETS
! Solve the optimization problem Min CX s.t. AX = B, X >= 0, by solving approximately the system: 1) AX = B, (Primal conditions) 2) A'Y - C = Z,(Dual conditions) 3) X >= 0, (Non-negativity) 4) Z >= 0 5) ZX = 0. (Complementarity) We start with a solution to the linear constraints, (1-4), and then use iterative approximation to satisfy (5); DATA: COL = A__ C__ D__ S_1 S_2 S_3; B = 60, 50, 120; ! RHS; C = -20, -30, -47, 0, 0, 0; ! Objective coefficients, cost minimize form; A = 1, 0, 1, 1, 0, 0, ! Coefficient matrix for the; 0, 1, 1, 0, 1, 0, ! Astro/Cosmo; 1, 2, 3, 0, 0, 1; ! Problem in Schrage; X = 1 1 1 58 48 114; ! Initial feasible primal soln; Z = 40 60 103 30 30 30; ! Initial feasible reduced costs; Y = 30 30 30; ! Initial dual prices; TOLZR = .0000001; ! Zero tolerance; TOLGAP = .00000005; ! Termination tolerance; ENDDATA SUBMODEL DIRECTION: ! Given a current point: X : feasible (nonnegative) primal point, Y : feasible dual prices, Z : feasible (nonnegative) reduced costs, Choose a direction: DX, DY and DZ that tries to better satisfy the complementary slackness constraint; ! The Primal equations: A*( X + DX) = B; @FOR( ROW( I): [P] @SUM( COL( J) : A( I, J)*( X( J) + DX( J))) = B( I); ); ! The Dual equations: A*( Y + DY) -(Z + DZ) = -C; @FOR( COL( J): [D] @SUM( ROW( I): A( I, J) * ( Y( I) + DY( I))) - (Z( J) + DZ( J)) = -C( J) ); ! The Complementary slackness equation: ( Z + DZ) * ( X + DX) = 0, or Z*X + Z*DX + DZ*X + DZ*DX = 0, or the linear approximation Z*X + Z*DX + DZ*X ~ 0, ; ! and the linear approximation to it; @FOR( COL( J): [CM] ( Z( J) + DZ( J)) * X( J) + Z( J) * DX( J) = MU ); ! Allow for movements in the negative direction; @FOR( ROW: @FREE( DY)); @FOR( COL: @FREE( DX)); @FOR( COL: @FREE( DZ)); ENDSUBMODEL
CALC: N = @SIZE( COL); ! Turn off all messages; @SET('TERSEO',3); ! Set to <= 2 for debugging; maxiter = 30; ! Seldom need more than this # iterations; more = 1; ! Set to 0 when done; iter = 0; @WHILE( iter #LE# maxiter #AND# more: iter = iter + 1; gap = @SUM( COL: X * Z); ! Duality gap; @WRITE(iter,') Current gap= ', gap,@NEWLINE(1)); ! Marsten's rule for error target, MU; MU = gap / ( N * N); @SOLVE( DIRECTION); ! Get the move direction; ! Calculate step size in the move direction so that X and Z remain > 0; ! Do not let any variable get too close to zero; ALPHAP = .995 * ( @MIN(COL( J) | DX( J) #LT# -TOLZR: -X(J) / DX(J))); ALPHAD = .995 * ( @MIN(COL( J) | DZ( J) #LT# -TOLZR: -Z(J) / DZ(J))); ! Move to the new point; @FOR( COL( J): X( J) = X( J) + ALPHAP * DX( J)); @FOR( COL( J): Z( J) = Z( J) + ALPHAD * DZ( J)); @FOR( ROW( I): Y( I) = Y( I) + ALPHAD * DY( I)); ! Calculate primal and dual objectives; POBJ = -@SUM( COL: X * C); DOBJ = @SUM( ROW: Y * B); gap = DOBJ - POBJ ; ! Write out details of new point; @WRITE(' New Primal, Dual, Gap= ', @FORMAT(POBJ,'12.4f'),' ',@FORMAT(DOBJ,'12.4f'),' ',gap,@NEWLINE(1)); @FOR( COL(j): @WRITE(' ',COL(j))); @WRITE(@NEWLINE(1),'X= '); @FOR( COL(j): @WRITE( @FORMAT(X(j),'10.3f'),' '); ); @WRITE(@NEWLINE(1)); @WRITE('Z= '); @FOR( COL(j): @WRITE( @FORMAT(Z(j),'10.3f'),' '); ); @WRITE(@NEWLINE(1)); @WRITE('Y= '); @FOR( ROW(i): @WRITE( @FORMAT(Y(i),'10.3f'),' '); ); @WRITE(@NEWLINE(1)); ! Exit if gap is small enough; @IFC( gap #LE# TOLGAP *( 1 + @ABS( @SUM( COL: C * X))): more = 0); ); ENDCALC