| 1 | /* $Id: CoinWarmStartBasis.hpp 1372 2011-01-03 23:31:00Z lou $ */ |
| 2 | /*! \legal |
| 3 | Copyright (C) 2000 -- 2003, International Business Machines Corporation |
| 4 | and others. All Rights Reserved. |
| 5 | This code is licensed under the terms of the Eclipse Public License (EPL). |
| 6 | */ |
| 7 | |
| 8 | /*! \file CoinWarmStart.hpp |
| 9 | \brief Declaration of the generic simplex (basis-oriented) warm start |
| 10 | class. Also contains a basis diff class. |
| 11 | */ |
| 12 | |
| 13 | #ifndef CoinWarmStartBasis_H |
| 14 | #define CoinWarmStartBasis_H |
| 15 | |
| 16 | #include <vector> |
| 17 | |
| 18 | #include "CoinSort.hpp" |
| 19 | #include "CoinHelperFunctions.hpp" |
| 20 | #include "CoinWarmStart.hpp" |
| 21 | |
| 22 | //############################################################################# |
| 23 | |
| 24 | /*! \class CoinWarmStartBasis |
| 25 | \brief The default COIN simplex (basis-oriented) warm start class |
| 26 | |
| 27 | CoinWarmStartBasis provides for a warm start object which contains the |
| 28 | status of each variable (structural and artificial). |
| 29 | |
| 30 | \todo Modify this class so that the number of status entries per byte |
| 31 | and bytes per status vector allocation unit are not hardcoded. |
| 32 | At the least, collect this into a couple of macros. |
| 33 | |
| 34 | \todo Consider separate fields for allocated capacity and actual basis |
| 35 | size. We could avoid some reallocation, at the price of retaining |
| 36 | more space than we need. Perhaps more important, we could do much |
| 37 | better sanity checks. |
| 38 | */ |
| 39 | |
| 40 | class CoinWarmStartBasis : public virtual CoinWarmStart { |
| 41 | public: |
| 42 | |
| 43 | /*! \brief Enum for status of variables |
| 44 | |
| 45 | Matches CoinPrePostsolveMatrix::Status, without superBasic. Most code that |
| 46 | converts between CoinPrePostsolveMatrix::Status and |
| 47 | CoinWarmStartBasis::Status will break if this correspondence is broken. |
| 48 | |
| 49 | The status vectors are currently packed using two bits per status code, |
| 50 | four codes per byte. The location of the status information for |
| 51 | variable \c i is in byte <code>i>>2</code> and occupies bits 0:1 |
| 52 | if <code>i\%4 == 0</code>, bits 2:3 if <code>i\%4 == 1</code>, etc. |
| 53 | The non-member functions getStatus(const char*,int) and |
| 54 | setStatus(char*,int,CoinWarmStartBasis::Status) are provided to hide |
| 55 | details of the packing. |
| 56 | */ |
| 57 | enum Status { |
| 58 | isFree = 0x00, ///< Nonbasic free variable |
| 59 | basic = 0x01, ///< Basic variable |
| 60 | atUpperBound = 0x02, ///< Nonbasic at upper bound |
| 61 | atLowerBound = 0x03 ///< Nonbasic at lower bound |
| 62 | }; |
| 63 | |
| 64 | /** \brief Transfer vector entry for |
| 65 | mergeBasis(const CoinWarmStartBasis*,const XferVec*,const XferVec*) |
| 66 | */ |
| 67 | typedef CoinTriple<int,int,int> XferEntry ; |
| 68 | |
| 69 | /** \brief Transfer vector for |
| 70 | mergeBasis(const CoinWarmStartBasis*,const XferVec*,const XferVec*) |
| 71 | */ |
| 72 | typedef std::vector<XferEntry> XferVec ; |
| 73 | |
| 74 | public: |
| 75 | |
| 76 | /*! \name Methods to get and set basis information. |
| 77 | |
| 78 | The status of variables is kept in a pair of arrays, one for structural |
| 79 | variables, and one for artificials (aka logicals and slacks). The status |
| 80 | is coded using the values of the Status enum. |
| 81 | |
| 82 | \sa CoinWarmStartBasis::Status for a description of the packing used in |
| 83 | the status arrays. |
| 84 | */ |
| 85 | //@{ |
| 86 | /// Return the number of structural variables |
| 87 | inline int getNumStructural() const { return numStructural_; } |
| 88 | |
| 89 | /// Return the number of artificial variables |
| 90 | inline int getNumArtificial() const { return numArtificial_; } |
| 91 | |
| 92 | /** Return the number of basic structurals |
| 93 | |
| 94 | A fast test for an all-slack basis. |
| 95 | */ |
| 96 | int numberBasicStructurals() const ; |
| 97 | |
| 98 | /// Return the status of the specified structural variable. |
| 99 | inline Status getStructStatus(int i) const { |
| 100 | const int st = (structuralStatus_[i>>2] >> ((i&3)<<1)) & 3; |
| 101 | return static_cast<CoinWarmStartBasis::Status>(st); |
| 102 | } |
| 103 | |
| 104 | /// Set the status of the specified structural variable. |
| 105 | inline void setStructStatus(int i, Status st) { |
| 106 | char& st_byte = structuralStatus_[i>>2]; |
| 107 | st_byte = static_cast<char>(st_byte & ~(3 << ((i&3)<<1))) ; |
| 108 | st_byte = static_cast<char>(st_byte | (st << ((i&3)<<1))) ; |
| 109 | } |
| 110 | |
| 111 | /** Return the status array for the structural variables |
| 112 | |
| 113 | The status information is stored using the codes defined in the |
| 114 | Status enum, 2 bits per variable, packed 4 variables per byte. |
| 115 | */ |
| 116 | inline char * getStructuralStatus() { return structuralStatus_; } |
| 117 | |
| 118 | /** \c const overload for |
| 119 | \link CoinWarmStartBasis::getStructuralStatus() |
| 120 | getStructuralStatus() |
| 121 | \endlink |
| 122 | */ |
| 123 | inline const char * getStructuralStatus() const { return structuralStatus_; } |
| 124 | |
| 125 | /** As for \link getStructuralStatus() getStructuralStatus \endlink, |
| 126 | but returns the status array for the artificial variables. |
| 127 | */ |
| 128 | inline char * getArtificialStatus() { return artificialStatus_; } |
| 129 | |
| 130 | /// Return the status of the specified artificial variable. |
| 131 | inline Status getArtifStatus(int i) const { |
| 132 | const int st = (artificialStatus_[i>>2] >> ((i&3)<<1)) & 3; |
| 133 | return static_cast<CoinWarmStartBasis::Status>(st); |
| 134 | } |
| 135 | |
| 136 | /// Set the status of the specified artificial variable. |
| 137 | inline void setArtifStatus(int i, Status st) { |
| 138 | char& st_byte = artificialStatus_[i>>2]; |
| 139 | st_byte = static_cast<char>(st_byte & ~(3 << ((i&3)<<1))) ; |
| 140 | st_byte = static_cast<char>(st_byte | (st << ((i&3)<<1))) ; |
| 141 | } |
| 142 | |
| 143 | /** \c const overload for |
| 144 | \link CoinWarmStartBasis::getArtificialStatus() |
| 145 | getArtificialStatus() |
| 146 | \endlink |
| 147 | */ |
| 148 | inline const char * getArtificialStatus() const { return artificialStatus_; } |
| 149 | |
| 150 | //@} |
| 151 | |
| 152 | /*! \name Basis `diff' methods */ |
| 153 | //@{ |
| 154 | |
| 155 | /*! \brief Generate a `diff' that can convert the warm start basis passed as |
| 156 | a parameter to the warm start basis specified by \c this. |
| 157 | |
| 158 | The capabilities are limited: the basis passed as a parameter can be no |
| 159 | larger than the basis pointed to by \c this. |
| 160 | */ |
| 161 | |
| 162 | virtual CoinWarmStartDiff* |
| 163 | generateDiff (const CoinWarmStart *const oldCWS) const override ; |
| 164 | |
| 165 | /*! \brief Apply \p diff to this basis |
| 166 | |
| 167 | Update this basis by applying \p diff. It's assumed that the allocated |
| 168 | capacity of the basis is sufficiently large. |
| 169 | */ |
| 170 | |
| 171 | virtual void |
| 172 | applyDiff (const CoinWarmStartDiff *const cwsdDiff) override ; |
| 173 | |
| 174 | //@} |
| 175 | |
| 176 | |
| 177 | /*! \name Methods to modify the warm start object */ |
| 178 | //@{ |
| 179 | |
| 180 | /*! \brief Set basis capacity; existing basis is discarded. |
| 181 | |
| 182 | After execution of this routine, the warm start object does not describe |
| 183 | a valid basis: all structural and artificial variables have status isFree. |
| 184 | */ |
| 185 | virtual void setSize(int ns, int na) ; |
| 186 | |
| 187 | /*! \brief Set basis capacity; existing basis is maintained. |
| 188 | |
| 189 | After execution of this routine, the warm start object describes a valid |
| 190 | basis: the status of new structural variables (added columns) is set to |
| 191 | nonbasic at lower bound, and the status of new artificial variables |
| 192 | (added rows) is set to basic. (The basis can be invalid if new structural |
| 193 | variables do not have a finite lower bound.) |
| 194 | */ |
| 195 | virtual void resize (int newNumberRows, int newNumberColumns); |
| 196 | |
| 197 | /** \brief Delete a set of rows from the basis |
| 198 | |
| 199 | \warning |
| 200 | This routine assumes that the set of indices to be deleted is sorted in |
| 201 | ascending order and contains no duplicates. Use deleteRows() if this is |
| 202 | not the case. |
| 203 | |
| 204 | \warning |
| 205 | The resulting basis is guaranteed valid only if all deleted |
| 206 | constraints are slack (hence the associated logicals are basic). |
| 207 | |
| 208 | Removal of a tight constraint with a nonbasic logical implies that |
| 209 | some basic variable must be made nonbasic. This correction is left to |
| 210 | the client. |
| 211 | */ |
| 212 | |
| 213 | virtual void compressRows (int tgtCnt, const int *tgts) ; |
| 214 | |
| 215 | /** \brief Delete a set of rows from the basis |
| 216 | |
| 217 | \warning |
| 218 | The resulting basis is guaranteed valid only if all deleted |
| 219 | constraints are slack (hence the associated logicals are basic). |
| 220 | |
| 221 | Removal of a tight constraint with a nonbasic logical implies that |
| 222 | some basic variable must be made nonbasic. This correction is left to |
| 223 | the client. |
| 224 | */ |
| 225 | |
| 226 | virtual void deleteRows(int rawTgtCnt, const int *rawTgts) ; |
| 227 | |
| 228 | /** \brief Delete a set of columns from the basis |
| 229 | |
| 230 | \warning |
| 231 | The resulting basis is guaranteed valid only if all deleted variables |
| 232 | are nonbasic. |
| 233 | |
| 234 | Removal of a basic variable implies that some nonbasic variable must be |
| 235 | made basic. This correction is left to the client. |
| 236 | */ |
| 237 | |
| 238 | virtual void deleteColumns(int number, const int * which); |
| 239 | |
| 240 | /** \brief Merge entries from a source basis into this basis. |
| 241 | |
| 242 | \warning |
| 243 | It's the client's responsibility to ensure validity of the merged basis, |
| 244 | if that's important to the application. |
| 245 | |
| 246 | The vector xferCols (xferRows) specifies runs of entries to be taken from |
| 247 | the source basis and placed in this basis. Each entry is a CoinTriple, |
| 248 | with first specifying the starting source index of a run, second |
| 249 | specifying the starting destination index, and third specifying the run |
| 250 | length. |
| 251 | */ |
| 252 | virtual void mergeBasis(const CoinWarmStartBasis *src, |
| 253 | const XferVec *xferRows, |
| 254 | const XferVec *xferCols) ; |
| 255 | |
| 256 | //@} |
| 257 | |
| 258 | /*! \name Constructors, destructors, and related functions */ |
| 259 | |
| 260 | //@{ |
| 261 | |
| 262 | /** Default constructor |
| 263 | |
| 264 | Creates a warm start object representing an empty basis |
| 265 | (0 rows, 0 columns). |
| 266 | */ |
| 267 | CoinWarmStartBasis(); |
| 268 | |
| 269 | /** Constructs a warm start object with the specified status vectors. |
| 270 | |
| 271 | The parameters are copied. |
| 272 | Consider assignBasisStatus(int,int,char*&,char*&) if the object should |
| 273 | assume ownership. |
| 274 | |
| 275 | \sa CoinWarmStartBasis::Status for a description of the packing used in |
| 276 | the status arrays. |
| 277 | */ |
| 278 | CoinWarmStartBasis(int ns, int na, const char* sStat, const char* aStat) ; |
| 279 | |
| 280 | /** Copy constructor */ |
| 281 | CoinWarmStartBasis(const CoinWarmStartBasis& ws) ; |
| 282 | |
| 283 | /** `Virtual constructor' */ |
| 284 | virtual CoinWarmStart *clone() const override |
| 285 | { |
| 286 | return new CoinWarmStartBasis(*this); |
| 287 | } |
| 288 | |
| 289 | /** Destructor */ |
| 290 | virtual ~CoinWarmStartBasis(); |
| 291 | |
| 292 | /** Assignment */ |
| 293 | |
| 294 | virtual CoinWarmStartBasis& operator=(const CoinWarmStartBasis& rhs) ; |
| 295 | |
| 296 | /** Assign the status vectors to be the warm start information. |
| 297 | |
| 298 | In this method the CoinWarmStartBasis object assumes ownership of the |
| 299 | pointers and upon return the argument pointers will be NULL. |
| 300 | If copying is desirable, use the |
| 301 | \link CoinWarmStartBasis(int,int,const char*,const char*) |
| 302 | array constructor \endlink |
| 303 | or the |
| 304 | \link operator=(const CoinWarmStartBasis&) |
| 305 | assignment operator \endlink. |
| 306 | |
| 307 | \note |
| 308 | The pointers passed to this method will be |
| 309 | freed using delete[], so they must be created using new[]. |
| 310 | */ |
| 311 | virtual void assignBasisStatus(int ns, int na, char*& sStat, char*& aStat) ; |
| 312 | //@} |
| 313 | |
| 314 | /*! \name Miscellaneous methods */ |
| 315 | //@{ |
| 316 | |
| 317 | /// Prints in readable format (for debug) |
| 318 | virtual void print() const; |
| 319 | /// Returns true if full basis (for debug) |
| 320 | bool fullBasis() const; |
| 321 | /// Returns true if full basis and fixes up (for debug) |
| 322 | bool fixFullBasis(); |
| 323 | |
| 324 | //@} |
| 325 | |
| 326 | protected: |
| 327 | /** \name Protected data members |
| 328 | |
| 329 | \sa CoinWarmStartBasis::Status for a description of the packing used in |
| 330 | the status arrays. |
| 331 | */ |
| 332 | //@{ |
| 333 | /// The number of structural variables |
| 334 | int numStructural_; |
| 335 | /// The number of artificial variables |
| 336 | int numArtificial_; |
| 337 | /// The maximum sise (in ints - actually 4*char) (so resize does not need to do new) |
| 338 | int maxSize_; |
| 339 | /** The status of the structural variables. */ |
| 340 | char * structuralStatus_; |
| 341 | /** The status of the artificial variables. */ |
| 342 | char * artificialStatus_; |
| 343 | //@} |
| 344 | }; |
| 345 | |
| 346 | |
| 347 | /*! \relates CoinWarmStartBasis |
| 348 | \brief Get the status of the specified variable in the given status array. |
| 349 | */ |
| 350 | |
| 351 | inline CoinWarmStartBasis::Status getStatus(const char *array, int i) { |
| 352 | const int st = (array[i>>2] >> ((i&3)<<1)) & 3; |
| 353 | return static_cast<CoinWarmStartBasis::Status>(st); |
| 354 | } |
| 355 | |
| 356 | /*! \relates CoinWarmStartBasis |
| 357 | \brief Set the status of the specified variable in the given status array. |
| 358 | */ |
| 359 | |
| 360 | inline void setStatus(char * array, int i, CoinWarmStartBasis::Status st) { |
| 361 | char& st_byte = array[i>>2]; |
| 362 | st_byte = static_cast<char>(st_byte & ~(3 << ((i&3)<<1))) ; |
| 363 | st_byte = static_cast<char>(st_byte | (st << ((i&3)<<1))) ; |
| 364 | } |
| 365 | |
| 366 | |
| 367 | |
| 368 | /*! \class CoinWarmStartBasisDiff |
| 369 | \brief A `diff' between two CoinWarmStartBasis objects |
| 370 | |
| 371 | This class exists in order to hide from the world the details of |
| 372 | calculating and representing a `diff' between two CoinWarmStartBasis |
| 373 | objects. For convenience, assignment, cloning, and deletion are visible to |
| 374 | the world, and default and copy constructors are made available to derived |
| 375 | classes. Knowledge of the rest of this structure, and of generating and |
| 376 | applying diffs, is restricted to the friend functions |
| 377 | CoinWarmStartBasis::generateDiff() and CoinWarmStartBasis::applyDiff(). |
| 378 | |
| 379 | The actual data structure is an unsigned int vector, #difference_ which |
| 380 | starts with indices of changed and then has values starting after #sze_ |
| 381 | |
| 382 | \todo This is a pretty generic structure, and vector diff is a pretty generic |
| 383 | activity. We should be able to convert this to a template. |
| 384 | |
| 385 | \todo Using unsigned int as the data type for the diff vectors might help |
| 386 | to contain the damage when this code is inevitably compiled for 64 bit |
| 387 | architectures. But the notion of int as 4 bytes is hardwired into |
| 388 | CoinWarmStartBasis, so changes are definitely required. |
| 389 | */ |
| 390 | |
| 391 | class CoinWarmStartBasisDiff : public virtual CoinWarmStartDiff |
| 392 | { public: |
| 393 | |
| 394 | /*! \brief `Virtual constructor' */ |
| 395 | virtual CoinWarmStartDiff *clone() const override |
| 396 | { CoinWarmStartBasisDiff *cwsbd = new CoinWarmStartBasisDiff(*this) ; |
| 397 | return (dynamic_cast<CoinWarmStartDiff *>(cwsbd)) ; } |
| 398 | |
| 399 | /*! \brief Assignment */ |
| 400 | virtual |
| 401 | CoinWarmStartBasisDiff &operator= (const CoinWarmStartBasisDiff &rhs) ; |
| 402 | |
| 403 | /*! \brief Destructor */ |
| 404 | virtual ~CoinWarmStartBasisDiff(); |
| 405 | |
| 406 | protected: |
| 407 | |
| 408 | /*! \brief Default constructor |
| 409 | |
| 410 | This is protected (rather than private) so that derived classes can |
| 411 | see it when they make <i>their</i> default constructor protected or |
| 412 | private. |
| 413 | */ |
| 414 | CoinWarmStartBasisDiff () : sze_(0), difference_(nullptr) { } |
| 415 | |
| 416 | /*! \brief Copy constructor |
| 417 | |
| 418 | For convenience when copying objects containing CoinWarmStartBasisDiff |
| 419 | objects. But consider whether you should be using #clone() to retain |
| 420 | polymorphism. |
| 421 | |
| 422 | This is protected (rather than private) so that derived classes can |
| 423 | see it when they make <i>their</i> copy constructor protected or |
| 424 | private. |
| 425 | */ |
| 426 | CoinWarmStartBasisDiff (const CoinWarmStartBasisDiff &cwsbd) ; |
| 427 | |
| 428 | /*! \brief Standard constructor */ |
| 429 | CoinWarmStartBasisDiff (int sze, const unsigned int *const diffNdxs, |
| 430 | const unsigned int *const diffVals) ; |
| 431 | |
| 432 | /*! \brief Constructor when full is smaller than diff!*/ |
| 433 | CoinWarmStartBasisDiff (const CoinWarmStartBasis * rhs); |
| 434 | |
| 435 | private: |
| 436 | |
| 437 | friend CoinWarmStartDiff* |
| 438 | CoinWarmStartBasis::generateDiff(const CoinWarmStart *const oldCWS) const ; |
| 439 | friend void |
| 440 | CoinWarmStartBasis::applyDiff(const CoinWarmStartDiff *const diff) ; |
| 441 | |
| 442 | /*! \brief Number of entries (and allocated capacity), in units of \c int. */ |
| 443 | int sze_ ; |
| 444 | |
| 445 | /*! \brief Array of diff indices and diff values */ |
| 446 | |
| 447 | unsigned int *difference_ ; |
| 448 | |
| 449 | } ; |
| 450 | |
| 451 | |
| 452 | #endif |
| 453 | |