Update procedures
[shapes.git] / source / basicsimplex.cc
blob67065792fc4296a6ced45a60b202bf5260e97761
1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * any later version.
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008 Henrik Tidefelt
19 #include <cmath>
21 #include "basicsimplex.h"
23 #include "autoonoff.h"
25 #include <vector>
26 #include <iostream> // For debugging
27 #include <cstdio>
29 using namespace Shapes;
31 Computation::BasicSimplex::BasicSimplex( size_t nVars, size_t nEqns )
32 : nVars_( nVars ), nEqns_( nEqns ),
33 nExt_( nVars + nEqns ),
34 a_( new double[ nEqns_ * ( nExt_ ) ] ),
35 b_( new double[ nEqns_ ] ),
36 c_( new double[ nExt_ ] ),
37 varSet_( new size_t[ nExt_ ] ),
38 nonBasicBegin_( varSet_ ),
39 nonBasicEnd_( nonBasicBegin_ + nVars_ ),
40 basicBegin_( nonBasicEnd_ ),
41 basicEnd_( basicBegin_ + nEqns_ )
42 { }
44 Computation::BasicSimplex::~BasicSimplex( )
46 delete a_;
47 delete b_;
48 delete c_;
49 delete varSet_;
53 // Call this function with preallocated memory for the result!
55 // It solves the problem of minimizing < c, *xdst > under the constraints
56 // *xdst >= 0
57 // a * *xdst <= b
58 // The constraints are stored in row major order, so consecutive memory
59 // belongs to the same constraint, not the same variable.
60 // The optimum is returned in *objdst, and the return value
61 // is true if optimization finished with *objdst < objGoal.
62 // If the return value is true, then the optimum is generally not located,
63 // but only a sufficiently good point.
64 bool
65 Computation::BasicSimplex::minimize( double * xdst,
66 double * objdst, double objGoal,
67 const double * c, const double * a, const double * b,
68 bool changeSign ) const
70 // Setup extended formulation with equality constraints and slack variables:
72 bool infeasibleStart = false;
75 // Initialize c;
76 double * end = c_ + nVars_;
77 double * dst = c_;
78 const double * src = c;
79 if( changeSign )
81 for( ; dst != end; ++dst, ++src )
83 *dst = *src;
86 else
88 for( ; dst != end; ++dst, ++src )
90 *dst = - *src;
93 end += nEqns_;
94 for( ; dst != end; ++dst )
96 *dst = 0;
101 // Initialize a and b
103 // First all of a is zeroed.
104 double * end = a_ + nEqns_ * ( nExt_ );
105 double * dst = a_;
106 for( ; dst != end; ++dst )
108 *dst = 0;
112 const double * srcb = b;
113 double * dstb = b_;
114 for( size_t eq = 0; eq < nEqns_; ++eq, ++srcb, ++dstb )
116 *dstb = *srcb;
117 if( *dstb < 0 )
119 infeasibleStart = true;
122 double * dst = a_ + eq * ( nExt_ );
123 const double * src = a + eq * nVars_;
124 const double * end = src + nVars_;
125 for( ; src != end; ++src, ++dst )
127 *dst = *src;
129 dst += eq;
130 *dst = 1;
134 // The basic and non-basic sets contain indices to variables.
135 // The basic set is organized so that the basic variable in equaiton i is located at ( basic + i ).
138 size_t i = 0;
139 for( size_t * dst = nonBasicBegin_; dst != basicEnd_; ++dst, ++i )
141 *dst = i;
145 double objective;
146 if( infeasibleStart )
148 if( phaseOne( ) )
150 objective = phaseTwo( xdst, objGoal );
152 else
154 objective = HUGE_VAL;
157 else
159 objective = phaseTwo( xdst, objGoal );
162 if( changeSign )
164 *objdst = - objective;
166 else
168 *objdst = objective;
170 return objective < objGoal;
174 bool
175 Computation::BasicSimplex::maximize( double * xdst,
176 double * objdst, double objGoal,
177 const double * c, const double * a, const double * b ) const
179 return minimize( xdst,
180 objdst, -objGoal,
181 c, a, b,
182 true );
186 // Function to compute a feasible tableau.
187 bool
188 Computation::BasicSimplex::phaseOne( ) const
190 throw "Not implemented: Computation::BasicSimplex::phaseOne.";
193 // Function for minimizing given a feasible initial tableau.
194 double
195 Computation::BasicSimplex::phaseTwo( double * xdst, double objGoal ) const
197 double objective = 0;
199 while( true )
202 if( false )
204 // Debug print.
205 std::cerr << "Simplex tableau:" << std::endl ;
206 for( size_t i = 0; i < 3 + nExt_ * 8 + 5; ++i )
208 std::cerr << "=" ;
210 std::cerr << std::endl ;
211 std::cerr << " |" ;
212 for( size_t col = 0; col < nExt_; ++col )
214 std::cerr << " " ;
216 bool found = false;
217 for( const size_t * src = basicBegin_; src != basicEnd_; ++src )
219 if( *src == col )
221 found = true;
222 break;
225 if( found )
227 std::cerr << "+" ;
229 else
231 std::cerr << " " ;
235 bool found = false;
236 for( const size_t * src = nonBasicBegin_; src != nonBasicEnd_; ++src )
238 if( *src == col )
240 found = true;
241 break;
244 if( found )
246 std::cerr << "-" ;
248 else
250 std::cerr << " " ;
252 std::cerr << " " ;
255 std::cerr << std::endl ;
256 std::cerr << " |" ;
257 for( const double * src = c_; src != c_ + nExt_; ++src )
259 static char buf[10];
260 std::sprintf( buf, "%7.3f", *src );
261 std::cerr << buf << " " ;
263 std::cerr << " | obj: " << objective << std::endl ;
264 for( size_t i = 0; i < 3 + nExt_ * 8 + 5; ++i )
266 std::cerr << "-" ;
268 std::cerr << std::endl ;
270 const double * srca = a_;
271 for( size_t row = 0; row < nEqns_; ++row )
273 std::cerr << *( basicBegin_ + row ) << " |" ;
274 const double * end = srca + nExt_;
275 for( ; srca != end; ++srca )
277 static char buf[10];
278 sprintf( buf, "%7.3f", *srca );
279 std::cerr << buf << " " ;
281 std::cerr << " | " << *( b_ + row ) << std::endl ;
283 for( size_t i = 0; i < 3 + nExt_ * 8 + 5; ++i )
285 std::cerr << "=" ;
287 std::cerr << std::endl ;
288 std::cerr << std::endl ;
291 // End of debug prints
294 if( objective < objGoal )
296 goto finished;
299 // Pick a pivot column. That is, the non-basic variable with the most positive coefficient
300 size_t * nonBasicCol = 0;
302 double best = 0;
303 for( size_t * src = nonBasicBegin_; src != nonBasicEnd_; ++src )
305 if( *( c_ + *src ) > best)
307 best = *( c_ + *src );
308 nonBasicCol = src;
312 if( nonBasicCol == 0 )
314 goto finished;
317 size_t col = *nonBasicCol;
319 // Find the outgoing row
320 size_t row = nEqns_;
322 double thMin = HUGE_VAL;
323 const double * srca = a_ + col;
324 const double * srcb = b_;
325 for( size_t i = 0; i < nEqns_; ++i, srca += nExt_, ++srcb )
327 if( *srca > 0 )
329 double tmp = *srcb / *srca;
330 if( tmp < thMin )
332 thMin = tmp;
333 row = i;
337 if( row == nEqns_ )
339 // There is no constraining equation.
341 // This return value is special, and does not correspond to the returned *dstx.
342 objective = -HUGE_VAL;
343 goto finished;
348 // Normalize the pivot
349 double * dst = a_ + nExt_ * row;
350 double tmp = 1. / *( dst + col );
351 double * end = dst + nExt_;
352 for( ; dst != end; ++dst )
354 *dst *= tmp;
356 *( b_ + row ) *= tmp;
360 // Reduce other rows
362 // Note that structural zeroes are kept track of using the basic/nonBasic distinction, and need not be enforced in a.
364 double * dst = a_;
365 double * enda = a_ + ( nExt_ * nEqns_ );
366 const double * pivota = a_ + nExt_ * row;
367 double * dstb = b_;
368 double pivotb = *( b_ + row );
369 for( ; dst != enda; ++dstb )
371 if( dst == pivota )
373 dst += nExt_;
374 continue;
376 double * end = dst + nExt_;
377 const double * src = pivota;
378 double tmp = *( dst + col );
379 for( ; dst != end; ++dst, ++src )
381 *dst -= tmp * *src;
383 *dstb -= tmp * pivotb;
387 // "Reduce objective"
388 const double * src = pivota;
389 double * dst = c_;
390 double * end = dst + nExt_;
391 double tmp = *( dst + col );
392 for( ; dst != end; ++dst, ++src )
394 *dst -= tmp * *src;
396 objective -= tmp * pivotb;
402 // Update the sets
403 *nonBasicCol = *( basicBegin_ + row );
404 *( basicBegin_ + row ) = col;
409 finished:
411 double * dst = xdst;
412 double * end = dst + nVars_;
413 for( ; dst != end; ++dst )
415 *dst = 0;
417 const double * srcb = b_;
418 for( const size_t * src = basicBegin_; src != basicEnd_; ++src, ++srcb )
420 if( *src < nVars_ )
422 *( xdst + *src ) = *srcb;
426 return objective;