Skip to content

Commit ee998e9

Browse files
committed
Add Test
1 parent 6436c32 commit ee998e9

File tree

3 files changed

+316
-0
lines changed

3 files changed

+316
-0
lines changed

Clp/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,7 @@ install(TARGETS ClpSolver
230230
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
231231
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
232232
)
233+
234+
if(BUILD_TESTING)
235+
add_subdirectory(test)
236+
endif()

Clp/test/CMakeLists.txt

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
2+
add_executable(ClpTest "ClpTest.cpp")
3+
target_include_directories(Clp PUBLIC
4+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
5+
$<INSTALL_INTERFACE:include/coin>)
6+
target_compile_definitions(ClpTest
7+
PUBLIC HAVE_CONFIG_H
8+
PRIVATE CLP_BUILD COIN_HAS_CLP)
9+
if(CMAKE_VERSION VERSION_LESS "3.8.2")
10+
set_property(TARGET ClpTest PROPERTY CXX_STANDARD 11)
11+
set_property(TARGET ClpTest PROPERTY CXX_STANDARD_REQUIRED ON)
12+
else()
13+
target_compile_features(ClpTest PUBLIC cxx_std_11)
14+
endif()
15+
target_link_libraries(ClpTest PRIVATE
16+
Coin::CoinUtils
17+
Coin::Osi
18+
Coin::Clp)
19+
set_target_properties(ClpTest PROPERTIES
20+
VERSION ${PROJECT_VERSION}
21+
SOVERSION ${PROJECT_VERSION_MAJOR})
22+
add_executable(Coin::ClpTest ALIAS ClpTest)
23+
24+
add_test(NAME ClpTest COMMAND ClpTest)

Clp/test/ClpTest.cpp

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

0 commit comments

Comments
 (0)