You are on page 1of 7

!

****************************************************************
!*
LINEAR PROGRAMMING: THE SIMPLEX METHOD
*
!* ------------------------------------------------------------ *
!* SAMPLE RUN:
*
!* Maximize z = x1 + x2 + 3x3 -0.5x4 with conditions:
*
!*
x1 + 2x3 <= 740
*
!*
2x2 - 7x4 <= 0
*
!*
x2 - x3 + 2x4 >= 0.5
*
!*
x1 + x2 + x3 +x4 = 9
*
!*
and all x's >=0.
*
!*
*
!* Number of variables in E.F.: 4
*
!* Number of <= inequalities..: 2
*
!* Number of >= inequalities..: 1
*
!* Number of = equalities.....: 1
*
!* Input Economic Function:
*
!* Coefficient # 1: 1
*
!* Coefficient # 2: 1
*
!* Coefficient # 3: 3
*
!* Coefficient # 4: -0.5
*
!* Constant term..: 0
*
!* Input constraint # 1:
*
!* Coefficient # 1: 1
*
!* Coefficient # 2: 0
*
!* Coefficient # 3: 2
*
!* Coefficient # 4: 0
*
!* Constant term..: 740
*
!* Input constraint # 2:
*
!* Coefficient # 1: 0
*
!* Coefficient # 2: 2
*
!* Coefficient # 3: 0
*
!* Coefficient # 4: -7
*
!* Constant term..: 0
*
!* Input constraint # 3:
*
!* Coefficient # 1: 0
*
!* Coefficient # 2: 1
*
!* Coefficient # 3: -1
*
!* Coefficient # 4: 2
*
!* Constant term..: 0.5
*
!* Input constraint # 4:
*
!* Coefficient # 1: 1
*
!* Coefficient # 2: 1
*
!* Coefficient # 3: 1
*
!* Coefficient # 4: 1
*
!* Constant term..: 9
*
!*
*
!* Input Table:
*
!*
0.00
1.00
1.00
3.00
-0.50
*
!* 740.00
-1.00
0.00
-2.00
0.00
*
!*
0.00
0.00
-2.00
0.00
7.00
*
!*
0.50
0.00
-1.00
1.00
-2.00
*
!*
9.00
-1.00
-1.00
-1.00
-1.00
*
!*
*
!* Maximum of E.F. =
17.02500
*
!* X 1 =
0.000000
*
!* X 2 =
3.325000
*
!* X 3 =
4.725000
*

!* X 4 =
0.950000
*
!*
*
!* ------------------------------------------------------------ *
!* Reference: "Numerical Recipes by W.H. Press, B. P. Flannery, *
!*
S.A. Teukolsky and W.T. Vetterling, Cambridge
*
!*
University Press, 1986".
*
!*
*
!*
F90 Release 1.0 By J-P Moreau, Paris
*
!*
(www.jpmoreau.fr)
*
!****************************************************************
PROGRAM TEST_SIMPLEX
implicit none
integer I,ICASE,J,M,N,M1,M2,M3
integer, parameter :: MMAX=25, NMAX=25
REAL A(MMAX,NMAX)
INTEGER IPOSV(MMAX), IZROV(NMAX)
REAL R
print *,' '
write(*,10,advance='no');
write(*,20,advance='no');
write(*,30,advance='no');
write(*,40,advance='no');
M=M1+M2+M3

read
read
read
read

*,
*,
*,
*,

N
M1
M2
M3

!Total number of constraints

A=0.
print *,'Input Economic Function:'
do i=2,N+1
write(*,50,advance='no') i-1; read *,A(1,i)
end do
write(*,51,advance='no'); read *,A(1,1)
!input constraints
do i=1, M
write(*,60) i
do j=2,N+1
write(*,50,advance='no') j-1; read *, R
A(i+1,j) = -R
end do
write(*,51,advance='no'); read *,A(i+1,1)
end do
print *,' '
print *,' Input Table:'
write(*,100) ((A(I,J),J=1,N+1),I=1,M+1)
call simplx(A,M,N,MMAX,NMAX,M1,M2,M3,ICASE,IZROV,IPOSV)
print *,' '
print *,' Maximum of E.F. = ', A(1,1)
do I=1, N
do J=1, M
if (IPOSV(J).eq.I) then
write(*,110) I, A(J+1, 1)
goto 3
end if

end do
write(*,110) I, 0.0
3 end do
print *,' '
10
20
30
40
50
51
60

format('
format('
format('
format('
format('
format('
format('

Number of variables in E.F.:


Number of <= inequalities..:
Number of >= inequalities..:
Number of = equalities.....:
Coefficient #',I2,': ')
Constant term..: ')
Input constraint #',I2,': ')

')
')
')
')

100 format(5F8.2)
110 format(' X',I2,' = ',F12.6)
END
SUBROUTINE simplx(a,m,n,mp,np,m1,m2,m3,icase,izrov,iposv)
implicit none
INTEGER icase,m,m1,m2,m3,mp,n,np,iposv(m),izrov(n)
REAL a(mp,np)
INTEGER, PARAMETER :: MMAX=100, NMAX=100
REAL, PARAMETER :: EPS=1.E-6
!--------------------------------------------------------------------------------------! USES simp1,simp2,simp3
!Simplex method for linear programming. Input parameters a, m, n, mp, np,
m1, m2, and m3,
!and output parameters a, icase, izrov, and iposv are described above.
!Parameters: MMAX is the maximum number of constraints expected; NMAX is
the maximum
!number of variables expected; EPS is the absolute precision, which
should be adjusted to
!the scale of your variables.
!--------------------------------------------------------------------------------------INTEGER i,ip,ir,is,k,kh,kp,m12,nl1,nl2,l1(NMAX),l2(MMAX),l3(MMAX)
REAL bmax,q1
if(m.ne.m1+m2+m3) pause ' Bad input constraint counts in simplx.'
nl1=n
do k=1,n
l1(k)=k
!Initialize index list of columns admissible for exchange.
izrov(k)=k !Initially make all variables right-hand.
end do
nl2=m
do i=1,m
if(a(i+1,1).lt.0.)pause ' Bad input tableau in simplx, Constants bi
must be nonnegative.'
l2(i)=i
iposv(i)=n+i
!-----------------------------------------------------------------------------------------------!Initial left-hand variables. m1 type constraints are represented by
having their slackv ariable
!initially left-hand, with no artificial variable. m2 type constraints
have their slack

!variable initially left-hand, with a minus sign, and their artificial


variable handled implicitly
!during their first exchange. m3 type constraints have their artificial
variable initially
!left-hand.
!-----------------------------------------------------------------------------------------------end do
do i=1,m2
l3(i)=1
end do
ir=0
if(m2+m3.eq.0) goto 30 !The origin is a feasible starting solution. Go to
phase two.
ir=1
do k=1,n+1
!Compute the auxiliary objective function.
q1=0.
do i=m1+1,m
q1=q1+a(i+1,k)
end do
a(m+2,k)=-q1
end do
10 call simp1(a,mp,np,m+1,l1,nl1,0,kp,bmax) !Find max. coeff. of
auxiliary objective fn
if(bmax.le.EPS.and.a(m+2,1).lt.-EPS)then
icase=-1
!Auxiliary objective function is still negative and
cant be improved,
return
!hence no feasible solution exists.
else if(bmax.le.EPS.and.a(m+2,1).le.EPS)then
!Auxiliary objective function is zero and cant be improved; we have a
feasible starting vector.
!Clean out the artificial variables corresponding to any remaining
equality constraints by
!goto 1s and then move on to phase two by goto 30.
m12=m1+m2+1
if (m12.le.m) then
do ip=m12,m
if(iposv(ip).eq.ip+n)then !Found an artificial variable for an
equalityconstraint.
call simp1(a,mp,np,ip,l1,nl1,1,kp,bmax)
if(bmax.gt.EPS) goto 1 !Exchange with column corresponding to
maximum
end if
!pivot element in row.
end do
end if
ir=0
m12=m12-1
if (m1+1.gt.m12) goto 30
do i=m1+1,m1+m2
!Change sign of row for any m2
constraints
!still present from the initial basis.
if(l3(i-m1).eq.1)then
do k=1,n+1
a(i+1,k)=-a(i+1,k)
end do
end if
end do

goto 30
!Go to phase two.
end if
call simp2(a,m,n,mp,np,l2,nl2,ip,kp,q1) !Locate a pivot element (phase
one).
if(ip.eq.0)then
!Maximum of auxiliary objective function
is
icase=-1
!unbounded, so no feasible solution
exists.
return
end if
1 call simp3(a,mp,np,m+1,n,ip,kp)
!Exchange a left- and a right-hand variable (phase one), then update
lists.
if(iposv(ip).ge.n+m1+m2+1)then
!Exchanged out an artificial variable
for an
!equality constraint. Make sure it stays
do k=1,nl1
!out by removing it from the l1 list.
if(l1(k).eq.kp) goto 2
end do
2 nl1=nl1-1
do is=k,nl1
l1(is)=l1(is+1)
end do
else
if(iposv(ip).lt.n+m1+1) goto 20
kh=iposv(ip)-m1-n
if(l3(kh).eq.0) goto 20
!Exchanged out an m2 type constraint.
l3(kh)=0
!If its the first time, correct the pivot
column
!or the minus sign and the implicit
end if
!artificial variable.
a(m+2,kp+1)=a(m+2,kp+1)+1.
do i=1,m+2
a(i,kp+1)=-a(i,kp+1)
end do
20 is=izrov(kp)
!Update lists of left- and right-hand
variables.
izrov(kp)=iposv(ip)
iposv(ip)=is
if (ir.ne.0) goto 10
!if still in phase one, go back to 10.
!End of phase one code for finding an initial feasible solution. Now, in
phase two, optimize it.
30 call simp1(a,mp,np,0,l1,nl1,0,kp,bmax) !Test the z-row for doneness.
if(bmax.le.EPS)then
!Done. Solution found. Return with the
good news.
icase=0
return
end if
call simp2(a,m,n,mp,np,l2,nl2,ip,kp,q1)
two).

!Locate a pivot element (phase

if(ip.eq.0)then
and return.
icase=1
return
end if

!Objective function is unbounded. Report

call simp3(a,mp,np,m,n,ip,kp)
variable (phase two),
goto 20
variables and
END

!Exchange a left- and a right-hand


!update lists of left- and right-hand
!return for another iteration.

!The preceding routine makes use of the following utility subroutines:


SUBROUTINE simp1(a,mp,np,mm,ll,nll,iabf,kp,bmax)
implicit none
INTEGER iabf,kp,mm,mp,nll,np,ll(np)
REAL bmax,a(mp,np)
!Determines the maximum of those elements whose index is contained in the
supplied list
!ll, either with or without taking the absolute value, as flagged by
iabf.
INTEGER k
REAL test
kp=ll(1)
bmax=a(mm+1,kp+1)
if(nll.lt.2) return
do k=2,nll
if(iabf.eq.0)then
test=a(mm+1,ll(k)+1)-bmax
else
test=abs(a(mm+1,ll(k)+1))-abs(bmax)
endif
if(test.gt.0.)then
bmax=a(mm+1,ll(k)+1)
kp=ll(k)
endif
end do
return
END
SUBROUTINE simp2(a,m,n,mp,np,l2,nl2,ip,kp,q1)
implicit none
INTEGER ii,ip,kp,mp,l2(mp),m,n,nl2,np
REAL a(mp,np),EPS
PARAMETER (EPS=1.e-6)
!Locate a pivot element, taking degeneracy into account.
INTEGER i,k
REAL q,q0,q1,qp
ip=0
if(nl2.lt.1) return
do i=1,nl2
if(a(i+1,kp+1).lt.-EPS) goto 2
end do
return !No possible pivots. Return with message.
2 q1=-a(l2(i)+1,1)/a(l2(i)+1,kp+1)
ip=l2(i)

if(i+1.gt.nl2) return
do i=i+1, nl2
ii=l2(i)
if(a(ii+1,kp+1).lt.-EPS)then
q=-a(ii+1,1)/a(ii+1,kp+1)
if(q.lt.q1)then
ip=ii
q1=q
else if (q.eq.q1) then !We have a degeneracy.
do k=1,n
qp=-a(ip+1,k+1)/a(ip+1,kp+1)
q0=-a(ii+1,k+1)/a(ii+1,kp+1)
if(q0.ne.qp)goto 6
end do
6
if(q0.lt.qp) ip=ii
end if
end if
end do
return
END
SUBROUTINE simp3(a,mp,np,i1,k1,ip,kp)
implicit none
INTEGER i1,ip,k1,kp,mp,np
REAL a(mp,np)
!Matrix operations to exchange a left-hand and right-hand variable (see
text).
INTEGER ii,kk
REAL piv
piv=1./a(ip+1,kp+1)
if (i1.ge.0) then
do ii=1,i1+1
if(ii-1.ne.ip)then
a(ii,kp+1)=a(ii,kp+1)*piv
do kk=1,k1+1
if(kk-1.ne.kp)then
a(ii,kk)=a(ii,kk)-a(ip+1,kk)*a(ii,kp+1)
end if
end do
end if
end do
end if
do kk=1,k1+1
if(kk-1.ne.kp) a(ip+1,kk)=-a(ip+1,kk)*piv
end do
a(ip+1,kp+1)=piv
return
END
!end of file tsimplex.f90