Updating the changelog in the VERSION file, and version_sync.
[shapes.git] / source / basicsimplex.cc
blob38a9bb99734ba2d99d9da5d3ae7a13270e133357
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
28 using namespace Shapes;
30 Computation::BasicSimplex::BasicSimplex( size_t nVars, size_t nEqns )
31 : nVars_( nVars ), nEqns_( nEqns ),
32 nExt_( nVars + nEqns ),
33 a_( new double[ nEqns_ * ( nExt_ ) ] ),
34 b_( new double[ nEqns_ ] ),
35 c_( new double[ nExt_ ] ),
36 varSet_( new size_t[ nExt_ ] ),
37 nonBasicBegin_( varSet_ ),
38 nonBasicEnd_( nonBasicBegin_ + nVars_ ),
39 basicBegin_( nonBasicEnd_ ),
40 basicEnd_( basicBegin_ + nEqns_ )
41 { }
43 Computation::BasicSimplex::~BasicSimplex( )
45 delete a_;
46 delete b_;
47 delete c_;
48 delete varSet_;
52 // Call this function with preallocated memory for the result!
54 // It solves the problem of minimizing < c, *xdst > under the constraints
55 // *xdst >= 0
56 // a * *xdst <= b
57 // The constraints are stored in row major order, so consecutive memory
58 // belongs to the same constraint, not the same variable.
59 // The optimum is returned in *objdst, and the return value
60 // is true if optimization finished with *objdst < objGoal.
61 // If the return value is true, then the optimum is generally not located,
62 // but only a sufficiently good point.
63 bool
64 Computation::BasicSimplex::minimize( double * xdst,
65 double * objdst, double objGoal,
66 const double * c, const double * a, const double * b,
67 bool changeSign ) const
69 // Setup extended formulation with equality constraints and slack variables:
71 bool infeasibleStart = false;
74 // Initialize c;
75 double * end = c_ + nVars_;
76 double * dst = c_;
77 const double * src = c;
78 if( changeSign )
80 for( ; dst != end; ++dst, ++src )
82 *dst = *src;
85 else
87 for( ; dst != end; ++dst, ++src )
89 *dst = - *src;
92 end += nEqns_;
93 for( ; dst != end; ++dst )
95 *dst = 0;
100 // Initialize a and b
102 // First all of a is zeroed.
103 double * end = a_ + nEqns_ * ( nExt_ );
104 double * dst = a_;
105 for( ; dst != end; ++dst )
107 *dst = 0;
111 const double * srcb = b;
112 double * dstb = b_;
113 for( size_t eq = 0; eq < nEqns_; ++eq, ++srcb, ++dstb )
115 *dstb = *srcb;
116 if( *dstb < 0 )
118 infeasibleStart = true;
121 double * dst = a_ + eq * ( nExt_ );
122 const double * src = a + eq * nVars_;
123 const double * end = src + nVars_;
124 for( ; src != end; ++src, ++dst )
126 *dst = *src;
128 dst += eq;
129 *dst = 1;
133 // The basic and non-basic sets contain indices to variables.
134 // The basic set is organized so that the basic variable in equaiton i is located at ( basic + i ).
137 size_t i = 0;
138 for( size_t * dst = nonBasicBegin_; dst != basicEnd_; ++dst, ++i )
140 *dst = i;
144 double objective;
145 if( infeasibleStart )
147 if( phaseOne( ) )
149 objective = phaseTwo( xdst, objGoal );
151 else
153 objective = HUGE_VAL;
156 else
158 objective = phaseTwo( xdst, objGoal );
161 if( changeSign )
163 *objdst = - objective;
165 else
167 *objdst = objective;
169 return objective < objGoal;
173 bool
174 Computation::BasicSimplex::maximize( double * xdst,
175 double * objdst, double objGoal,
176 const double * c, const double * a, const double * b ) const
178 return minimize( xdst,
179 objdst, -objGoal,
180 c, a, b,
181 true );
185 // Function to compute a feasible tableau.
186 bool
187 Computation::BasicSimplex::phaseOne( ) const
189 throw "Not implemented: Computation::BasicSimplex::phaseOne.";
192 // Function for minimizing given a feasible initial tableau.
193 double
194 Computation::BasicSimplex::phaseTwo( double * xdst, double objGoal ) const
196 double objective = 0;
198 while( true )
201 if( false )
203 // Debug print.
204 std::cerr << "Simplex tableau:" << std::endl ;
205 for( size_t i = 0; i < 3 + nExt_ * 8 + 5; ++i )
207 std::cerr << "=" ;
209 std::cerr << std::endl ;
210 std::cerr << " |" ;
211 for( size_t col = 0; col < nExt_; ++col )
213 std::cerr << " " ;
215 bool found = false;
216 for( const size_t * src = basicBegin_; src != basicEnd_; ++src )
218 if( *src == col )
220 found = true;
221 break;
224 if( found )
226 std::cerr << "+" ;
228 else
230 std::cerr << " " ;
234 bool found = false;
235 for( const size_t * src = nonBasicBegin_; src != nonBasicEnd_; ++src )
237 if( *src == col )
239 found = true;
240 break;
243 if( found )
245 std::cerr << "-" ;
247 else
249 std::cerr << " " ;
251 std::cerr << " " ;
254 std::cerr << std::endl ;
255 std::cerr << " |" ;
256 for( const double * src = c_; src != c_ + nExt_; ++src )
258 static char buf[10];
259 sprintf( buf, "%7.3f", *src );
260 std::cerr << buf << " " ;
262 std::cerr << " | obj: " << objective << std::endl ;
263 for( size_t i = 0; i < 3 + nExt_ * 8 + 5; ++i )
265 std::cerr << "-" ;
267 std::cerr << std::endl ;
269 const double * srca = a_;
270 for( size_t row = 0; row < nEqns_; ++row )
272 std::cerr << *( basicBegin_ + row ) << " |" ;
273 const double * end = srca + nExt_;
274 for( ; srca != end; ++srca )
276 static char buf[10];
277 sprintf( buf, "%7.3f", *srca );
278 std::cerr << buf << " " ;
280 std::cerr << " | " << *( b_ + row ) << std::endl ;
282 for( size_t i = 0; i < 3 + nExt_ * 8 + 5; ++i )
284 std::cerr << "=" ;
286 std::cerr << std::endl ;
287 std::cerr << std::endl ;
290 // End of debug prints
293 if( objective < objGoal )
295 goto finished;
298 // Pick a pivot column. That is, the non-basic variable with the most positive coefficient
299 size_t * nonBasicCol = 0;
301 double best = 0;
302 for( size_t * src = nonBasicBegin_; src != nonBasicEnd_; ++src )
304 if( *( c_ + *src ) > best)
306 best = *( c_ + *src );
307 nonBasicCol = src;
311 if( nonBasicCol == 0 )
313 goto finished;
316 size_t col = *nonBasicCol;
318 // Find the outgoing row
319 size_t row = nEqns_;
321 double thMin = HUGE_VAL;
322 const double * srca = a_ + col;
323 const double * srcb = b_;
324 for( size_t i = 0; i < nEqns_; ++i, srca += nExt_, ++srcb )
326 if( *srca > 0 )
328 double tmp = *srcb / *srca;
329 if( tmp < thMin )
331 thMin = tmp;
332 row = i;
336 if( row == nEqns_ )
338 // There is no constraining equation.
340 // This return value is special, and does not correspond to the returned *dstx.
341 objective = -HUGE_VAL;
342 goto finished;
347 // Normalize the pivot
348 double * dst = a_ + nExt_ * row;
349 double tmp = 1. / *( dst + col );
350 double * end = dst + nExt_;
351 for( ; dst != end; ++dst )
353 *dst *= tmp;
355 *( b_ + row ) *= tmp;
359 // Reduce other rows
361 // Note that structural zeroes are kept track of using the basic/nonBasic distinction, and need not be enforced in a.
363 double * dst = a_;
364 double * enda = a_ + ( nExt_ * nEqns_ );
365 const double * pivota = a_ + nExt_ * row;
366 double * dstb = b_;
367 double pivotb = *( b_ + row );
368 for( ; dst != enda; ++dstb )
370 if( dst == pivota )
372 dst += nExt_;
373 continue;
375 double * end = dst + nExt_;
376 const double * src = pivota;
377 double tmp = *( dst + col );
378 for( ; dst != end; ++dst, ++src )
380 *dst -= tmp * *src;
382 *dstb -= tmp * pivotb;
386 // "Reduce objective"
387 const double * src = pivota;
388 double * dst = c_;
389 double * end = dst + nExt_;
390 double tmp = *( dst + col );
391 for( ; dst != end; ++dst, ++src )
393 *dst -= tmp * *src;
395 objective -= tmp * pivotb;
401 // Update the sets
402 *nonBasicCol = *( basicBegin_ + row );
403 *( basicBegin_ + row ) = col;
408 finished:
410 double * dst = xdst;
411 double * end = dst + nVars_;
412 for( ; dst != end; ++dst )
414 *dst = 0;
416 const double * srcb = b_;
417 for( const size_t * src = basicBegin_; src != basicEnd_; ++src, ++srcb )
419 if( *src < nVars_ )
421 *( xdst + *src ) = *srcb;
425 return objective;