1 junk simplex
(input
, output
);
3 { two-phase simplex algorithm
: version Feb.
24, 1988 }
5 { copyright K. Steiglitz
}
6 { Computer Science Dept.
}
7 { Princeton University
08544 }
11 maxpivots
= 1000; { maximum no. of pivots
}
12 large
= 1.0e+31; { large number used in search for minimum cost column
}
13 lowlim
= -1.0e+31; { large negative number to test for unboundedness
}
14 mmax
= 32; { max. no. of rows
}
15 ncolmax
= 50; { max. no. of columns allowed in tableau
}
16 eps
= 1.0e-8; { for testing for zero
}
19 done
, unbounded
, optimal
: boolean
; { flags for simplex
}
20 result
: (toomanycols
, unbound
, infeas
, toomanypivots
, opt
);
21 m
: 1..mmax
; { no. of rows
- 1, the rows are numbered
0..m
}
22 numpivots
: integer
; { pivot count
}
23 pivotcol
, pivotrow
: integer
; { pivot column and row
}
24 pivotel
: real
; { pivot element
}
25 cbar
: real
; { price when searching for entering column
}
26 carry
: array
[-1..mmax
, -1..mmax
] of real
; { inverse-basis matrix of the
27 revised simplex method
}
28 phase
: 1.
.2; { phase
}
29 price
: array
[0..mmax
] of real
; { shadow prices
= row
-1 of carry
=
31 basis
: array
[0..mmax
] of integer
; { basis columns
, negative integers
33 ncol
: 1..ncolmax
; { number of columns
}
34 tab
: array
[0..mmax
, 1..ncolmax
] of real
; { tableau
}
35 lhs
: array
[0..mmax
] of real
; { left-hand-side
}
36 d
: array
[1..ncolmax
] of real
; { current cost vector
}
37 c
: array
[1..ncolmax
] of real
; { cost vector in original problem
}
38 curcol
: array
[-1..mmax
] of real
; { current column
}
39 curcost
: real
; { current cost
}
40 i
, col
, row
: integer
; { miscellaneous variables
}
42 procedure columnsearch
;
43 { looks for favorable column to enter basis.
44 returns lowest cost and its column number
, or turns on the flag optimal
}
48 tempcost
: real
; { minimum cost
, temporary cost of column
}
50 begin
{ columnsearch
}
51 for i
:= 0 to m do price
[i
]:= -carry
[-1, i
]; { set up price vector
}
55 for col
:= 1 to ncol do
58 for i
:= 0 to m do tempcost
:= tempcost
- price
[i
]*tab
[i
, col
];
59 if
( cbar
> tempcost
) then
65 if
( cbar
> -eps
) then optimal
:= true
70 { looks for pivot row. returns pivot row number
,
71 or turns on the flag unbounded
}
75 ratio
, minratio
: real
; { ratio and minimum ratio for ratio test
}
78 for i
:= 0 to m do
{ generate column
}
80 curcol
[i
]:= 0.0; { current column
= B inverse
* original col.
}
81 for j
:= 0 to m do curcol
[i
]:=
82 curcol
[i
] + carry
[i
, j
]*tab
[j
, pivotcol
]
84 curcol
[-1]:= cbar
; { first element in current column
}
87 for i
:= 0 to m do
{ ratio test
}
89 if
( curcol
[i
] > eps
) then
91 ratio
:= carry
[i
, -1]/curcol
[i
];
92 if
( minratio
> ratio
) then
{ favorable row
}
98 else
{ break tie with max pivot
}
99 if
( (minratio
= ratio
) and
(pivotel
< curcol
[i
]) ) then
106 if
( pivotrow
= -1 ) then unbounded
:= true
{ nothing found
}
107 else unbounded
:= false
118 basis
[pivotrow
]:= pivotcol
;
119 for j
:= -1 to m do carry
[pivotrow
, j
]:= carry
[pivotrow
, j
]/pivotel
;
121 if
( i
<> pivotrow
) then
123 carry
[i
, j
]:= carry
[i
, j
] - carry
[pivotrow
, j
]*curcol
[i
];
124 curcost
:= -carry
[-1, -1]
128 procedure changephase
;
129 { changes phase from
1 to
2, by switching to original cost vector
}
134 begin
{ changephase
}
136 for i
:= 0 to m do if
( basis
[i
] <= 0 ) then
137 writeln
( '...artificial basis element '
, basis
[i
]:5,
138 ' remains in basis after phase
1'
);
139 for j
:= 1 to ncol do d
[j
]:= c
[j
]; { switch to original cost vector
}
145 b
:= basis
[i
]; { ignore artificial basis elements that are
}
146 if
( b
>= 1 ) then
{ still in basis
}
147 carry
[-1, j
]:= carry
[-1, j
] - c
[b
]*carry
[i
,j
];
150 curcost
:= -carry
[-1, -1]
154 { sets up test problem
, lhs
= tab
*x
, x
>= 0, min c
*x
}
155 { nrow
= number of rows
; ncol
= number of cols
}
156 { tab
= tableau
; lhs
= constants
}
162 readln
(nrow
); { read number of rows
}
163 readln
(ncol
); { read number of columns
}
164 m
:= nrow
- 1; { rows are numbered
0..m
}
166 read
(c
[j
]); { cost vector
}
169 read
(lhs
[i
]); { left-hand-side
}
171 read
(tab
[i
, j
]); { tableau
}
174 done
:= false
; { initialize carry matrix
, etc.
}
176 for i
:= -1 to m do for j
:= -1 to mmax do carry
[i
, j
]:= 0.0;
177 for i
:= 0 to m do carry
[i
, i
]:= 1.0; { artificial basis
}
180 carry
[i
, -1]:= lhs
[i
]; { -1 col of carry
= left-hand-side
}
181 carry
[-1, -1]:= carry
[-1, -1] - lhs
[i
] { - initial cost
}
183 curcost
:= -carry
[-1, -1];
184 for i
:= 0 to m do basis
[i
]:= -i
; { initial
, artificial basis
}
185 if
( ncol
<= ncolmax
) then
{ check number of columns
}
186 for col
:= 1 to ncol do
{ initialize cost vector for phase
1 }
189 for row
:= 0 to m do d
[col
]:= d
[col
] - tab
[row
, col
]
193 writeln
('...termination
: too many columns for storage'
);
203 while
( (numpivots
< maxpivots
) and
(not done
) and
204 ( (curcost
> lowlim
) or
(phase
= 1) ) ) do
207 if
( not optimal
) then
208 begin
{ not optimal
}
214 writeln
('problem is unbounded'
)
219 numpivots
:= numpivots
+ 1;
220 if
( (numpivots
= 1 ) or
( numpivots mod
10 = 0 ) ) then
221 writeln
('pivot '
, numpivots
:4, ' cost
= '
, curcost
:12)
227 if
( curcost
> eps
) then
231 writeln
('problem is infeasible'
)
235 if
( (numpivots
<> 1 ) and
( numpivots mod
10 <> 0 ) ) then
236 writeln
('pivot '
, numpivots
:4, ' cost
= '
, curcost
:12);
237 writeln
('phase
1 successfully completed'
);
243 if
( (numpivots
<> 1 ) and
( numpivots mod
10 <> 0 ) ) then
244 writeln
('pivot '
, numpivots
:4, ' cost
= '
, curcost
:12);
245 writeln
('phase
2 successfully completed'
);
250 if
(((curcost
<= lowlim
) and
(phase
= 2) ) then
252 if
( (numpivots
<> 1 ) and
( numpivots mod
10 <> 0 ) ) then
253 writeln
('pivot '
, numpivots
:4, ' cost
= '
, curcost
:12);
255 writeln
('problem is unbounded'
)
257 if
( numpivots
>= maxpivots
) then
259 writeln
('...termination
: maximum number of pivots exceeded'
);
260 result
:= toomanypivots
,
265 writeln
('optimal solution reached'
);
266 writeln
('cost
='
, -carry
[-1,-1]:10:6);
268 writeln
('x
('
, basis
[i
]:4, '
)= '
, carry
[i
,-1]:10:6)