[1370] | 1 | /* $Id: addRows.cpp 2278 2017-10-02 09:51:14Z forrest $ */ |
---|
[527] | 2 | // Copyright (C) 2004, International Business Machines |
---|
| 3 | // Corporation and others. All Rights Reserved. |
---|
[1662] | 4 | // This code is licensed under the terms of the Eclipse Public License (EPL). |
---|
[527] | 5 | |
---|
| 6 | |
---|
| 7 | // This is a simple example to create a model by row |
---|
| 8 | #include "ClpSimplex.hpp" |
---|
| 9 | #include "CoinHelperFunctions.hpp" |
---|
[538] | 10 | #include "CoinTime.hpp" |
---|
[540] | 11 | #include "CoinBuild.hpp" |
---|
[546] | 12 | #include "CoinModel.hpp" |
---|
[527] | 13 | #include <iomanip> |
---|
| 14 | #include <cassert> |
---|
| 15 | |
---|
[1559] | 16 | int main(int argc, const char *argv[]) |
---|
[527] | 17 | { |
---|
[2278] | 18 | #if COIN_BIG_INDEX<2 |
---|
[1552] | 19 | try { |
---|
| 20 | // Empty model |
---|
| 21 | ClpSimplex model; |
---|
| 22 | |
---|
| 23 | // Objective - just nonzeros |
---|
| 24 | int objIndex[] = {0, 2}; |
---|
| 25 | double objValue[] = {1.0, 4.0}; |
---|
| 26 | // Upper bounds - as dense vector |
---|
| 27 | double upper[] = {2.0, COIN_DBL_MAX, 4.0}; |
---|
| 28 | |
---|
| 29 | // Create space for 3 columns |
---|
| 30 | model.resize(0, 3); |
---|
| 31 | // Fill in |
---|
| 32 | int i; |
---|
| 33 | // Virtuous way |
---|
| 34 | // First objective |
---|
| 35 | for (i = 0; i < 2; i++) |
---|
| 36 | model.setObjectiveCoefficient(objIndex[i], objValue[i]); |
---|
| 37 | // Now bounds (lower will be zero by default but do again) |
---|
| 38 | for (i = 0; i < 3; i++) { |
---|
| 39 | model.setColumnLower(i, 0.0); |
---|
| 40 | model.setColumnUpper(i, upper[i]); |
---|
| 41 | } |
---|
| 42 | /* |
---|
| 43 | We could also have done in non-virtuous way e.g. |
---|
| 44 | double * objective = model.objective(); |
---|
| 45 | and then set directly |
---|
| 46 | */ |
---|
| 47 | // Faster to add rows all at once - but this is easier to show |
---|
| 48 | // Now add row 1 as >= 2.0 |
---|
| 49 | int row1Index[] = {0, 2}; |
---|
| 50 | double row1Value[] = {1.0, 1.0}; |
---|
| 51 | model.addRow(2, row1Index, row1Value, |
---|
| 52 | 2.0, COIN_DBL_MAX); |
---|
| 53 | // Now add row 2 as == 1.0 |
---|
| 54 | int row2Index[] = {0, 1, 2}; |
---|
| 55 | double row2Value[] = {1.0, -5.0, 1.0}; |
---|
| 56 | model.addRow(3, row2Index, row2Value, |
---|
| 57 | 1.0, 1.0); |
---|
| 58 | // solve |
---|
| 59 | model.dual(); |
---|
| 60 | |
---|
| 61 | /* |
---|
| 62 | Adding one row at a time has a significant overhead so let's |
---|
| 63 | try a more complicated but faster way |
---|
| 64 | |
---|
| 65 | First time adding in 10000 rows one by one |
---|
| 66 | */ |
---|
| 67 | model.allSlackBasis(); |
---|
| 68 | ClpSimplex modelSave = model; |
---|
| 69 | double time1 = CoinCpuTime(); |
---|
| 70 | int k; |
---|
[1559] | 71 | for (k = 0; k < 10000; k++) { |
---|
[1552] | 72 | int row2Index[] = {0, 1, 2}; |
---|
| 73 | double row2Value[] = {1.0, -5.0, 1.0}; |
---|
| 74 | model.addRow(3, row2Index, row2Value, |
---|
| 75 | 1.0, 1.0); |
---|
| 76 | } |
---|
| 77 | printf("Time for 10000 addRow is %g\n", CoinCpuTime() - time1); |
---|
| 78 | model.dual(); |
---|
| 79 | model = modelSave; |
---|
| 80 | // Now use build |
---|
| 81 | CoinBuild buildObject; |
---|
| 82 | time1 = CoinCpuTime(); |
---|
[1559] | 83 | for (k = 0; k < 10000; k++) { |
---|
[1552] | 84 | int row2Index[] = {0, 1, 2}; |
---|
| 85 | double row2Value[] = {1.0, -5.0, 1.0}; |
---|
| 86 | buildObject.addRow(3, row2Index, row2Value, |
---|
| 87 | 1.0, 1.0); |
---|
| 88 | } |
---|
| 89 | model.addRows(buildObject); |
---|
| 90 | printf("Time for 10000 addRow using CoinBuild is %g\n", CoinCpuTime() - time1); |
---|
| 91 | model.dual(); |
---|
| 92 | model = modelSave; |
---|
| 93 | int del[] = {0, 1, 2}; |
---|
| 94 | model.deleteRows(2, del); |
---|
| 95 | // Now use build +-1 |
---|
| 96 | CoinBuild buildObject2; |
---|
| 97 | time1 = CoinCpuTime(); |
---|
[1559] | 98 | for (k = 0; k < 10000; k++) { |
---|
[1552] | 99 | int row2Index[] = {0, 1, 2}; |
---|
| 100 | double row2Value[] = {1.0, -1.0, 1.0}; |
---|
| 101 | buildObject2.addRow(3, row2Index, row2Value, |
---|
| 102 | 1.0, 1.0); |
---|
| 103 | } |
---|
| 104 | model.addRows(buildObject2, true); |
---|
| 105 | printf("Time for 10000 addRow using CoinBuild+-1 is %g\n", CoinCpuTime() - time1); |
---|
| 106 | model.dual(); |
---|
| 107 | model = modelSave; |
---|
| 108 | model.deleteRows(2, del); |
---|
| 109 | // Now use build +-1 |
---|
| 110 | CoinModel modelObject2; |
---|
| 111 | time1 = CoinCpuTime(); |
---|
[1559] | 112 | for (k = 0; k < 10000; k++) { |
---|
[1552] | 113 | int row2Index[] = {0, 1, 2}; |
---|
| 114 | double row2Value[] = {1.0, -1.0, 1.0}; |
---|
| 115 | modelObject2.addRow(3, row2Index, row2Value, |
---|
| 116 | 1.0, 1.0); |
---|
| 117 | } |
---|
| 118 | model.addRows(modelObject2, true); |
---|
| 119 | printf("Time for 10000 addRow using CoinModel+-1 is %g\n", CoinCpuTime() - time1); |
---|
| 120 | model.dual(); |
---|
| 121 | model = ClpSimplex(); |
---|
| 122 | // Now use build +-1 |
---|
| 123 | CoinModel modelObject3; |
---|
| 124 | time1 = CoinCpuTime(); |
---|
[1559] | 125 | for (k = 0; k < 10000; k++) { |
---|
[1552] | 126 | int row2Index[] = {0, 1, 2}; |
---|
| 127 | double row2Value[] = {1.0, -1.0, 1.0}; |
---|
| 128 | modelObject3.addRow(3, row2Index, row2Value, |
---|
| 129 | 1.0, 1.0); |
---|
| 130 | } |
---|
| 131 | model.loadProblem(modelObject3, true); |
---|
| 132 | printf("Time for 10000 addRow using CoinModel load +-1 is %g\n", CoinCpuTime() - time1); |
---|
| 133 | model.writeMps("xx.mps"); |
---|
| 134 | model.dual(); |
---|
| 135 | model = modelSave; |
---|
| 136 | // Now use model |
---|
| 137 | CoinModel modelObject; |
---|
| 138 | time1 = CoinCpuTime(); |
---|
[1559] | 139 | for (k = 0; k < 10000; k++) { |
---|
[1552] | 140 | int row2Index[] = {0, 1, 2}; |
---|
| 141 | double row2Value[] = {1.0, -5.0, 1.0}; |
---|
| 142 | modelObject.addRow(3, row2Index, row2Value, |
---|
| 143 | 1.0, 1.0); |
---|
| 144 | } |
---|
| 145 | model.addRows(modelObject); |
---|
| 146 | printf("Time for 10000 addRow using CoinModel is %g\n", CoinCpuTime() - time1); |
---|
| 147 | model.dual(); |
---|
| 148 | model.writeMps("b.mps"); |
---|
| 149 | // Method using least memory - but most complicated |
---|
| 150 | time1 = CoinCpuTime(); |
---|
| 151 | // Assumes we know exact size of model and matrix |
---|
| 152 | // Empty model |
---|
| 153 | ClpSimplex model2; |
---|
| 154 | { |
---|
| 155 | // Create space for 3 columns and 10000 rows |
---|
| 156 | int numberRows = 10000; |
---|
| 157 | int numberColumns = 3; |
---|
| 158 | // This is fully dense - but would not normally be so |
---|
| 159 | int numberElements = numberRows * numberColumns; |
---|
| 160 | // Arrays will be set to default values |
---|
| 161 | model2.resize(numberRows, numberColumns); |
---|
| 162 | double * elements = new double [numberElements]; |
---|
| 163 | CoinBigIndex * starts = new CoinBigIndex [numberColumns+1]; |
---|
| 164 | int * rows = new int [numberElements];; |
---|
| 165 | int * lengths = new int[numberColumns]; |
---|
| 166 | // Now fill in - totally unsafe but .... |
---|
| 167 | // no need as defaults to 0.0 double * columnLower = model2.columnLower(); |
---|
| 168 | double * columnUpper = model2.columnUpper(); |
---|
| 169 | double * objective = model2.objective(); |
---|
| 170 | double * rowLower = model2.rowLower(); |
---|
| 171 | double * rowUpper = model2.rowUpper(); |
---|
| 172 | // Columns - objective was packed |
---|
| 173 | for (k = 0; k < 2; k++) { |
---|
| 174 | int iColumn = objIndex[k]; |
---|
| 175 | objective[iColumn] = objValue[k]; |
---|
| 176 | } |
---|
| 177 | for (k = 0; k < numberColumns; k++) |
---|
| 178 | columnUpper[k] = upper[k]; |
---|
| 179 | // Rows |
---|
| 180 | for (k = 0; k < numberRows; k++) { |
---|
| 181 | rowLower[k] = 1.0; |
---|
| 182 | rowUpper[k] = 1.0; |
---|
| 183 | } |
---|
| 184 | // Now elements |
---|
| 185 | double row2Value[] = {1.0, -5.0, 1.0}; |
---|
| 186 | CoinBigIndex put = 0; |
---|
| 187 | for (k = 0; k < numberColumns; k++) { |
---|
| 188 | starts[k] = put; |
---|
| 189 | lengths[k] = numberRows; |
---|
| 190 | double value = row2Value[k]; |
---|
| 191 | for (int i = 0; i < numberRows; i++) { |
---|
| 192 | rows[put] = i; |
---|
| 193 | elements[put] = value; |
---|
| 194 | put++; |
---|
| 195 | } |
---|
| 196 | } |
---|
| 197 | starts[numberColumns] = put; |
---|
| 198 | // assign to matrix |
---|
| 199 | CoinPackedMatrix * matrix = new CoinPackedMatrix(true, 0.0, 0.0); |
---|
| 200 | matrix->assignMatrix(true, numberRows, numberColumns, numberElements, |
---|
| 201 | elements, rows, starts, lengths); |
---|
| 202 | ClpPackedMatrix * clpMatrix = new ClpPackedMatrix(matrix); |
---|
| 203 | model2.replaceMatrix(clpMatrix, true); |
---|
| 204 | printf("Time for 10000 addRow using hand written code is %g\n", CoinCpuTime() - time1); |
---|
| 205 | // If matrix is really big could switch off creation of row copy |
---|
| 206 | // model2.setSpecialOptions(256); |
---|
| 207 | } |
---|
| 208 | model2.dual(); |
---|
| 209 | model2.writeMps("a.mps"); |
---|
| 210 | // Print column solution |
---|
| 211 | int numberColumns = model.numberColumns(); |
---|
| 212 | |
---|
| 213 | // Alternatively getColSolution() |
---|
| 214 | double * columnPrimal = model.primalColumnSolution(); |
---|
| 215 | // Alternatively getReducedCost() |
---|
| 216 | double * columnDual = model.dualColumnSolution(); |
---|
| 217 | // Alternatively getColLower() |
---|
| 218 | double * columnLower = model.columnLower(); |
---|
| 219 | // Alternatively getColUpper() |
---|
| 220 | double * columnUpper = model.columnUpper(); |
---|
| 221 | // Alternatively getObjCoefficients() |
---|
| 222 | double * columnObjective = model.objective(); |
---|
| 223 | |
---|
| 224 | int iColumn; |
---|
| 225 | |
---|
| 226 | std::cout << " Primal Dual Lower Upper Cost" |
---|
| 227 | << std::endl; |
---|
| 228 | |
---|
| 229 | for (iColumn = 0; iColumn < numberColumns; iColumn++) { |
---|
| 230 | double value; |
---|
| 231 | std::cout << std::setw(6) << iColumn << " "; |
---|
| 232 | value = columnPrimal[iColumn]; |
---|
| 233 | if (fabs(value) < 1.0e5) |
---|
| 234 | std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; |
---|
| 235 | else |
---|
| 236 | std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value; |
---|
| 237 | value = columnDual[iColumn]; |
---|
| 238 | if (fabs(value) < 1.0e5) |
---|
| 239 | std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; |
---|
| 240 | else |
---|
| 241 | std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value; |
---|
| 242 | value = columnLower[iColumn]; |
---|
| 243 | if (fabs(value) < 1.0e5) |
---|
| 244 | std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; |
---|
| 245 | else |
---|
| 246 | std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value; |
---|
| 247 | value = columnUpper[iColumn]; |
---|
| 248 | if (fabs(value) < 1.0e5) |
---|
| 249 | std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; |
---|
| 250 | else |
---|
| 251 | std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value; |
---|
| 252 | value = columnObjective[iColumn]; |
---|
| 253 | if (fabs(value) < 1.0e5) |
---|
| 254 | std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; |
---|
| 255 | else |
---|
| 256 | std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value; |
---|
| 257 | |
---|
| 258 | std::cout << std::endl; |
---|
| 259 | } |
---|
| 260 | std::cout << "--------------------------------------" << std::endl; |
---|
| 261 | // Test CoinAssert |
---|
[1935] | 262 | std::cout << "If Clp compiled without NDEBUG below should give assert, if with NDEBUG or COIN_ASSERT CoinError" << std::endl; |
---|
[1552] | 263 | model = modelSave; |
---|
| 264 | model.deleteRows(2, del); |
---|
| 265 | // Deliberate error |
---|
| 266 | model.deleteColumns(1, del + 2); |
---|
| 267 | // Now use build +-1 |
---|
| 268 | CoinBuild buildObject3; |
---|
| 269 | time1 = CoinCpuTime(); |
---|
[1559] | 270 | for (k = 0; k < 10000; k++) { |
---|
[1552] | 271 | int row2Index[] = {0, 1, 2}; |
---|
| 272 | double row2Value[] = {1.0, -1.0, 1.0}; |
---|
| 273 | buildObject3.addRow(3, row2Index, row2Value, |
---|
| 274 | 1.0, 1.0); |
---|
| 275 | } |
---|
| 276 | model.addRows(buildObject3, true); |
---|
| 277 | } catch (CoinError e) { |
---|
| 278 | e.print(); |
---|
| 279 | if (e.lineNumber() >= 0) |
---|
| 280 | std::cout << "This was from a CoinAssert" << std::endl; |
---|
| 281 | } |
---|
[2278] | 282 | #else |
---|
| 283 | printf("addRows not available with COIN_BIG_INDEX=2\n"); |
---|
| 284 | #endif |
---|
[1552] | 285 | return 0; |
---|
| 286 | } |
---|