aboutsummaryrefslogtreecommitdiffstats
path: root/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc
diff options
context:
space:
mode:
Diffstat (limited to 'Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc')
-rw-r--r--Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/.classpath15
-rw-r--r--Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/.gitignore2
-rw-r--r--Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/.project28
-rw-r--r--Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/META-INF/MANIFEST.MF10
-rw-r--r--Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/build.properties4
-rw-r--r--Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/cpp/CMakeLists.txt23
-rw-r--r--Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/cpp/viatracbc.cpp277
-rw-r--r--Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/cpp/viatracbc.hpp16
-rwxr-xr-xSolvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/lib/libviatracbc.sobin0 -> 33944 bytes
-rw-r--r--Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/src/hu/bme/mit/inf/dslreasoner/ilp/cbc/CbcException.java30
-rw-r--r--Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/src/hu/bme/mit/inf/dslreasoner/ilp/cbc/CbcResult.java54
-rw-r--r--Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/src/hu/bme/mit/inf/dslreasoner/ilp/cbc/CbcSolver.java71
12 files changed, 530 insertions, 0 deletions
diff --git a/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/.classpath b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/.classpath
new file mode 100644
index 00000000..e19039ae
--- /dev/null
+++ b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/.classpath
@@ -0,0 +1,15 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<classpath>
3 <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
4 <attributes>
5 <attribute name="module" value="true"/>
6 </attributes>
7 </classpathentry>
8 <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
9 <classpathentry kind="src" path="src">
10 <attributes>
11 <attribute name="org.eclipse.jdt.launching.CLASSPATH_ATTR_LIBRARY_PATH_ENTRY" value="hu.bme.mit.inf.dslreasoner.ilp.cbc/lib"/>
12 </attributes>
13 </classpathentry>
14 <classpathentry kind="output" path="bin"/>
15</classpath>
diff --git a/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/.gitignore b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/.gitignore
new file mode 100644
index 00000000..0cc6a59e
--- /dev/null
+++ b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/.gitignore
@@ -0,0 +1,2 @@
1/bin/
2/cpp/build/
diff --git a/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/.project b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/.project
new file mode 100644
index 00000000..6c32e464
--- /dev/null
+++ b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/.project
@@ -0,0 +1,28 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<projectDescription>
3 <name>hu.bme.mit.inf.dslreasoner.ilp.cbc</name>
4 <comment></comment>
5 <projects>
6 </projects>
7 <buildSpec>
8 <buildCommand>
9 <name>org.eclipse.jdt.core.javabuilder</name>
10 <arguments>
11 </arguments>
12 </buildCommand>
13 <buildCommand>
14 <name>org.eclipse.pde.ManifestBuilder</name>
15 <arguments>
16 </arguments>
17 </buildCommand>
18 <buildCommand>
19 <name>org.eclipse.pde.SchemaBuilder</name>
20 <arguments>
21 </arguments>
22 </buildCommand>
23 </buildSpec>
24 <natures>
25 <nature>org.eclipse.pde.PluginNature</nature>
26 <nature>org.eclipse.jdt.core.javanature</nature>
27 </natures>
28</projectDescription>
diff --git a/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/META-INF/MANIFEST.MF b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..04478746
--- /dev/null
+++ b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/META-INF/MANIFEST.MF
@@ -0,0 +1,10 @@
1Manifest-Version: 1.0
2Bundle-ManifestVersion: 2
3Bundle-Name: Cbc
4Bundle-SymbolicName: hu.bme.mit.inf.dslreasoner.ilp.cbc
5Bundle-Version: 1.0.0.qualifier
6Automatic-Module-Name: hu.bme.mit.inf.dslreasoner.ilp.cbc
7Export-Package: hu.bme.mit.inf.dslreasoner.ilp.cbc
8Bundle-NativeCode: libviatracbc.so;
9 osname=Linux;
10 processor=x86_64
diff --git a/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/build.properties b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/build.properties
new file mode 100644
index 00000000..34d2e4d2
--- /dev/null
+++ b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/build.properties
@@ -0,0 +1,4 @@
1source.. = src/
2output.. = bin/
3bin.includes = META-INF/,\
4 .
diff --git a/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/cpp/CMakeLists.txt b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/cpp/CMakeLists.txt
new file mode 100644
index 00000000..6169ae8f
--- /dev/null
+++ b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/cpp/CMakeLists.txt
@@ -0,0 +1,23 @@
1cmake_minimum_required(VERSION 3.10.2)
2project(hu.bme.mit.inf.dslreasoner.ilp.cbc)
3
4set(CMAKE_CXX_STANDARD 14)
5
6find_package(JNI REQUIRED)
7find_package(PkgConfig REQUIRED)
8
9pkg_check_modules(CBC REQUIRED cbc)
10
11add_library(viatracbc SHARED viatracbc.cpp)
12
13target_link_libraries(viatracbc
14 ${JAVA_JVM_LIBRARY}
15 ${CBC_LIBRARIES})
16target_include_directories(viatracbc
17 PUBLIC ${JNI_INCLUDE_DIRS}
18 PRIVATE ${CBC_INCLUDE_DIRS})
19
20set(VIATRACBC_NATIVES_DIR ${CMAKE_SOURCE_DIR}/../lib)
21add_custom_command(TARGET viatracbc POST_BUILD
22 COMMAND ${CMAKE_COMMAND} -E make_directory ${VIATRACBC_NATIVES_DIR}
23 COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:viatracbc> ${VIATRACBC_NATIVES_DIR})
diff --git a/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/cpp/viatracbc.cpp b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/cpp/viatracbc.cpp
new file mode 100644
index 00000000..34cab1dd
--- /dev/null
+++ b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/cpp/viatracbc.cpp
@@ -0,0 +1,277 @@
1
2#include <cmath>
3#include <cstdlib>
4#include <iostream>
5#include <stdexcept>
6
7#include <jni.h>
8
9#include "CbcBranchDefaultDecision.hpp"
10#include "CbcCompareDefault.hpp"
11#include "CbcHeuristic.hpp"
12#include "CbcHeuristicLocal.hpp"
13#include "CbcModel.hpp"
14#include "CglClique.hpp"
15#include "CglFlowCover.hpp"
16#include "CglGomory.hpp"
17#include "CglKnapsackCover.hpp"
18#include "CglMixedIntegerRounding.hpp"
19#include "CglOddHole.hpp"
20#include "CglProbing.hpp"
21#include "CoinModel.hpp"
22#include "OsiClpSolverInterface.hpp"
23
24#include "viatracbc.hpp"
25
26static const char *const kCbcExceptionClassName = "hu/bme/mit/inf/dslreasoner/ilp/cbc/CbcException";
27static const char *const kRuntimeExceptionClassName = "java/lang/RuntimeException";
28
29static const jint kCbcSolutionBounded = 0;
30static const jint kCbcSolutionUnbounded = 1;
31static const jint kCbcUnsat = 2;
32static const jint kCbcAbandoned = 3;
33static const jint kCbcTimeout = 4;
34static const jint kCbcError = 5;
35
36static CoinModel CreateModel(JNIEnv *env, jdoubleArray columnLowerBoundsArray,
37 jdoubleArray columnUpperBoundsArray, jintArray rowStartsArray, jintArray columnIndicesArray,
38 jdoubleArray entriedArray, jdoubleArray rowLowerBoundsArray, jdoubleArray rowUpperBoundsArray,
39 jdoubleArray objectiveArray, jboolean lpRelaxation);
40static void CreateModelColumns(JNIEnv *env, jdoubleArray columnLowerBoundsArray,
41 jdoubleArray columnUpperBoundsArray, jdoubleArray objectiveArray, jboolean lpRelaxation,
42 CoinModel &build);
43static void CreateModelRows(JNIEnv *env, jintArray rowStartsArray, jintArray columnIndicesArray,
44 jdoubleArray entriesArray, jdoubleArray rowLowerBoundsArray, jdoubleArray rowUpperBoundsArray,
45 CoinModel &build);
46static jint SolveModel(CoinModel &build, jdouble timeoutSeconds, jboolean silent, jdouble &value);
47static void ThrowException(JNIEnv *env, const char *message);
48
49template <
50 typename Array,
51 typename Element,
52 Element *(JNIEnv::*GetElementsPtr)(Array, jboolean *),
53 void (JNIEnv::*ReleaseElementsPtr)(Array, Element *, jint)
54>
55class PinnedArray {
56public:
57 PinnedArray(JNIEnv *env, Array array)
58 : env_{env}, array_{array}, elements_{(env->*GetElementsPtr)(array, nullptr)} {
59 if (elements_ == nullptr) {
60 throw std::runtime_error("Failed to pin array elements");
61 }
62 }
63 PinnedArray(const PinnedArray &) = delete;
64 PinnedArray(PinnedArray &&) = delete;
65 PinnedArray &operator=(const PinnedArray &) = delete;
66 PinnedArray &operator=(PinnedArray &&) = delete;
67 ~PinnedArray() {
68 (env_->*ReleaseElementsPtr)(array_, elements_, 0);
69 }
70
71 operator Element *() { return elements_; }
72 operator const Element *() const { return elements_; }
73
74private:
75 JNIEnv *env_;
76 Array array_;
77 Element *elements_;
78};
79
80using PinnedIntArray = PinnedArray<jintArray, jint, &JNIEnv::GetIntArrayElements, &JNIEnv::ReleaseIntArrayElements>;
81using PinnedDoubleArray = PinnedArray<jdoubleArray, jdouble, &JNIEnv::GetDoubleArrayElements, &JNIEnv::ReleaseDoubleArrayElements>;
82
83jint Java_hu_bme_mit_inf_dslreasoner_ilp_cbc_CbcSolver_solveIlpProblem(
84 JNIEnv *env, jclass klazz, jdoubleArray columnLowerBoundsArray, jdoubleArray columnUpperBoundsArray,
85 jintArray rowStartsArray, jintArray columnIndicesArray, jdoubleArray entriesArray,
86 jdoubleArray rowLowerBoundsArray, jdoubleArray rowUpperBoundsArray, jdoubleArray objectiveArray,
87 jdoubleArray outputArray, jboolean lpRelaxation, jdouble timeoutSeconds, jboolean silent) {
88 try {
89 auto build = CreateModel(env, columnLowerBoundsArray, columnUpperBoundsArray,
90 rowStartsArray, columnIndicesArray, entriesArray, rowLowerBoundsArray, rowUpperBoundsArray,
91 objectiveArray, lpRelaxation);
92 double value;
93 jint result = SolveModel(build, timeoutSeconds, silent, value);
94 if (result == kCbcSolutionBounded) {
95 PinnedDoubleArray output{env, outputArray};
96 *output = value;
97 }
98 return result;
99 } catch (const std::exception &e) {
100 ThrowException(env, e.what());
101 } catch (...) {
102 ThrowException(env, "Unknown solver error");
103 }
104 return kCbcError;
105}
106
107CoinModel CreateModel(JNIEnv *env, jdoubleArray columnLowerBoundsArray,
108 jdoubleArray columnUpperBoundsArray, jintArray rowStartsArray, jintArray columnIndicesArray,
109 jdoubleArray entriesArray, jdoubleArray rowLowerBoundsArray, jdoubleArray rowUpperBoundsArray,
110 jdoubleArray objectiveArray, jboolean lpRelaxation) {
111 CoinModel build;
112 CreateModelColumns(env, columnLowerBoundsArray, columnUpperBoundsArray, objectiveArray,
113 lpRelaxation, build);
114 CreateModelRows(env, rowStartsArray, columnIndicesArray, entriesArray, rowLowerBoundsArray,
115 rowUpperBoundsArray, build);
116 return build;
117}
118
119void CreateModelColumns(JNIEnv *env, jdoubleArray columnLowerBoundsArray,
120 jdoubleArray columnUpperBoundsArray, jdoubleArray objectiveArray, jboolean lpRelaxation,
121 CoinModel &build) {
122 int numColumns = env->GetArrayLength(columnLowerBoundsArray);
123 PinnedDoubleArray columnLowerBounds{env, columnLowerBoundsArray};
124 PinnedDoubleArray columnUpperBounds{env, columnUpperBoundsArray};
125 PinnedDoubleArray objective{env, objectiveArray};
126 for (int i = 0; i < numColumns; i++) {
127 build.setColumnBounds(i, columnLowerBounds[i], columnUpperBounds[i]);
128 build.setObjective(i, objective[i]);
129 if (!lpRelaxation) {
130 build.setInteger(i);
131 }
132 }
133}
134
135void CreateModelRows(JNIEnv *env, jintArray rowStartsArray, jintArray columnIndicesArray,
136 jdoubleArray entriesArray, jdoubleArray rowLowerBoundsArray, jdoubleArray rowUpperBoundsArray,
137 CoinModel &build) {
138 int numRows = env->GetArrayLength(rowLowerBoundsArray);
139 PinnedIntArray rowStarts{env, rowStartsArray};
140 PinnedIntArray columnIndices{env, columnIndicesArray};
141 PinnedDoubleArray entries{env, entriesArray};
142 PinnedDoubleArray rowLowerBounds{env, rowLowerBoundsArray};
143 PinnedDoubleArray rowUpperBounds{env, rowUpperBoundsArray};
144 for (int i = 0; i < numRows; i++) {
145 int rowStart = rowStarts[i];
146 int numbersInRow = rowStarts[i + 1] - rowStart;
147 build.addRow(numbersInRow, &columnIndices[rowStart], &entries[rowStart],
148 rowLowerBounds[i], rowUpperBounds[i]);
149 }
150}
151
152jint SolveModel(CoinModel &build, jdouble timeoutSeconds, jboolean silent, jdouble &value) {
153 OsiClpSolverInterface solver;
154 solver.loadFromCoinModel(build);
155 CbcModel model{solver};
156
157 if (timeoutSeconds >= 0) {
158 model.setDblParam(CbcModel::CbcMaximumSeconds, timeoutSeconds);
159 }
160 if (silent == JNI_FALSE) {
161 model.messageHandler()->setLogLevel(2);
162 model.solver()->messageHandler()->setLogLevel(1);
163 } else {
164 model.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry);
165 model.messageHandler()->setLogLevel(0);
166 model.solver()->messageHandler()->setLogLevel(0);
167 }
168
169 // Cut generators and heuristics are used according to
170 // https://github.com/coin-or/Cbc/blob/6b977b6707f1755520c64fea57b95891c1f3ddc0/Cbc/examples/sample2.cpp
171
172 CglProbing probing;
173 probing.setUsingObjective(true);
174 probing.setMaxPass(1);
175 probing.setMaxPassRoot(5);
176 probing.setMaxProbe(10);
177 probing.setMaxProbeRoot(1000);
178 probing.setMaxLook(50);
179 probing.setMaxLookRoot(500);
180 probing.setMaxElements(200);
181 probing.setRowCuts(3);
182 model.addCutGenerator(&probing, -1, "Probing");
183
184 CglGomory gomory;
185 gomory.setLimit(300);
186 model.addCutGenerator(&gomory, -1, "Gomory");
187
188 CglKnapsackCover knapsackCover;
189 model.addCutGenerator(&knapsackCover, -1, "KnapsackCover");
190
191 CglClique clique;
192 clique.setStarCliqueReport(false);
193 clique.setRowCliqueReport(false);
194 model.addCutGenerator(&clique, -1, "Clique");
195
196 CglFlowCover flowCover;
197 model.addCutGenerator(&flowCover, -1, "FlowCover");
198
199 CglMixedIntegerRounding mixedIntegerRounding;
200 model.addCutGenerator(&mixedIntegerRounding, -1, "MixedIntegerRounding");
201
202 OsiClpSolverInterface *osiClp = dynamic_cast<OsiClpSolverInterface *>(model.solver());
203 if (osiClp != nullptr) {
204 osiClp->setSpecialOptions(128);
205 osiClp->setupForRepeatedUse(0, 0);
206 }
207
208 CbcRounding rounding;
209 model.addHeuristic(&rounding);
210
211 CbcHeuristicLocal localHeuristic;
212 model.addHeuristic(&localHeuristic);
213
214 CbcBranchDefaultDecision branchDecision;
215 model.setBranchingMethod(&branchDecision);
216
217 CbcCompareDefault nodeComparison;
218 model.setNodeComparison(nodeComparison);
219
220 model.initialSolve();
221
222 if (model.isInitialSolveProvenPrimalInfeasible()) {
223 return kCbcUnsat;
224 }
225 if (model.isInitialSolveProvenDualInfeasible()) {
226 return kCbcSolutionUnbounded;
227 }
228 if (model.isInitialSolveAbandoned()) {
229 return kCbcTimeout;
230 }
231
232 model.setMinimumDrop(CoinMin(1.0, fabs(model.getMinimizationObjValue()) * 1.0e-3 + 1.0e-4));
233 model.setMaximumCutPassesAtRoot(-100);
234 model.setNumberStrong(10);
235 model.solver()->setIntParam(OsiMaxNumIterationHotStart, 100);
236
237 model.branchAndBound();
238
239 switch (model.status()) {
240 case 0:
241 if (model.isProvenInfeasible()) {
242 return kCbcUnsat;
243 }
244 if (model.isProvenDualInfeasible()) {
245 return kCbcSolutionUnbounded;
246 }
247 if (model.isProvenOptimal()) {
248 value = model.getMinimizationObjValue();
249 return kCbcSolutionBounded;
250 }
251 throw std::runtime_error("CBC status is 0, but no solution is found");
252 case 1:
253 return kCbcTimeout;
254 case 2:
255 return kCbcAbandoned;
256 default:
257 throw std::runtime_error("Unknown CBC status");
258 }
259}
260
261void ThrowException(JNIEnv *env, const char *message) {
262 jclass exceptionClass = env->FindClass(kCbcExceptionClassName);
263 if (exceptionClass == nullptr) {
264 std::cerr << "WARNING: " << kCbcExceptionClassName << " class was not found" << std::endl;
265 exceptionClass = env->FindClass(kRuntimeExceptionClassName);
266 if (exceptionClass == nullptr) {
267 std::cerr << "FATAL: " << kRuntimeExceptionClassName << " class was not found" << std::endl;
268 std::cerr << "FATAL: " << message << std::endl;
269 std::exit(EXIT_FAILURE);
270 }
271 }
272 if (env->ThrowNew(exceptionClass, message) < 0) {
273 std::cerr << "FATAL: Could not throw java exception" << std::endl;
274 std::cerr << "FATAL: " << message << std::endl;
275 std::exit(EXIT_FAILURE);
276 }
277}
diff --git a/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/cpp/viatracbc.hpp b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/cpp/viatracbc.hpp
new file mode 100644
index 00000000..12198c8b
--- /dev/null
+++ b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/cpp/viatracbc.hpp
@@ -0,0 +1,16 @@
1#ifndef HU_BME_MIT_INF_DSLREASONER_ILP_CBC_
2#define HU_BME_MIT_INF_DSLREASONER_ILP_CBC_
3
4#include <jni.h>
5
6extern "C" {
7
8JNIEXPORT jint JNICALL Java_hu_bme_mit_inf_dslreasoner_ilp_cbc_CbcSolver_solveIlpProblem(
9 JNIEnv *env, jclass klazz, jdoubleArray columnLowerBoundsArray, jdoubleArray columnUpperBoundsArray,
10 jintArray rowStartsArray, jintArray columnIndicesArray, jdoubleArray entriesArray,
11 jdoubleArray rowLowerBoundsArray, jdoubleArray rowUpperBoundsArray, jdoubleArray objectiveArray,
12 jdoubleArray outputArray, jboolean lpRelaxation, jdouble timeoutSeconds, jboolean silent);
13
14}
15
16#endif // HU_BME_MIT_INF_DSLREASONER_ILP_CBC_
diff --git a/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/lib/libviatracbc.so b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/lib/libviatracbc.so
new file mode 100755
index 00000000..96289216
--- /dev/null
+++ b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/lib/libviatracbc.so
Binary files differ
diff --git a/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/src/hu/bme/mit/inf/dslreasoner/ilp/cbc/CbcException.java b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/src/hu/bme/mit/inf/dslreasoner/ilp/cbc/CbcException.java
new file mode 100644
index 00000000..26846958
--- /dev/null
+++ b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/src/hu/bme/mit/inf/dslreasoner/ilp/cbc/CbcException.java
@@ -0,0 +1,30 @@
1package hu.bme.mit.inf.dslreasoner.ilp.cbc;
2
3public class CbcException extends RuntimeException {
4
5 /**
6 *
7 */
8 private static final long serialVersionUID = 2691773509078511887L;
9
10 public CbcException() {
11 super();
12 }
13
14 public CbcException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
15 super(message, cause, enableSuppression, writableStackTrace);
16 }
17
18 public CbcException(String message, Throwable cause) {
19 super(message, cause);
20 }
21
22 public CbcException(String message) {
23 super(message);
24 }
25
26 public CbcException(Throwable cause) {
27 super(cause);
28 }
29
30}
diff --git a/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/src/hu/bme/mit/inf/dslreasoner/ilp/cbc/CbcResult.java b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/src/hu/bme/mit/inf/dslreasoner/ilp/cbc/CbcResult.java
new file mode 100644
index 00000000..dae3a447
--- /dev/null
+++ b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/src/hu/bme/mit/inf/dslreasoner/ilp/cbc/CbcResult.java
@@ -0,0 +1,54 @@
1package hu.bme.mit.inf.dslreasoner.ilp.cbc;
2
3public abstract class CbcResult {
4 public static final CbcResult SOLUTION_UNBOUNDED = new CbcResult() {
5 };
6
7 public static final CbcResult UNSAT = new CbcResult() {
8 };
9
10 public static final CbcResult ABANDONED = new CbcResult() {
11 };
12
13 public static final CbcResult TIMEOUT = new CbcResult() {
14 };
15
16 private CbcResult() {
17 }
18
19 public static class SolutionBounded extends CbcResult {
20 public final double value;
21
22 public SolutionBounded(double value) {
23 this.value = value;
24 }
25
26 public double getValue() {
27 return value;
28 }
29
30 @Override
31 public int hashCode() {
32 final int prime = 31;
33 int result = 1;
34 long temp;
35 temp = Double.doubleToLongBits(value);
36 result = prime * result + (int) (temp ^ (temp >>> 32));
37 return result;
38 }
39
40 @Override
41 public boolean equals(Object obj) {
42 if (this == obj)
43 return true;
44 if (obj == null)
45 return false;
46 if (getClass() != obj.getClass())
47 return false;
48 SolutionBounded other = (SolutionBounded) obj;
49 if (Double.doubleToLongBits(value) != Double.doubleToLongBits(other.value))
50 return false;
51 return true;
52 }
53 }
54}
diff --git a/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/src/hu/bme/mit/inf/dslreasoner/ilp/cbc/CbcSolver.java b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/src/hu/bme/mit/inf/dslreasoner/ilp/cbc/CbcSolver.java
new file mode 100644
index 00000000..085d4448
--- /dev/null
+++ b/Solvers/ILP-Solver/hu.bme.mit.inf.dslreasoner.ilp.cbc/src/hu/bme/mit/inf/dslreasoner/ilp/cbc/CbcSolver.java
@@ -0,0 +1,71 @@
1package hu.bme.mit.inf.dslreasoner.ilp.cbc;
2
3public class CbcSolver {
4 private static int CBC_SOLUTION_BOUNDED = 0;
5 private static int CBC_SOLUTION_UNBOUNDED = 1;
6 private static int CBC_UNSAT = 2;
7 private static int CBC_ABANDONED = 3;
8 private static int CBC_TIMEOUT = 4;
9 private static int CBC_ERROR = 5;
10
11 private static boolean nativesLoaded = false;
12
13 private CbcSolver() {
14 throw new IllegalStateException("This is a static utility class and should not be instantiated directly.");
15 }
16
17 public static CbcResult solve(double[] columnLowerBounds, double[] columnUpperBounds, int[] rowStarts,
18 int[] columnIndices, double[] entries, double[] rowLowerBounds, double[] rowUpperBounds, double[] objective,
19 boolean lpRelaxation, double timeoutSeconds, boolean silent) {
20 loadNatives();
21 validate(columnLowerBounds, columnUpperBounds, rowStarts, columnIndices, entries, rowLowerBounds,
22 rowUpperBounds, objective);
23 double[] output = new double[1];
24 int result = solveIlpProblem(columnLowerBounds, columnUpperBounds, rowStarts, columnIndices, entries,
25 rowLowerBounds, rowUpperBounds, objective, output, lpRelaxation, timeoutSeconds, silent);
26 if (result == CBC_SOLUTION_BOUNDED) {
27 return new CbcResult.SolutionBounded(output[0]);
28 } else if (result == CBC_SOLUTION_UNBOUNDED) {
29 return CbcResult.SOLUTION_UNBOUNDED;
30 } else if (result == CBC_UNSAT) {
31 return CbcResult.UNSAT;
32 } else if (result == CBC_ABANDONED) {
33 return CbcResult.ABANDONED;
34 } else if (result == CBC_TIMEOUT) {
35 return CbcResult.TIMEOUT;
36 } else if (result == CBC_ERROR) {
37 throw new CbcException("Solver signalled error, but no exception was thrown");
38 } else {
39 throw new CbcException("Unknown return value: " + result);
40 }
41 }
42
43 private static void loadNatives() {
44 if (!nativesLoaded) {
45 synchronized (CbcSolver.class) {
46 System.loadLibrary("viatracbc");
47 nativesLoaded = true;
48 }
49 }
50 }
51
52 private static void validate(double[] columnLowerBounds, double[] columnUpperBounds, int[] rowStarts,
53 int[] columnIndices, double[] entries, double[] rowLowerBounds, double[] rowUpperBounds,
54 double[] objective) {
55 int numColumns = columnLowerBounds.length;
56 if (columnUpperBounds.length != numColumns) {
57 throw new CbcException("Lengths of columnLowerBounds and columnUpperBounds must match");
58 }
59 if (objective.length != numColumns) {
60 throw new CbcException("Lengths of columnLowerBounds and objective must match");
61 }
62 int numRows = rowLowerBounds.length;
63 if (rowUpperBounds.length != numRows) {
64 throw new CbcException("Lengths of rowLowerBounds and rowUpperBounds must match");
65 }
66 }
67
68 private static native int solveIlpProblem(double[] columnLowerBounds, double[] columnUpperBounds, int[] rowStarts,
69 int[] columnIndices, double[] entries, double[] rowLowerBounds, double[] rowUpperBounds, double[] objective,
70 double[] output, boolean lpRelaxation, double timeoutSeconds, boolean silent);
71}