-
Notifications
You must be signed in to change notification settings - Fork 85
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
316 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
|
||
add_executable(ClpTest "ClpTest.cpp") | ||
target_include_directories(Clp PUBLIC | ||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src> | ||
$<INSTALL_INTERFACE:include/coin>) | ||
target_compile_definitions(ClpTest | ||
PUBLIC HAVE_CONFIG_H | ||
PRIVATE CLP_BUILD COIN_HAS_CLP) | ||
if(CMAKE_VERSION VERSION_LESS "3.8.2") | ||
set_property(TARGET ClpTest PROPERTY CXX_STANDARD 11) | ||
set_property(TARGET ClpTest PROPERTY CXX_STANDARD_REQUIRED ON) | ||
else() | ||
target_compile_features(ClpTest PUBLIC cxx_std_11) | ||
endif() | ||
target_link_libraries(ClpTest PRIVATE | ||
Coin::CoinUtils | ||
Coin::Osi | ||
Coin::Clp) | ||
set_target_properties(ClpTest PROPERTIES | ||
VERSION ${PROJECT_VERSION} | ||
SOVERSION ${PROJECT_VERSION_MAJOR}) | ||
add_executable(Coin::ClpTest ALIAS ClpTest) | ||
|
||
add_test(NAME ClpTest COMMAND ClpTest) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,288 @@ | ||
// This is a simple example to create a model by row | ||
#include "ClpSimplex.hpp" | ||
#include "CoinBuild.hpp" | ||
#include "CoinHelperFunctions.hpp" | ||
#include "CoinModel.hpp" | ||
#include "CoinTime.hpp" | ||
#include <ClpConfig.h> | ||
#include <ClpConfig.h> | ||
#include <CoinUtilsConfig.h> | ||
#include <OsiConfig.h> | ||
#include <iostream> | ||
#include <iomanip> | ||
#include <cassert> | ||
|
||
int main(int argc, const char *argv[]) { | ||
std::cout << "coinutils version: " << COINUTILS_VERSION << std::endl; | ||
std::cout << "osi version: " << OSI_VERSION << std::endl; | ||
std::cout << "clp version: " << CLP_VERSION << std::endl; | ||
#if COIN_BIG_INDEX<2 | ||
try { | ||
// Empty model | ||
ClpSimplex model; | ||
|
||
// Objective - just nonzeros | ||
int objIndex[] = {0, 2}; | ||
double objValue[] = {1.0, 4.0}; | ||
// Upper bounds - as dense vector | ||
double upper[] = {2.0, COIN_DBL_MAX, 4.0}; | ||
|
||
// Create space for 3 columns | ||
model.resize(0, 3); | ||
// Fill in | ||
int i; | ||
// Virtuous way | ||
// First objective | ||
for (i = 0; i < 2; i++) | ||
model.setObjectiveCoefficient(objIndex[i], objValue[i]); | ||
// Now bounds (lower will be zero by default but do again) | ||
for (i = 0; i < 3; i++) { | ||
model.setColumnLower(i, 0.0); | ||
model.setColumnUpper(i, upper[i]); | ||
} | ||
/* | ||
We could also have done in non-virtuous way e.g. | ||
double * objective = model.objective(); | ||
and then set directly | ||
*/ | ||
// Faster to add rows all at once - but this is easier to show | ||
// Now add row 1 as >= 2.0 | ||
int row1Index[] = {0, 2}; | ||
double row1Value[] = {1.0, 1.0}; | ||
model.addRow(2, row1Index, row1Value, | ||
2.0, COIN_DBL_MAX); | ||
// Now add row 2 as == 1.0 | ||
int row2Index[] = {0, 1, 2}; | ||
double row2Value[] = {1.0, -5.0, 1.0}; | ||
model.addRow(3, row2Index, row2Value, | ||
1.0, 1.0); | ||
// solve | ||
model.dual(); | ||
|
||
/* | ||
Adding one row at a time has a significant overhead so let's | ||
try a more complicated but faster way | ||
First time adding in 10000 rows one by one | ||
*/ | ||
model.allSlackBasis(); | ||
ClpSimplex modelSave = model; | ||
double time1 = CoinCpuTime(); | ||
int k; | ||
for (k = 0; k < 10000; k++) { | ||
int row2Index[] = {0, 1, 2}; | ||
double row2Value[] = {1.0, -5.0, 1.0}; | ||
model.addRow(3, row2Index, row2Value, | ||
1.0, 1.0); | ||
} | ||
printf("Time for 10000 addRow is %g\n", CoinCpuTime() - time1); | ||
model.dual(); | ||
model = modelSave; | ||
// Now use build | ||
CoinBuild buildObject; | ||
time1 = CoinCpuTime(); | ||
for (k = 0; k < 10000; k++) { | ||
int row2Index[] = {0, 1, 2}; | ||
double row2Value[] = {1.0, -5.0, 1.0}; | ||
buildObject.addRow(3, row2Index, row2Value, | ||
1.0, 1.0); | ||
} | ||
model.addRows(buildObject); | ||
printf("Time for 10000 addRow using CoinBuild is %g\n", CoinCpuTime() - time1); | ||
model.dual(); | ||
model = modelSave; | ||
int del[] = {0, 1, 2}; | ||
model.deleteRows(2, del); | ||
// Now use build +-1 | ||
CoinBuild buildObject2; | ||
time1 = CoinCpuTime(); | ||
for (k = 0; k < 10000; k++) { | ||
int row2Index[] = {0, 1, 2}; | ||
double row2Value[] = {1.0, -1.0, 1.0}; | ||
buildObject2.addRow(3, row2Index, row2Value, | ||
1.0, 1.0); | ||
} | ||
model.addRows(buildObject2, true); | ||
printf("Time for 10000 addRow using CoinBuild+-1 is %g\n", CoinCpuTime() - time1); | ||
model.dual(); | ||
model = modelSave; | ||
model.deleteRows(2, del); | ||
// Now use build +-1 | ||
CoinModel modelObject2; | ||
time1 = CoinCpuTime(); | ||
for (k = 0; k < 10000; k++) { | ||
int row2Index[] = {0, 1, 2}; | ||
double row2Value[] = {1.0, -1.0, 1.0}; | ||
modelObject2.addRow(3, row2Index, row2Value, | ||
1.0, 1.0); | ||
} | ||
model.addRows(modelObject2, true); | ||
printf("Time for 10000 addRow using CoinModel+-1 is %g\n", CoinCpuTime() - time1); | ||
model.dual(); | ||
model = ClpSimplex(); | ||
// Now use build +-1 | ||
CoinModel modelObject3; | ||
time1 = CoinCpuTime(); | ||
for (k = 0; k < 10000; k++) { | ||
int row2Index[] = {0, 1, 2}; | ||
double row2Value[] = {1.0, -1.0, 1.0}; | ||
modelObject3.addRow(3, row2Index, row2Value, | ||
1.0, 1.0); | ||
} | ||
model.loadProblem(modelObject3, true); | ||
printf("Time for 10000 addRow using CoinModel load +-1 is %g\n", CoinCpuTime() - time1); | ||
model.writeMps("xx.mps"); | ||
model.dual(); | ||
model = modelSave; | ||
// Now use model | ||
CoinModel modelObject; | ||
time1 = CoinCpuTime(); | ||
for (k = 0; k < 10000; k++) { | ||
int row2Index[] = {0, 1, 2}; | ||
double row2Value[] = {1.0, -5.0, 1.0}; | ||
modelObject.addRow(3, row2Index, row2Value, | ||
1.0, 1.0); | ||
} | ||
model.addRows(modelObject); | ||
printf("Time for 10000 addRow using CoinModel is %g\n", CoinCpuTime() - time1); | ||
model.dual(); | ||
model.writeMps("b.mps"); | ||
// Method using least memory - but most complicated | ||
time1 = CoinCpuTime(); | ||
// Assumes we know exact size of model and matrix | ||
// Empty model | ||
ClpSimplex model2; | ||
{ | ||
// Create space for 3 columns and 10000 rows | ||
int numberRows = 10000; | ||
int numberColumns = 3; | ||
// This is fully dense - but would not normally be so | ||
int numberElements = numberRows * numberColumns; | ||
// Arrays will be set to default values | ||
model2.resize(numberRows, numberColumns); | ||
double * elements = new double [numberElements]; | ||
CoinBigIndex * starts = new CoinBigIndex [numberColumns+1]; | ||
int * rows = new int [numberElements];; | ||
int * lengths = new int[numberColumns]; | ||
// Now fill in - totally unsafe but .... | ||
// no need as defaults to 0.0 double * columnLower = model2.columnLower(); | ||
double * columnUpper = model2.columnUpper(); | ||
double * objective = model2.objective(); | ||
double * rowLower = model2.rowLower(); | ||
double * rowUpper = model2.rowUpper(); | ||
// Columns - objective was packed | ||
for (k = 0; k < 2; k++) { | ||
int iColumn = objIndex[k]; | ||
objective[iColumn] = objValue[k]; | ||
} | ||
for (k = 0; k < numberColumns; k++) | ||
columnUpper[k] = upper[k]; | ||
// Rows | ||
for (k = 0; k < numberRows; k++) { | ||
rowLower[k] = 1.0; | ||
rowUpper[k] = 1.0; | ||
} | ||
// Now elements | ||
double row2Value[] = {1.0, -5.0, 1.0}; | ||
CoinBigIndex put = 0; | ||
for (k = 0; k < numberColumns; k++) { | ||
starts[k] = put; | ||
lengths[k] = numberRows; | ||
double value = row2Value[k]; | ||
for (int i = 0; i < numberRows; i++) { | ||
rows[put] = i; | ||
elements[put] = value; | ||
put++; | ||
} | ||
} | ||
starts[numberColumns] = put; | ||
// assign to matrix | ||
CoinPackedMatrix * matrix = new CoinPackedMatrix(true, 0.0, 0.0); | ||
matrix->assignMatrix(true, numberRows, numberColumns, numberElements, | ||
elements, rows, starts, lengths); | ||
ClpPackedMatrix * clpMatrix = new ClpPackedMatrix(matrix); | ||
model2.replaceMatrix(clpMatrix, true); | ||
printf("Time for 10000 addRow using hand written code is %g\n", CoinCpuTime() - time1); | ||
// If matrix is really big could switch off creation of row copy | ||
// model2.setSpecialOptions(256); | ||
} | ||
model2.dual(); | ||
model2.writeMps("a.mps"); | ||
// Print column solution | ||
int numberColumns = model.numberColumns(); | ||
|
||
// Alternatively getColSolution() | ||
double * columnPrimal = model.primalColumnSolution(); | ||
// Alternatively getReducedCost() | ||
double * columnDual = model.dualColumnSolution(); | ||
// Alternatively getColLower() | ||
double * columnLower = model.columnLower(); | ||
// Alternatively getColUpper() | ||
double * columnUpper = model.columnUpper(); | ||
// Alternatively getObjCoefficients() | ||
double * columnObjective = model.objective(); | ||
|
||
int iColumn; | ||
|
||
std::cout << " Primal Dual Lower Upper Cost" | ||
<< std::endl; | ||
|
||
for (iColumn = 0; iColumn < numberColumns; iColumn++) { | ||
double value; | ||
std::cout << std::setw(6) << iColumn << " "; | ||
value = columnPrimal[iColumn]; | ||
if (fabs(value) < 1.0e5) | ||
std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; | ||
else | ||
std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; | ||
value = columnDual[iColumn]; | ||
if (fabs(value) < 1.0e5) | ||
std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; | ||
else | ||
std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; | ||
value = columnLower[iColumn]; | ||
if (fabs(value) < 1.0e5) | ||
std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; | ||
else | ||
std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; | ||
value = columnUpper[iColumn]; | ||
if (fabs(value) < 1.0e5) | ||
std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; | ||
else | ||
std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; | ||
value = columnObjective[iColumn]; | ||
if (fabs(value) < 1.0e5) | ||
std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; | ||
else | ||
std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; | ||
|
||
std::cout << std::endl; | ||
} | ||
std::cout << "--------------------------------------" << std::endl; | ||
// Test CoinAssert | ||
std::cout << "If Clp compiled without NDEBUG below should give assert, if with NDEBUG or COIN_ASSERT CoinError" << std::endl; | ||
model = modelSave; | ||
model.deleteRows(2, del); | ||
// Deliberate error | ||
model.deleteColumns(1, del + 2); | ||
// Now use build +-1 | ||
CoinBuild buildObject3; | ||
time1 = CoinCpuTime(); | ||
for (k = 0; k < 10000; k++) { | ||
int row2Index[] = {0, 1, 2}; | ||
double row2Value[] = {1.0, -1.0, 1.0}; | ||
buildObject3.addRow(3, row2Index, row2Value, | ||
1.0, 1.0); | ||
} | ||
model.addRows(buildObject3, true); | ||
} catch (CoinError e) { | ||
e.print(); | ||
if (e.lineNumber() >= 0) | ||
std::cout << "This was from a CoinAssert" << std::endl; | ||
} | ||
#else | ||
printf("addRows not available with COIN_BIG_INDEX=2\n"); | ||
#endif | ||
return 0; | ||
} | ||
|