├── .gitignore
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── quantego
│ │ └── clp
│ │ ├── CLP.java
│ │ ├── CLPConstraint.java
│ │ ├── CLPExpression.java
│ │ ├── CLPNative.java
│ │ ├── CLPObjective.java
│ │ ├── CLPVariable.java
│ │ ├── CLPVariableSet.java
│ │ └── NativeLoader.java
├── javadoc
│ └── overview.html
└── resources
│ └── clp-1.16.15
│ ├── .DS_Store
│ ├── darwin-aarch64
│ ├── libClp.dylib
│ └── libCoinUtils.3.dylib
│ ├── darwin-x86
│ ├── libClp.dylib
│ └── libCoinUtils.3.dylib
│ ├── linux-aarch64
│ ├── libClp.so
│ └── libCoinUtils.so.3
│ ├── linux-x86
│ ├── libClp.so
│ └── libCoinUtils.so.3
│ └── win64
│ ├── Clp.dll
│ ├── libCoinUtils-3.dll
│ ├── libgcc_s_seh-1.dll
│ └── libstdc++-6.dll
└── test
├── java
└── com
│ └── quantego
│ └── clp
│ └── CLPTest.java
└── resources
└── 10teams.mps
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Nils Löhndorf
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Linear Programming in Java
2 |
3 | Java interface for the [CLP linear solver](https://projects.coin-or.org/Clp), optimized towards fast model building and fast resolves.
4 |
5 | ## Overview
6 |
7 | The interface provides a number of useful features for Java programmers who want to build either large models or apply decomposition strategies that require a lot of resolves. The interface has undergone several rounds of testing and profiling outside of unit tests.
8 |
9 | #### Compact model creation using builders
10 |
11 | Variables, constraints, and linear expressions are available as Java objects to make model building as easy as possible.
12 |
13 | Decision variables as well as their bounds and objective coefficients can be created in a single line. For example, ![x \in [-3,3]](https://latex.codecogs.com/gif.latex?x%20%5Cin%20%5B-3%2C3%5D) and , would become
14 | ```
15 | CLPVariable x = model.addVariable().lb(-3).ub(3);
16 | CLPVariable y = model.addVariable().free();
17 | ```
18 | Since there is no operator overloading in Java, algebraic formulations are not possible. To avoid excessive use of setters, constraints can be built by using a series of *add* statements. For example,  can be expressed as
19 | ```
20 | model.createExpression().add(3,x).add(4,y).leq(10);
21 | ```
22 | The *add* statements also accepts vectors of variables and coefficients. See the [javadoc](http://quantego.github.io/clp-java) for further reference.
23 |
24 | #### Fast model building
25 |
26 | Chunks of a model are buffered in heap for model building before being sent to the native lib. The size of the buffer can be set by the user. Models can be formulated in a row-by-row fashion, without bothering about possible performance bottlenecks. Models with millions of constraints can be generated quickly.
27 |
28 | #### Direct memory access
29 |
30 | Once a model is build it only lives in native memory, with the exception of referenced objects of variables and constraints which remain in heap. To update model coefficients, the model is accessed directly in native memory via direct byte buffers which speeds up resolves. When the model gets gc'ed, native memory will be released automatically.
31 |
32 | ## Installation
33 |
34 | #### Maven
35 | The project is available at the central repository. Simply add the following dependency to your pom file
36 | ```
37 |
38 | com.quantego
39 | clp-java
40 | 1.16.15
41 |
42 | ```
43 |
44 | #### All-in-one jar file
45 | Download the [latest build](https://github.com/quantego/clp-java/releases/latest) of the jar from the release page.
46 |
47 | The jar file contains the native libs for the most important host systems (Intel Mac, Apple Silcon, Win 64, Linux ARM and x86), so there won't be `UnsatisfiedLinkError`messages and there is no messing around with setting build paths. A copy of the native libs will be created in a temporary directory at runtime. Simply import the jar and you're done.
48 |
49 | ## Requirements
50 |
51 | * Java JDK 8
52 | * 64-bit Linux, Mac OS, or Windows
53 |
54 | ## Documentation
55 |
56 | See the [javadoc](http://quantego.github.io/clp-java) for a full class reference.
57 |
58 | ## Author
59 | Nils Löhndorf
60 |
61 |
62 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.quantego
4 | clp-java
5 | 1.16.15
6 | ${project.groupId}:${project.artifactId}
7 | A linear programming library based on the Coin-OR CLP linear solver.
8 | https://github.com/loehndorf/clp-java
9 |
10 |
11 | MIT License
12 | http://www.opensource.org/licenses/mit-license.php
13 |
14 |
15 |
16 |
17 | Nils Loehndorf
18 | nils@loehndorf.com
19 | Quantego
20 |
21 |
22 |
23 | scm:git:git@github.com:loehndorf/clp-java.git
24 | scm:git:git@github.com:loehndorf/clp-java.git
25 | scm:git:git@github.com:loehndorf/clp-java.git
26 |
27 |
28 |
29 |
30 | in-project
31 | In Project Repo
32 | file://${project.basedir}/libs
33 |
34 |
35 |
36 | jar
37 |
38 |
39 |
40 | junit
41 | junit
42 | 4.8.2
43 | test
44 |
45 |
46 | com.github.jnr
47 | jnr-ffi
48 | 2.2.15
49 |
50 |
51 |
52 |
53 | UTF-8
54 | 1.8
55 | 1.8
56 |
57 |
58 |
59 |
60 | ossrh
61 | https://oss.sonatype.org/content/repositories/snapshots
62 |
63 |
64 | ossrh
65 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
66 |
67 |
68 |
69 |
70 | ${project.artifactId}-${project.version}
71 |
72 |
73 | org.sonatype.plugins
74 | nexus-staging-maven-plugin
75 | 1.6.13
76 | true
77 |
78 | ossrh
79 | https://oss.sonatype.org/
80 | true
81 |
82 |
83 |
84 |
85 | org.apache.maven.plugins
86 | maven-source-plugin
87 |
88 |
89 | attach-sources
90 |
91 | jar
92 |
93 |
94 |
95 |
96 |
97 | org.apache.maven.plugins
98 | maven-javadoc-plugin
99 |
100 |
101 | attach-javadocs
102 |
103 | jar
104 |
105 |
106 |
107 |
108 | -Xdoclint:none
109 | false
110 |
111 |
112 |
113 | maven-assembly-plugin
114 |
115 |
116 | package
117 |
118 | single
119 |
120 |
121 |
122 |
123 |
124 | jar-with-dependencies
125 |
126 |
127 |
128 | com.quantego.clp.NativeLoader
129 |
130 |
131 | ${project.artifactId}-${project.version}-full
132 | false
133 |
134 |
135 |
136 | org.apache.maven.plugins
137 | maven-compiler-plugin
138 |
139 | 8
140 | 8
141 |
142 |
143 |
144 | org.apache.maven.plugins
145 | maven-gpg-plugin
146 | 1.5
147 |
148 |
149 | sign-artifacts
150 | verify
151 |
152 | sign
153 |
154 |
155 |
156 |
157 |
158 |
159 |
--------------------------------------------------------------------------------
/src/main/java/com/quantego/clp/CLP.java:
--------------------------------------------------------------------------------
1 | package com.quantego.clp;
2 |
3 | import com.quantego.clp.CLPConstraint.TYPE;
4 | import jnr.ffi.Memory;
5 | import jnr.ffi.Pointer;
6 | import jnr.ffi.Runtime;
7 | import java.io.File;
8 | import java.io.IOException;
9 | import java.util.ArrayList;
10 | import java.util.HashMap;
11 | import java.util.List;
12 | import java.util.Map;
13 |
14 | /**
15 | *
Java interface for the CLP linear solver. The implementation provides a light-weight wrapper that
16 | * creates as little overhead as possible. If no variables or constraints are referenced, the memory
17 | * footprint in Java heap is negligible.
18 | *
19 | *
Chunks of a model are buffered in heap for model building before
20 | * being sent to the native lib. The size of the buffer can be set with {@link CLP#buffer(int)}. The buffer
21 | * helps to formulate models in a row-by-row fashion, without bothering about possible performance bottlenecks.
22 | * Models with millions of constraints can be generated quickly.
23 | *
24 | *
To update model coefficients, the model is accessed
25 | * directly in native memory via direct byte buffers which enables fast resolves.
26 | * When the model gets gc'ed, native memory will be released automatically.
27 | *
28 | *
For debugging a model, use {@link CLP#verbose(int)} to set the internal log level of CLP which will show some solution information
29 | * during the solution process. {@link CLP#toString()} returns the model as string in .lp format (Xpress style),
30 | * and {@link CLP#printModel()} sends it to standard out in the same format.
31 | * @author Nils Loehndorf
32 | *
33 | */
34 | public class CLP {
35 |
36 | static CLPNative NATIVE = NativeLoader.load();
37 | static Runtime RUNTIME = Runtime.getSystemRuntime();
38 |
39 | Pointer _model;
40 | Pointer _solve;
41 | Pointer _elements;
42 | Pointer _rowLower;
43 | Pointer _rowUpper;
44 | Pointer _obj;
45 | Pointer _colLower;
46 | Pointer _colUpper;
47 | Pointer _primal;
48 | Pointer _dual;
49 | int[] _starts;
50 | int[] _index;
51 |
52 | Map _varNames = new HashMap<>();
53 | Map _ctrNames = new HashMap<>();
54 | int _numCols;
55 | int _numRows;
56 | int _numElements;
57 | double _objValue = Double.NaN;
58 | boolean _maximize;
59 | double _offset;
60 | int _bufferSize = 100000;
61 | double _smallestElement = 1.e-20;
62 | int _numNativeCols;
63 | int _numNativeRows;
64 | ColBuffer _colBuffer = new ColBuffer();
65 | RowBuffer _rowBuffer = new RowBuffer();
66 | QuadraticObjective _qobj;
67 | ALGORITHM _algorithm;
68 |
69 | /**
70 | * Create an new model instance.
71 | */
72 | public CLP () {
73 | _model = init();
74 | }
75 |
76 | public static CLP createFromMPS(File f) {
77 | // Make BridJ Pointer to file
78 | String path = f.toPath().toString()+'\0';
79 | // Read MPS
80 | CLP clp = new CLP();
81 | NATIVE.Clp_readMps(clp._model, path, 1, 0);
82 |
83 | // Explicitly release manually allocated memory to be on the safe side
84 | // This is normally freed by finalize method from BridJ
85 |
86 | return clp;
87 | }
88 |
89 | Pointer init() {
90 | Pointer model = NATIVE.Clp_newModel();
91 | NATIVE.Clp_setLogLevel(model,0);
92 | NATIVE.Clp_setSmallElementValue(model, 0.);
93 | NATIVE.Clp_scaling(model, 0);
94 | return model;
95 | }
96 |
97 | private void flushBuffers() {
98 | NATIVE.Clp_setObjectiveOffset(_model, (_maximize?1:-1)*_offset);
99 | if (_colBuffer.size()>0)
100 | addCols();
101 | if (_numRows == 0)
102 | _rowBuffer.addDummyRow();
103 | if (_rowBuffer.size()>0)
104 | addRows();
105 | if (_qobj != null)
106 | _qobj.update(_model);
107 | }
108 |
109 | private void addRows() {
110 | NATIVE.Clp_addRows(_model, _rowBuffer.size(),
111 | arrayToPointer(_rowBuffer.lower()),
112 | arrayToPointer(_rowBuffer.upper()),
113 | arrayToPointer(_rowBuffer.starts()),
114 | arrayToPointer(_rowBuffer.columns()),
115 | arrayToPointer(_rowBuffer.elements()));
116 | _numElements += _rowBuffer._elements.size();
117 | _elements = NATIVE.Clp_getElements(_model);
118 | _rowLower = NATIVE.Clp_getRowLower(_model);
119 | for (int i=0; i<_rowBuffer.size(); i++) {
120 | if (_rowBuffer._lower.get(i)==Double.NEGATIVE_INFINITY)
121 | _rowLower.putDouble((i+_numNativeRows)*Double.BYTES,Double.NEGATIVE_INFINITY);
122 | }
123 | _rowUpper = NATIVE.Clp_getRowUpper(_model);
124 | for (int i=0; i<_rowBuffer.size(); i++) {
125 | if (_rowBuffer._upper.get(i)==Double.POSITIVE_INFINITY)
126 | _rowUpper.putDouble((i+_numNativeRows)*Double.BYTES,Double.POSITIVE_INFINITY);
127 | }
128 | _rowBuffer = new RowBuffer();
129 | _dual = NATIVE.Clp_dualRowSolution(_model);
130 | _numNativeRows = _numRows;
131 | _index = null;
132 | _starts = null;
133 | }
134 |
135 | private int[] getIndex() {
136 | if (_index==null) {
137 | _index = new int[_numElements];
138 | NATIVE.Clp_getIndices(_model).get(0,_index,0,_numElements);
139 | }
140 | return _index;
141 |
142 | }
143 |
144 | private int[] getStarts() {
145 | if (_starts==null) {
146 | _starts = new int[_numCols + 1];
147 | NATIVE.Clp_getVectorStarts(_model).get(0,_starts,0,_numCols + 1);
148 | }
149 | return _starts;
150 | }
151 |
152 | private void addCols() {
153 | NATIVE.Clp_resize(_model, _numNativeRows, _numCols);
154 | _obj = NATIVE.Clp_getObjCoefficients(_model);
155 | _colLower = NATIVE.Clp_getColLower(_model);
156 | _colUpper = NATIVE.Clp_getColUpper(_model);
157 | for (Integer index : _colBuffer.objectives.keySet())
158 | _obj.putDouble(index*Double.BYTES, _colBuffer.objectives.get(index));
159 | for (Integer index : _colBuffer.lower.keySet())
160 | _colLower.putDouble(index*Double.BYTES, _colBuffer.lower.get(index));
161 | for (Integer index : _colBuffer.upper.keySet())
162 | _colUpper.putDouble(index*Double.BYTES, _colBuffer.upper.get(index));
163 | _colBuffer = new ColBuffer();
164 | _numNativeCols = _numCols;
165 | _primal = NATIVE.Clp_primalColumnSolution(_model);
166 | }
167 |
168 | private void neg() {
169 | if (_colBuffer.size()>0)
170 | addCols();
171 | if (_rowBuffer.size()>0)
172 | addRows();
173 | for (int col=0; col<_numCols; col++)
174 | _obj.putDouble(col*Double.BYTES, -_obj.getDouble(col*Double.BYTES));
175 | if (_qobj != null)
176 | _qobj.neg();
177 | }
178 |
179 | String getVariableName(int index) {
180 | String name = _varNames.get(index);
181 | if (name==null)
182 | name = "x_"+index;
183 | return name;
184 | }
185 |
186 | String getConstraintName(int index) {
187 | String name = _ctrNames.get(index);
188 | if (name==null)
189 | name = "ctr_"+index;
190 | return name;
191 | }
192 |
193 | /**
194 | * Store the model in a proprietary CLP file format.
195 | * @param filename
196 | */
197 | public void storeModel(String filename) {
198 | NATIVE.Clp_saveModel(_model, filename);
199 | }
200 |
201 | /**
202 | * Restore a model from a proprietary CLP file format.
203 | * @param filename
204 | * @throws IOException
205 | */
206 | public void restoreModel(String filename) throws IOException {
207 | if (!new File(filename).canRead())
208 | throw new IOException(String.format("File '%s' does not exist or cannot be read.",filename));
209 | NATIVE.Clp_restoreModel(_model, filename);
210 | _rowLower = NATIVE.Clp_getRowLower(_model);
211 | _rowUpper = NATIVE.Clp_getRowUpper(_model);
212 | _colLower = NATIVE.Clp_getColLower(_model);
213 | _colUpper = NATIVE.Clp_getColUpper(_model);
214 | _elements = NATIVE.Clp_getElements(_model);
215 | _maximize = NATIVE.Clp_getObjSense(_model) == -1;
216 | _index = null;
217 | _starts = null;
218 | _dual = NATIVE.Clp_dualRowSolution(_model);
219 | _obj = NATIVE.Clp_getObjCoefficients(_model);
220 | _primal = NATIVE.Clp_primalColumnSolution(_model);
221 | _numCols = NATIVE.Clp_getNumCols(_model);
222 | _numRows = NATIVE.Clp_getNumRows(_model);
223 | _numNativeCols = _numCols;
224 | _numNativeRows = _numRows;
225 | _numElements = NATIVE.Clp_getNumElements(_model);
226 | }
227 |
228 | /**
229 | *
230 | * @param constraint
231 | * @return Get dual solution value.
232 | */
233 | public double getDualSolution(CLPConstraint constraint) {
234 | if (constraint._index >= _numNativeRows)
235 | flushBuffers();
236 | return _maximize ? -_dual.getDouble(constraint._index*Double.BYTES) : _dual.getDouble(constraint._index*Double.BYTES);
237 | }
238 |
239 | /**
240 | *
241 | * @param variable
242 | * @return Get solution value.
243 | */
244 | public double getSolution(CLPVariable variable) {
245 | if (variable._index >= _numNativeCols)
246 | flushBuffers();
247 | return _primal.getDouble(variable._index*Double.BYTES);
248 | }
249 |
250 | /**
251 | * Set variable bounds. See {@link CLPVariable#bounds(double, double)}.
252 | * @param variable
253 | * @param lb
254 | * @param ub
255 | */
256 | public void setVariableBounds(CLPVariable variable, double lb, double ub) {
257 | if (variable._index < _numNativeCols) {
258 | _colLower.putDouble(variable._index*Double.BYTES,lb);
259 | _colUpper.putDouble(variable._index*Double.BYTES,ub);
260 | }
261 | else {
262 | _colBuffer.lower.put(variable._index, lb);
263 | _colBuffer.upper.put(variable._index, ub);
264 | }
265 | }
266 |
267 | /**
268 | * Set variable lower bound. See {@link CLPVariable#lb(double)}.
269 | * @param variable
270 | * @param value
271 | */
272 | public void setVariableLowerBound(CLPVariable variable, double value) {
273 | value = checkValue(value);
274 | if (variable._index < _numNativeCols)
275 | _colLower.putDouble(variable._index*Double.BYTES,value);
276 | else
277 | _colBuffer.lower.put(variable._index, value);
278 | }
279 |
280 | /**
281 | * Set variable upper bound. See {@link CLPVariable#ub(double)}.
282 | * @param variable
283 | * @param value
284 | */
285 | public void setVariableUpperBound(CLPVariable variable, double value) {
286 | value = checkValue(value);
287 | if (variable._index < _numNativeCols)
288 | _colUpper.putDouble(variable._index*Double.BYTES,value);
289 | else
290 | _colBuffer.upper.put(variable._index, value);
291 | }
292 |
293 | /**
294 | *
295 | * @param variable
296 | * @param name
297 | */
298 | public void setVariableName(CLPVariable variable, String name) {
299 | _varNames.put(variable._index,name);
300 | }
301 |
302 | /**
303 | * Set the left-hand side coefficient of a constraint. See {@link CLPConstraint#setLhs(CLPVariable, double)}.
304 | * @param constraint
305 | * @param variable
306 | * @param value
307 | */
308 | public void setConstraintCoefficient(CLPConstraint constraint, CLPVariable variable, double value) {
309 | if (constraint._index < _numNativeRows) {
310 | int[] index = getIndex();
311 | int[] starts = getStarts();
312 | int pos = starts[variable._index];
313 | int end = starts[variable._index+1];
314 | while(index[pos++]!=constraint._index) {
315 | if (pos>=end)
316 | throw new IllegalStateException(String.format("Constraint %s does not contain variable %s. Coefficient not set.",constraint.toString(),variable.toString()));
317 | }
318 | value = checkValue(value);
319 | _elements.putDouble((pos-1)*Double.BYTES,value);
320 | }
321 | else
322 | _rowBuffer.setElement(constraint._index,variable._index, value);
323 | }
324 |
325 | private double checkValue(double value) {
326 | if (Math.abs(value)>=_smallestElement)
327 | return value;
328 | return 0.;
329 | }
330 |
331 | /**
332 | * Set constraint bounds. See {@link CLPConstraint#setRhs(double)}.
333 | * @param constraint
334 | * @param lb
335 | * @param ub
336 | */
337 | public void setConstraintBounds(CLPConstraint constraint, double lb, double ub) {
338 | lb = checkValue(lb);
339 | ub = checkValue(ub);
340 | if (constraint._index < _numNativeRows) {
341 | _rowLower.putDouble(constraint._index*Double.BYTES,lb);
342 | _rowUpper.putDouble(constraint._index*Double.BYTES,ub);
343 | }
344 | else {
345 | _rowBuffer._lower.set(constraint._index,lb);
346 | _rowBuffer._upper.set(constraint._index,ub);
347 |
348 | }
349 | }
350 |
351 | /**
352 | * Set constraint lower bound. See {@link CLPConstraint#setRhs(double)}.
353 | * @param constraint
354 | * @param value
355 | */
356 | public void setConstraintLowerBound(CLPConstraint constraint, double value) {
357 | value = checkValue(value);
358 | if (constraint._index < _numNativeRows)
359 | _rowLower.putDouble(constraint._index*Double.BYTES,value);
360 | else
361 | _rowBuffer._lower.set(constraint._index,value);
362 | }
363 |
364 | /**
365 | * Set constraint upper bound. See {@link CLPConstraint#setRhs(double)}.
366 | * @param constraint
367 | * @param value
368 | */
369 | public void setConstraintUpperBound(CLPConstraint constraint, double value) {
370 | value = checkValue(value);
371 | if (constraint._index < _numNativeRows)
372 | _rowUpper.putDouble(constraint._index*Double.BYTES,value);
373 | else
374 | _rowBuffer._upper.set(constraint._index,value);
375 |
376 | }
377 |
378 | /**
379 | *
380 | * @param constraint
381 | * @param name
382 | */
383 | public void setConstraintName(CLPConstraint constraint, String name) {
384 | _ctrNames.put(constraint._index,name);
385 | }
386 |
387 | /**
388 | * Print CLP log to standard out (default=0).
389 | * 0 - none
390 | * 1 - just final info
391 | * 2 - basic factorization info
392 | * 3 - finer factorization info
393 | * 4 - verbose
394 | * @param level
395 | * @return builder
396 | */
397 | public CLP verbose(int level) {
398 | NATIVE.Clp_setLogLevel(_model,level);
399 | return this;
400 | }
401 |
402 | /**
403 | * A number of constraints remain in heap space during model building and will be passed to the native methods when needed.
404 | * The buffer gets flushed either when {@link CLP#solve()} gets executed or when the maximum buffer size is reached (default=10000).
405 | * @return builder
406 | */
407 | public CLP buffer(int size) {
408 | _bufferSize = size;
409 | return this;
410 | }
411 |
412 | /**
413 | * Solve as maximization problem.
414 | * @return builder
415 | */
416 | public CLP maximization() {
417 | if (!_maximize)
418 | neg();
419 | _maximize = true;
420 | return this;
421 | }
422 |
423 | /**
424 | * Solve as maximization problem.
425 | * @return builder
426 | */
427 | public CLP minimization() {
428 | if (_maximize)
429 | neg();
430 | _maximize = false;
431 | return this;
432 | }
433 |
434 | /**
435 | * Add a new variable to the model
436 | * @return
437 | */
438 | public CLPVariable addVariable() {
439 | if (_colBuffer.size()>=_bufferSize)
440 | addCols();
441 | _colBuffer.addCol();
442 | return new CLPVariable(this, _numCols++);
443 | }
444 |
445 | /**
446 | * Create a set of variables.
447 | * @param size
448 | * @return
449 | */
450 | public CLPVariableSet addVariables(int size) {
451 | return new CLPVariableSet(this,size);
452 | }
453 |
454 | /**
455 | * Set the objective coefficient of the given variable.
456 | * @param variable
457 | * @param value
458 | */
459 | public void setObjectiveCoefficient(CLPVariable variable, double value) {
460 | value = checkValue(value);
461 | if (_maximize)
462 | value = -value;
463 | if (variable._index < _numNativeCols)
464 | _obj.putDouble(variable._index*Double.BYTES, value);
465 | else
466 | _colBuffer.objectives.put(variable._index, value);
467 | }
468 |
469 | /**
470 | * Set the objective coefficient of the given variable.
471 | * @param variable
472 | * @param value
473 | */
474 | public void setQuadraticObjectiveCoefficient(CLPVariable variable, double value) {
475 | value = checkValue(value);
476 | if (_maximize && value>0)
477 | throw new IllegalArgumentException(String.format(
478 | "Quadratic objective coefficient of variable %s must not be greater than zero.", variable.toString()));
479 | if (!_maximize && value<0)
480 | throw new IllegalArgumentException(String.format(
481 | "Quadratic objective coefficient of variable %s must not be less than zero.", variable.toString()));
482 | if (variable._index >= _numCols)
483 | setObjectiveCoefficient(variable,0);
484 | if (_qobj == null)
485 | _qobj = new QuadraticObjective();
486 | _qobj.put(variable._index, _maximize ? -value : value);
487 | }
488 |
489 | /**
490 | * Set objective constant term.
491 | * @param value
492 | */
493 | public void setObjectiveOffset(double value) {
494 | value = checkValue(value);
495 | _offset = value;
496 | }
497 |
498 | /**
499 | * Create an expression builder to add a constraint or formulate the objective function.
500 | * @return builder
501 | */
502 | public CLPExpression createExpression() {
503 | return new CLPExpression(this);
504 | }
505 |
506 | /**
507 | * Set the objective function to the model without using {@link CLP#createExpression()}. Objective coefficients not set remain unchanged.
508 | * @param terms terms of the objective function
509 | * @param offset constant offset in the objective function
510 | * @return
511 | */
512 | public CLPObjective addObjective(Map terms, double offset) {
513 | for (CLPVariable var : terms.keySet())
514 | setObjectiveCoefficient(var,terms.get(var));
515 | setObjectiveOffset(_offset+offset);
516 | return new CLPObjective(this);
517 | }
518 |
519 | /**
520 | * Add a new constraint to the model without using {@link CLP#createExpression()}.
521 | * @param lhs terms on the left-hand side
522 | * @param type constraint type
523 | * @param rhs right-hand side coefficient
524 | * @return
525 | */
526 | public CLPConstraint addConstraint(Map lhs, TYPE type, double rhs) {
527 | if (lhs.isEmpty()) throw new IllegalArgumentException("The constraint does not contain variables.");
528 | if (_rowBuffer.size()>=_bufferSize)
529 | flushBuffers();
530 | _rowBuffer.addRow(lhs,type,rhs);
531 | return new CLPConstraint(this,_numRows++,type);
532 | }
533 |
534 | /**
535 | * Add a new constraint to the model without using {@link CLP#createExpression()}.
536 | * @param lhs terms on the left-hand side
537 | * @param type constraint type
538 | * @param rhs right-hand side coefficient
539 | * @return
540 | */
541 | public CLPConstraint addConstraint(List variables, List lhs, TYPE type, double rhs) {
542 | if (lhs.size()==0) throw new IllegalArgumentException("The constraint does not contain variables.");
543 | if (variables.size()!=lhs.size()) throw new IllegalArgumentException("Arrays of unequal size.");
544 | if (_rowBuffer.size()>=_bufferSize)
545 | flushBuffers();
546 | _rowBuffer.addRow(variables,lhs,type,rhs);
547 | return new CLPConstraint(this,_numRows++,type);
548 | }
549 |
550 | /**
551 | * Solve the optimization problem.
552 | * @return solution {@link STATUS}
553 | */
554 | public STATUS solve() {
555 | //take care of empty problem
556 | flushBuffers();
557 | // if (_solve!=null)
558 | // NATIVE.clpInitialSolveWithOptions(_model,_solve);
559 | // else
560 | // NATIVE.clpInitialSolve(_model);
561 | if (_algorithm==ALGORITHM.DUAL)
562 | NATIVE.Clp_dual(_model,0);
563 | else if (_algorithm==ALGORITHM.PRIMAL)
564 | NATIVE.Clp_primal(_model,0);
565 | else {
566 | if (_solve!=null)
567 | NATIVE.Clp_initialSolveWithOptions(_model,_solve);
568 | else
569 | NATIVE.Clp_initialSolve(_model);
570 | }
571 | _objValue = NATIVE.Clp_getObjValue(_model);
572 | int status = NATIVE.Clp_status(_model);
573 | if (status == 0)
574 | return STATUS.OPTIMAL;
575 | if (status == 1)
576 | return STATUS.INFEASIBLE;
577 | if (status == 2)
578 | return STATUS.UNBOUNDED;
579 | if (status == 3)
580 | return STATUS.LIMIT;
581 | if (status == 4)
582 | return STATUS.ERROR;
583 | return STATUS.UNKNOWN;
584 | }
585 |
586 | /**
587 | * Rebuild the model from scratch. The previous model is deleted from memory.
588 | */
589 | public void reset() {
590 | flushBuffers();
591 | Pointer newModel = init();
592 | NATIVE.Clp_resize(newModel, _numRows, 0);
593 | double[] a = new double[_numCols];
594 | _colLower.get(0,a,0,_numCols);
595 | double[] b = new double[_numCols];
596 | _colUpper.get(0,b,0,_numCols);
597 | double[] c = new double[_numCols];
598 | _obj.get(0,c,0,_numCols);
599 | double[] d = new double[_numElements];
600 | _elements.get(0,d,0,_numElements);
601 | NATIVE.Clp_addColumns(newModel,
602 | _numCols,
603 | copyOfDoublePointer(_colLower,_numCols),
604 | copyOfDoublePointer(_colUpper,_numCols),
605 | copyOfDoublePointer(_obj,_numCols),
606 | arrayToPointer(getStarts()),
607 | arrayToPointer(getIndex()),
608 | copyOfDoublePointer(_elements,_numElements));
609 | Pointer rowLower = _rowLower;
610 | _rowLower = NATIVE.Clp_getRowLower(newModel);
611 | for (int i=0; i<_numRows; i++)
612 | _rowLower.putDouble(i*Double.BYTES,rowLower.getDouble(i*Double.BYTES));
613 | Pointer rowUpper = _rowUpper;
614 | _rowUpper = NATIVE.Clp_getRowUpper(newModel);
615 | for (int i=0; i<_numRows; i++)
616 | _rowUpper.putDouble(i*Double.BYTES,rowUpper.getDouble(i*Double.BYTES));
617 | Pointer colLower = _colLower;
618 | _colLower = NATIVE.Clp_getColLower(newModel);
619 | for (int i=0; i<_numCols; i++)
620 | _colLower.putDouble(i*Double.BYTES,colLower.getDouble(i*Double.BYTES));
621 | Pointer colUpper = _colUpper;
622 | _colUpper = NATIVE.Clp_getColUpper(newModel);
623 | for (int i=0; i<_numCols; i++)
624 | _colUpper.putDouble(i*Double.BYTES,colUpper.getDouble(i*Double.BYTES));
625 | _elements = NATIVE.Clp_getElements(newModel);
626 | _index = null;
627 | _starts = null;
628 | _dual = NATIVE.Clp_dualRowSolution(newModel);
629 | if (_qobj != null)
630 | NATIVE.Clp_loadQuadraticObjective(newModel, _qobj._numElements, _qobj._starts, _qobj._index, _qobj._elements);
631 | _obj = NATIVE.Clp_getObjCoefficients(newModel);
632 | _primal = NATIVE.Clp_primalColumnSolution(newModel);
633 | NATIVE.Clp_deleteModel(_model);
634 | _model = newModel;
635 | }
636 |
637 | /**
638 | * Solve the problem as maximization problem.
639 | * @return solution {@link STATUS}
640 | */
641 | public STATUS maximize() {
642 | maximization();
643 | return solve();
644 | }
645 |
646 | /**
647 | * Solve the problem as minimization problem.
648 | * @return solution {@link STATUS}
649 | */
650 | public STATUS minimize() {
651 | minimization();
652 | return solve();
653 | }
654 |
655 | /**
656 | *
657 | * @return the optimal objective value
658 | */
659 | public double getObjectiveValue() {
660 | return _maximize? -_objValue : _objValue;
661 | }
662 |
663 | /**
664 | *
665 | * @return number of variables in model
666 | */
667 | public int getNumVariables() {
668 | return _numCols;
669 | }
670 |
671 | /**
672 | *
673 | * @return number of constraints in model
674 | */
675 | public int getNumConstraints() {
676 | return _numRows;
677 | }
678 |
679 | /**
680 | * Set the dual tolerance (default=1.e-7).
681 | * @param value
682 | * @return builder
683 | */
684 | public CLP dualTolerance(double value) {
685 | NATIVE.Clp_setDualTolerance(_model, value);
686 | return this;
687 | }
688 |
689 | /**
690 | * Set the smallest coefficient value considered as non-zero (default = 1.e-20). All values smaller than this will be set to zero.
691 | * @param value
692 | * @return builder
693 | */
694 | public CLP smallestCoefficient(double value) {
695 | if (value<0)
696 | throw new IllegalArgumentException("The smallest coefficient must be >= 0");
697 | _smallestElement = value;
698 | return this;
699 | }
700 |
701 | /**
702 | * Set the primal tolerance (default=1.e-7).
703 | * @param value
704 | * @return builder
705 | */
706 | public CLP primalTolerance(double value) {
707 | NATIVE.Clp_setPrimalTolerance(_model, value);
708 | return this;
709 | }
710 |
711 | /**
712 | * Set the maximum number of iterations of the solution algorithm.
713 | * @param iter
714 | * @return builder
715 | */
716 | public CLP maxIterations(int iter) {
717 | NATIVE.Clp_setMaximumIterations(_model, iter);
718 | return this;
719 | }
720 |
721 | /**
722 | * Set the maximum number of seconds for the solution process.
723 | * @param seconds
724 | * @return builder
725 | */
726 | public CLP maxSeconds(double seconds) {
727 | NATIVE.Clp_setMaximumSeconds(_model, seconds);
728 | return this;
729 | }
730 |
731 | /**
732 | * Define the parameter scaling defined by {@link SCALING} (default=OFF).
733 | * @param scaling
734 | * @return builder
735 | */
736 | public CLP scaling(SCALING scaling) {
737 | switch(scaling) {
738 | case OFF:
739 | NATIVE.Clp_scaling(_model, 0);
740 | break;
741 | case EQULIBRIUM:
742 | NATIVE.Clp_scaling(_model, 1);
743 | break;
744 | case GEOMETRIC:
745 | NATIVE.Clp_scaling(_model, 2);
746 | break;
747 | default:
748 | NATIVE.Clp_scaling(_model, 3);
749 | break;
750 | }
751 | return this;
752 | }
753 |
754 | /**
755 | * Turn presolve on (default=true).
756 | * @param on
757 | * @return builder
758 | */
759 | public CLP presolve(boolean on) {
760 | if (_solve==null) _solve = NATIVE.ClpSolve_new();
761 | NATIVE.ClpSolve_setPresolveType(_solve, on ? 0 : 1, -1);
762 | return this;
763 | }
764 |
765 | /**
766 | * Set the solution {@link ALGORITHM} (default=AUTO).
767 | * @param algorithm
768 | * @return builder
769 | */
770 | public CLP algorithm(ALGORITHM algorithm) {
771 | if (_solve==null) _solve = NATIVE.ClpSolve_new();
772 | switch(algorithm) {
773 | case DUAL:
774 | NATIVE.ClpSolve_setSolveType(_solve, 0, -1);
775 | break;
776 | case PRIMAL:
777 | NATIVE.ClpSolve_setSolveType(_solve, 1, -1);
778 | break;
779 | case PRIMAL_SPRINT:
780 | NATIVE.ClpSolve_setSolveType(_solve, 2, -1);
781 | break;
782 | case BARRIER:
783 | NATIVE.ClpSolve_setSolveType(_solve, 3, -1);
784 | break;
785 | case BARRIER_NO_CROSSOVER:
786 | NATIVE.ClpSolve_setSolveType(_solve, 4, -1);
787 | break;
788 | default:
789 | NATIVE.ClpSolve_setSolveType(_solve, 5, -1);
790 | break;
791 | }
792 | _algorithm = algorithm;
793 | return this;
794 | }
795 |
796 | /**
797 | * Solution algorithm
798 | * @author Nils Loehndorf
799 | *
800 | */
801 | public enum ALGORITHM {
802 | AUTO, DUAL, PRIMAL, PRIMAL_SPRINT, BARRIER, BARRIER_NO_CROSSOVER
803 | }
804 |
805 | /**
806 | * Solution status
807 | * @author Nils Loehndorf
808 | *
809 | */
810 | public enum STATUS {
811 | OPTIMAL, INFEASIBLE, UNBOUNDED, LIMIT, ERROR, UNKNOWN
812 | }
813 |
814 | /**
815 | * Parameter scaling
816 | * @author Nils Loehndorf
817 | *
818 | */
819 | public enum SCALING {
820 | OFF, EQULIBRIUM, GEOMETRIC, AUTO
821 | }
822 |
823 | @Override
824 | public void finalize() {
825 | NATIVE.Clp_deleteModel(_model);
826 | NATIVE.ClpSolve_delete(_solve);
827 | }
828 |
829 |
830 |
831 | private int[] toIntArray(List ints) {
832 | int[] ar = new int[ints.size()];
833 | int i=0;
834 | for (Integer j : ints)
835 | ar[i++] = j;
836 | return ar;
837 | }
838 |
839 | private double[] toDoubleArray(List doubles) {
840 | double[] ar = new double[doubles.size()];
841 | int i=0;
842 | for (Double d : doubles)
843 | ar[i++] = d;
844 | return ar;
845 | }
846 |
847 | private class QuadraticObjective {
848 | HashMap _buffer = new HashMap<>();
849 | private Pointer _elements;
850 | private Pointer _starts;
851 | private Pointer _index;
852 | int _numElements;
853 | boolean _hasChange;
854 |
855 | void flush() {
856 | if (_buffer.isEmpty()) return;
857 | int[] starts = new int[_numCols+1];
858 | starts[_numCols] = _numCols;
859 | int[] index = new int[_numCols];
860 | for (int i=0; i<_numCols; i++) {
861 | starts[i] = i;
862 | index[i] = i;
863 | }
864 | _starts = arrayToPointer(starts);
865 | _index = arrayToPointer(index);
866 | Pointer elements = Memory.allocateDirect(RUNTIME,_numNativeCols*Double.BYTES);
867 | if (_elements != null)
868 | _elements.transferTo(0,elements,0,elements.size());
869 | _elements = elements;
870 | _numElements = _numNativeCols;
871 | for (Integer i : _buffer.keySet())
872 | _elements.putDouble(i*Double.BYTES, _buffer.get(i));
873 | _buffer.clear();
874 | }
875 |
876 | void update(Pointer model) {
877 | if (!_hasChange) return;
878 | flush();
879 | NATIVE.Clp_loadQuadraticObjective(model, _numCols, _starts, _index, _elements);
880 | _obj = NATIVE.Clp_getObjCoefficients(model);
881 | }
882 |
883 | void put(int index, double value) {
884 | value *= 2;
885 | if (index < _numElements)
886 | _elements.putDouble(index*Double.BYTES, value);
887 | else
888 | _buffer.put(index, value);
889 | _hasChange = true;
890 | }
891 |
892 | double get(int index) {
893 | return _elements.getDouble(index*Double.BYTES);
894 | }
895 |
896 | void neg() {
897 | for (int i=0; i<_numCols; i++)
898 | _elements.putDouble(i*Double.BYTES, -_elements.getDouble(i*Double.BYTES));
899 | _hasChange = true;
900 | update(_model);
901 | }
902 | }
903 |
904 | /**
905 | * Buffer for new variables added to the model.
906 | * @author Nils Loehndorf
907 | *
908 | */
909 | private class ColBuffer {
910 | int _size;
911 | Map objectives = new HashMap<>();
912 | Map lower = new HashMap<>();
913 | Map upper = new HashMap<>();
914 |
915 | void addCol() {
916 | _size++;
917 | }
918 |
919 | int size() {
920 | return _size;
921 | }
922 | }
923 |
924 | /**
925 | * Buffer for new constraints added to the model.
926 | * @author Nils Loehndorf
927 | *
928 | */
929 | private class RowBuffer {
930 |
931 | List _columns = new ArrayList<>();
932 | List _starts = new ArrayList<>();
933 | List _elements = new ArrayList<>();
934 | List _lower = new ArrayList<>();
935 | List _upper = new ArrayList<>();
936 |
937 | RowBuffer() {
938 | _starts.add(0);
939 | }
940 |
941 | int size() {
942 | return _lower.size();
943 | }
944 |
945 | int[] columns() {
946 | return toIntArray(_columns);
947 | }
948 |
949 | int[] starts() {
950 | return toIntArray(_starts);
951 | }
952 |
953 | double[] elements() {
954 | return toDoubleArray(_elements);
955 | }
956 |
957 | double[] lower() {
958 | return toDoubleArray(_lower);
959 | }
960 |
961 | double[] upper() {
962 | return toDoubleArray(_upper);
963 | }
964 |
965 | void setElement(int rowIndex, int colIndex, double value) {
966 | checkValue(value);
967 | int pos = _starts.get(rowIndex);
968 | int end = pos + _starts.get(rowIndex+1);
969 | while(_columns.get(pos++)!=colIndex) {
970 | if (pos>=end)
971 | throw new IllegalStateException("Constraint does not contain this variable. Must be redefined first.");
972 | }
973 | pos--;
974 | value = checkValue(value);
975 | _elements.set(pos,value);
976 | }
977 |
978 | void addDummyRow() {
979 | _lower.add(Double.NEGATIVE_INFINITY);
980 | _upper.add(Double.POSITIVE_INFINITY);
981 | _starts.add(_elements.size()+1);
982 | _columns.add(0);
983 | _elements.add(1.);
984 | _numRows++;
985 | }
986 |
987 | void addRow(Map lhs, TYPE type, double rhs) {
988 | rhs = checkValue(rhs);
989 | switch(type) {
990 | case EQ:
991 | _lower.add(rhs);
992 | _upper.add(rhs);
993 | break;
994 | case GEQ:
995 | _lower.add(rhs);
996 | _upper.add(Double.POSITIVE_INFINITY);
997 | break;
998 | case LEQ:
999 | _lower.add(Double.NEGATIVE_INFINITY);
1000 | _upper.add(rhs);
1001 | break;
1002 | default:
1003 | _lower.add(Double.NEGATIVE_INFINITY);
1004 | _upper.add(Double.POSITIVE_INFINITY);
1005 | break;
1006 | }
1007 | _starts.add(_elements.size()+lhs.size());
1008 | for (CLPVariable variable : lhs.keySet()) {
1009 | _columns.add(variable._index);
1010 | double value = lhs.get(variable);
1011 | value = checkValue(value);
1012 | _elements.add(value);
1013 | }
1014 | }
1015 |
1016 | void addRow(List variables, List lhs, TYPE type, double rhs) {
1017 | rhs = checkValue(rhs);
1018 | switch(type) {
1019 | case EQ:
1020 | _lower.add(rhs);
1021 | _upper.add(rhs);
1022 | break;
1023 | case GEQ:
1024 | _lower.add(rhs);
1025 | _upper.add(Double.POSITIVE_INFINITY);
1026 | break;
1027 | case LEQ:
1028 | _lower.add(Double.NEGATIVE_INFINITY);
1029 | _upper.add(rhs);
1030 | break;
1031 | default:
1032 | _lower.add(Double.NEGATIVE_INFINITY);
1033 | _upper.add(Double.POSITIVE_INFINITY);
1034 | break;
1035 | }
1036 | _starts.add(_elements.size()+lhs.size());
1037 | for (int i=0; i constraintStrings = new ArrayList<>(_numRows);
1077 | for (int row=0; row<_numRows; row++)
1078 | constraintStrings.add(new StringBuilder().append(getConstraintName(row)).append(":"));
1079 | int[] starts = getStarts();
1080 | int[] index = getIndex();
1081 | for (int col=0; col<_numCols; col++) {
1082 | int begin = starts[col];
1083 | int end = starts[col+1];
1084 | for (int j=begin; jDouble.NEGATIVE_INFINITY)
1099 | modelString.append(constraintStrings.get(row).append(" >= ").append(lb).append("\n"));
1100 | }
1101 | //bounds
1102 | modelString.append("Bounds\n");
1103 | for (int col=0; col<_numCols; col++) {
1104 | double lb = _colLower.getDouble(col*Double.BYTES);
1105 | double ub = _colUpper.getDouble(col*Double.BYTES);
1106 | if (lb==0 && ub=Double.MAX_VALUE)
1109 | modelString.append("-inf <= ").append(getVariableName(col)).append(" <= inf\n");
1110 | else if (lb!=0 && lb>-Double.MAX_VALUE && ub>=Double.MAX_VALUE)
1111 | modelString.append(lb).append(" <= ").append(getVariableName(col)).append(" <= inf").append("\n");
1112 | else if (lb<=-Double.MAX_VALUE && ub-Double.MAX_VALUE && ub0)
1128 | return " + "+d+" "+s;
1129 | return " - "+(-d)+" "+s;
1130 | }
1131 |
1132 | static public Pointer arrayToPointer(double[] array) {
1133 | Pointer pointer = Memory.allocateDirect(RUNTIME,array.length * Double.BYTES);
1134 | pointer.put(0, array, 0, array.length);
1135 | return pointer;
1136 | }
1137 |
1138 | static public Pointer arrayToPointer(int[] array) {
1139 | Pointer pointer = Memory.allocateDirect(RUNTIME,array.length * Integer.BYTES);
1140 | pointer.put(0, array, 0, array.length);
1141 | return pointer;
1142 | }
1143 |
1144 | public static Pointer copyOfDoublePointer(Pointer pointer, int length) {
1145 | Pointer pointer2 = Memory.allocateDirect(RUNTIME,length * Double.BYTES);
1146 | pointer.transferTo(0,pointer2,0,length* Double.BYTES);
1147 | return pointer2;
1148 | }
1149 |
1150 |
1151 | }
1152 |
--------------------------------------------------------------------------------
/src/main/java/com/quantego/clp/CLPConstraint.java:
--------------------------------------------------------------------------------
1 | package com.quantego.clp;
2 |
3 | /**
4 | * Holds a constraint of a {@link CLP} model.
5 | * @author Nils Loehndorf
6 | *
7 | */
8 | public class CLPConstraint {
9 |
10 | CLP _solver;
11 | TYPE _type;
12 | String _name;
13 | int _index;
14 | double _rhs;
15 |
16 | CLPConstraint(CLP solver, int index, TYPE type) {
17 | _solver = solver;
18 | _index = index;
19 | _type = type;
20 | }
21 |
22 | /**
23 | * Constraint name
24 | * @param name
25 | * @return
26 | */
27 | public CLPConstraint name(String name) {
28 | _solver.setConstraintName(this, name);
29 | return this;
30 | }
31 |
32 | /**
33 | * Set the left-hand side coefficient of the given variable. Throws an exception if the variable is not in the constraint.
34 | * @param variable
35 | * @param value
36 | * @return
37 | */
38 | public CLPConstraint setLhs(CLPVariable variable, double value) {
39 | _solver.setConstraintCoefficient(this, variable, value);
40 | return this;
41 | }
42 |
43 | /**
44 | * Set the right-hand side of this constraint.
45 | * @param value
46 | * @return
47 | */
48 | public CLPConstraint setRhs(double value) {
49 | _rhs = value;
50 | switch(_type) {
51 | case EQ:
52 | _solver.setConstraintBounds(this, value, value);
53 | break;
54 | case GEQ:
55 | _solver.setConstraintLowerBound(this, value);
56 | break;
57 | case LEQ:
58 | _solver.setConstraintUpperBound(this, value);
59 | break;
60 | default:
61 | break;
62 | }
63 | return this;
64 | }
65 |
66 | /**
67 | * Set the constraint as free.
68 | * @return
69 | */
70 | public CLPConstraint free() {
71 | _solver.setConstraintBounds(this, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
72 | return this;
73 | }
74 |
75 | /**
76 | *
77 | * @return Get the dual solution value of this constraint.
78 | */
79 | public double getSolution() {
80 | return _solver.getDualSolution(this);
81 | }
82 |
83 | /**
84 | *
85 | * @return the right-hand side coeffcient of this constraint
86 | */
87 | public double getRhs() {
88 | return _rhs;
89 | }
90 |
91 | /**
92 | * Constraint type.
93 | * @author Nils Loehndorf
94 | *
95 | */
96 | public enum TYPE {
97 | LEQ, GEQ, EQ, NEQ
98 | }
99 |
100 | @Override
101 | public String toString() {
102 | return _solver.getConstraintName(_index);
103 | }
104 |
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/src/main/java/com/quantego/clp/CLPExpression.java:
--------------------------------------------------------------------------------
1 | package com.quantego.clp;
2 |
3 | import java.util.Map;
4 | import java.util.HashMap;
5 |
6 | /**
7 | * Builder class to create the left-hand side of a {@link CLPConstraint}. Use {@link CLP#createExpression()} to create a new instance.
8 | * @author Nils Loehndorf
9 | *
10 | */
11 | public class CLPExpression {
12 |
13 | CLP _solver;
14 | Map _terms = new HashMap<>();
15 | double _constant;
16 |
17 | CLPExpression(CLP solver) {
18 | _solver = solver;
19 | }
20 |
21 | /**
22 | * Add a constant term to the expression. Terms are collected automatically.
23 | * @param value
24 | * @return builder
25 | */
26 | public CLPExpression add(double value) {
27 | _constant += value;
28 | return this;
29 | }
30 |
31 | /**
32 | * Add a new term to the expression. Terms are collected automatically.
33 | * @param value
34 | * @param variable
35 | * @return builder
36 | */
37 | public CLPExpression add(double value, CLPVariable variable) {
38 | Double old;
39 | if ((old = _terms.get(variable)) != null)
40 | value += old.doubleValue();
41 | _terms.put(variable,value);
42 | return this;
43 | }
44 |
45 | /**
46 | * Add a new term to the expression. Terms are collected automatically.
47 | * @param value
48 | * @param variable
49 | * @return builder
50 | */
51 | public CLPExpression add(CLPVariable variable, double value) {
52 | return add(value,variable);
53 | }
54 |
55 | /**
56 | * Add the sum of multiple variables.
57 | * @param value
58 | * @param variable
59 | * @return builder
60 | */
61 | public CLPExpression add(CLPVariable... variable) {
62 | for (CLPVariable var : variable)
63 | add(1.,var);
64 | return this;
65 | }
66 |
67 | /**
68 | * Add the sum of multiple variables, each multiplied by the same scalar.
69 | * @param value
70 | * @param variable
71 | * @return builder
72 | */
73 | public CLPExpression add(double value, CLPVariable... variable) {
74 | for (CLPVariable var : variable)
75 | add(value,var);
76 | return this;
77 | }
78 |
79 | /**
80 | * Add the sum of multiple terms.
81 | * @param value
82 | * @param variable
83 | * @return builder
84 | */
85 | public CLPExpression add(double[] values, CLPVariable[] variables) {
86 | if (values.length != variables.length)
87 | throw new IllegalArgumentException("Arrays must be of equal length.");
88 | for (int i=0; i variables) {
99 | for (CLPVariable var : variables.keySet()) {
100 | add(variables.get(var),var);
101 | }
102 | return this;
103 | }
104 |
105 | /**
106 | * Add this expression as less-or-equal constraint to the {@link CLP} model.
107 | * @param value right-hand side
108 | * @return this expression as {@link CLPConstraint}
109 | */
110 | public CLPConstraint leq(double value) {
111 | return _solver.addConstraint(_terms, CLPConstraint.TYPE.LEQ, value-_constant);
112 | }
113 |
114 | /**
115 | * Add this expression as not-equal constraint to the {@link CLP} model.
116 | * @param value right-hand side
117 | * @return this expression as {@link CLPConstraint}
118 | */
119 | public CLPConstraint neq(double value) {
120 | return _solver.addConstraint(_terms, CLPConstraint.TYPE.NEQ, value-_constant);
121 | }
122 |
123 | /**
124 | * Add this expression as greater-or-equal constraint to the {@link CLP} model.
125 | * @param value right-hand side
126 | * @return this expression as {@link CLPConstraint}
127 | */
128 | public CLPConstraint geq(double value) {
129 | return _solver.addConstraint(_terms, CLPConstraint.TYPE.GEQ, value-_constant);
130 | }
131 |
132 | /**
133 | * Add this expression as equality constraint to the {@link CLP} model.
134 | * @param value right-hand side
135 | * @return this expression as {@link CLPConstraint}
136 | */
137 | public CLPConstraint eq(double value) {
138 | return _solver.addConstraint(_terms, CLPConstraint.TYPE.EQ, value-_constant);
139 | }
140 |
141 | /**
142 | * Set this expression as objective function of the {@link CLP} model.
143 | * @return this expression as {@link CLPObjective}
144 | */
145 | public CLPObjective asObjective() {
146 | return _solver.addObjective(_terms, _constant);
147 | }
148 |
149 | @Override
150 | public String toString() {
151 | String str = "";
152 | for (CLPVariable var : _terms.keySet())
153 | str += CLP.termToString(_terms.get(var),var.toString())+" ";
154 | str.trim();
155 | if (str.startsWith("+"))
156 | return str.substring(2);
157 | return str;
158 | }
159 |
160 | }
161 |
--------------------------------------------------------------------------------
/src/main/java/com/quantego/clp/CLPNative.java:
--------------------------------------------------------------------------------
1 | package com.quantego.clp;
2 | import jnr.ffi.*;
3 |
4 | // Define the interface that is a part of JNR-FFI
5 | public interface CLPNative {
6 |
7 | String Clp_Version();
8 |
9 | int clpVersionMajor();
10 |
11 | int Clp_VersionMinor();
12 |
13 | int Clp_VersionRelease();
14 |
15 | Pointer Clp_newModel();
16 |
17 | void Clp_deleteModel(Pointer model);
18 |
19 | Pointer ClpSolve_new();
20 |
21 | void ClpSolve_delete(Pointer solve);
22 |
23 | void Clp_loadProblem(Pointer model, int numcols, int numrows, Pointer start, Pointer index, Pointer value, Pointer collb, Pointer colub, Pointer obj, Pointer rowlb, Pointer rowub);
24 | /**
25 | * Original signature : COINLINKAGE Clp_loadQuadraticObjective(Clp_Simplex*, const int, const CoinBigIndex*, const int*, const double*)
26 | * native declaration : line 96
27 | */
28 | void Clp_loadQuadraticObjective(Pointer model, int numberColumns, Pointer start, Pointer column, Pointer element);
29 | /**
30 | * Original signature : int Clp_readMps(Clp_Simplex*, const char*, int, int)
31 | * native declaration : line 103
32 | */
33 | int Clp_readMps(Pointer model, String filename, int keepNames, int ignoreErrors);
34 | /**
35 | * Original signature : void Clp_copyInIntegerInformation(Clp_Simplex*, const char*)
36 | * native declaration : line 107
37 | */
38 | void Clp_copyInIntegerInformation(Pointer model, String information);
39 | /**
40 | * Original signature : void Clp_deleteIntegerInformation(Clp_Simplex*)
41 | * native declaration : line 109
42 | */
43 | void Clp_deleteIntegerInformation(Pointer model);
44 | /**
45 | * Original signature : void Clp_resize(Clp_Simplex*, int, int)
46 | * native declaration : line 111
47 | */
48 | void Clp_resize(Pointer model, int newNumberRows, int newNumberColumns);
49 | /**
50 | * Original signature : void Clp_deleteRows(Clp_Simplex*, int, const int*)
51 | * native declaration : line 113
52 | */
53 | void Clp_deleteRows(Pointer model, int number, Pointer which);
54 | /**
55 | * Original signature : void Clp_addRows(Clp_Simplex*, int, const double*, const double*, const int*, const int*, const double*)
56 | * native declaration : line 115
57 | */
58 | void Clp_addRows(Pointer model, int number, Pointer rowLower, Pointer rowUpper, Pointer rowStarts, Pointer columns, Pointer elements);
59 | /**
60 | * Original signature : void Clp_deleteColumns(Clp_Simplex*, int, const int*)
61 | * native declaration : line 121
62 | */
63 | void Clp_deleteColumns(Pointer model, int number, Pointer which);
64 | /**
65 | * Original signature : void Clp_addColumns(Clp_Simplex*, int, const double*, const double*, const double*, const int*, const int*, const double*)
66 | * native declaration : line 123
67 | */
68 | void Clp_addColumns(Pointer model, int number, Pointer columnLower, Pointer columnUpper, Pointer objective, Pointer columnStarts, Pointer rows, Pointer elements);
69 | /**
70 | * Original signature : void Clp_chgRowLower(Clp_Simplex*, const double*)
71 | * native declaration : line 129
72 | */
73 | void Clp_chgRowLower(Pointer model, Pointer rowLower);
74 | /**
75 | * Original signature : void Clp_chgRowUpper(Clp_Simplex*, const double*)
76 | * native declaration : line 131
77 | */
78 | void Clp_chgRowUpper(Pointer model, Pointer rowUpper);
79 | /**
80 | * Original signature : void Clp_chgColumnLower(Clp_Simplex*, const double*)
81 | * native declaration : line 133
82 | */
83 | void Clp_chgColumnLower(Pointer model, Pointer columnLower);
84 | /**
85 | * Original signature : void Clp_chgColumnUpper(Clp_Simplex*, const double*)
86 | * native declaration : line 135
87 | */
88 | void Clp_chgColumnUpper(Pointer model, Pointer columnUpper);
89 | /**
90 | * Original signature : void Clp_chgObjCoefficients(Clp_Simplex*, const double*)
91 | * native declaration : line 137
92 | */
93 | void Clp_chgObjCoefficients(Pointer model, Pointer objIn);
94 | /**
95 | * Original signature : void Clp_dropNames(Clp_Simplex*)
96 | * native declaration : line 139
97 | */
98 | void Clp_dropNames(Pointer model);
99 |
100 | /**
101 | * Original signature : int Clp_numberRows(Clp_Simplex*)
102 | * native declaration : line 148
103 | */
104 | int Clp_numberRows(Pointer model);
105 | /**
106 | * Original signature : int Clp_numberColumns(Clp_Simplex*)
107 | * native declaration : line 150
108 | */
109 | int Clp_numberColumns(Pointer model);
110 | /**
111 | * Original signature : double Clp_primalTolerance(Clp_Simplex*)
112 | * native declaration : line 152
113 | */
114 | double Clp_primalTolerance(Pointer model);
115 | /**
116 | * Original signature : void Clp_setPrimalTolerance(Clp_Simplex*, double)
117 | * native declaration : line 153
118 | */
119 | void Clp_setPrimalTolerance(Pointer model, double value);
120 | /**
121 | * Original signature : double Clp_dualTolerance(Clp_Simplex*)
122 | * native declaration : line 155
123 | */
124 | double Clp_dualTolerance(Pointer model);
125 | /**
126 | * Original signature : void Clp_setDualTolerance(Clp_Simplex*, double)
127 | * native declaration : line 156
128 | */
129 | void Clp_setDualTolerance(Pointer model, double value);
130 | /**
131 | * Original signature : double Clp_dualObjectiveLimit(Clp_Simplex*)
132 | * native declaration : line 158
133 | */
134 | double Clp_dualObjectiveLimit(Pointer model);
135 | /**
136 | * Original signature : void Clp_setDualObjectiveLimit(Clp_Simplex*, double)
137 | * native declaration : line 159
138 | */
139 | void Clp_setDualObjectiveLimit(Pointer model, double value);
140 | /**
141 | * Original signature : double Clp_objectiveOffset(Clp_Simplex*)
142 | * native declaration : line 161
143 | */
144 | double Clp_objectiveOffset(Pointer model);
145 | /**
146 | * Original signature : void Clp_setObjectiveOffset(Clp_Simplex*, double)
147 | * native declaration : line 162
148 | */
149 | void Clp_setObjectiveOffset(Pointer model, double value);
150 | /**
151 | * Original signature : void Clp_problemName(Clp_Simplex*, int, char*)
152 | * native declaration : line 164
153 | */
154 | void Clp_problemName(Pointer model, int maxNumberCharacters, String array);
155 | /**
156 | * Original signature : COINLINKAGE Clp_setProblemName(Clp_Simplex*, int, char*)
157 | * native declaration : line 166
158 | */
159 | int Clp_setProblemName(Pointer model, int maxNumberCharacters, String array);
160 | /**
161 | * Original signature : int Clp_numberIterations(Clp_Simplex*)
162 | * native declaration : line 169
163 | */
164 | int Clp_numberIterations(Pointer model);
165 | /**
166 | * Original signature : void Clp_setNumberIterations(Clp_Simplex*, int)
167 | * native declaration : line 170
168 | */
169 | void Clp_setNumberIterations(Pointer model, int numberIterations);
170 | /**
171 | * Original signature : int maximumIterations(Clp_Simplex*)
172 | * native declaration : line 172
173 | */
174 | int maximumIterations(Pointer model);
175 | /**
176 | * Original signature : void Clp_setMaximumIterations(Clp_Simplex*, int)
177 | * native declaration : line 173
178 | */
179 | void Clp_setMaximumIterations(Pointer model, int value);
180 | /**
181 | * Original signature : double Clp_maximumSeconds(Clp_Simplex*)
182 | * native declaration : line 175
183 | */
184 | double Clp_maximumSeconds(Pointer model);
185 | /**
186 | * Original signature : void Clp_setMaximumSeconds(Clp_Simplex*, double)
187 | * native declaration : line 176
188 | */
189 | void Clp_setMaximumSeconds(Pointer model, double value);
190 | /**
191 | * Original signature : int Clp_hitMaximumIterations(Clp_Simplex*)
192 | * native declaration : line 178
193 | */
194 | int Clp_hitMaximumIterations(Pointer model);
195 | /**
196 | * Original signature : int Clp_status(Clp_Simplex*)
197 | * native declaration : line 186
198 | */
199 | int Clp_status(Pointer model);
200 | /**
201 | * Original signature : void Clp_setProblemStatus(Clp_Simplex*, int)
202 | * native declaration : line 188
203 | */
204 | void Clp_setProblemStatus(Pointer model, int problemStatus);
205 | /**
206 | * Original signature : int Clp_secondaryStatus(Clp_Simplex*)
207 | * native declaration : line 196
208 | */
209 | int Clp_secondaryStatus(Pointer model);
210 | /**
211 | * Original signature : void Clp_setSecondaryStatus(Clp_Simplex*, int)
212 | * native declaration : line 197
213 | */
214 | void Clp_setSecondaryStatus(Pointer model, int status);
215 | /**
216 | * Original signature : double Clp_optimizationDirection(Clp_Simplex*)
217 | * native declaration : line 199
218 | */
219 | double Clp_optimizationDirection(Pointer model);
220 | /**
221 | * Original signature : void Clp_setOptimizationDirection(Clp_Simplex*, double)
222 | * native declaration : line 200
223 | */
224 | void Clp_setOptimizationDirection(Pointer model, double value);
225 | /**
226 | * Original signature : double* Clp_primalRowSolution(Clp_Simplex*)
227 | * native declaration : line 202
228 | */
229 | Pointer Clp_primalRowSolution(Pointer model);
230 | /**
231 | * Original signature : double* Clp_primalColumnSolution(Clp_Simplex*)
232 | * native declaration : line 204
233 | */
234 | Pointer Clp_primalColumnSolution(Pointer model);
235 | /**
236 | * Original signature : double* Clp_dualRowSolution(Clp_Simplex*)
237 | * native declaration : line 206
238 | */
239 | Pointer Clp_dualRowSolution(Pointer model);
240 | /**
241 | * Original signature : double* Clp_dualColumnSolution(Clp_Simplex*)
242 | * native declaration : line 208
243 | */
244 | Pointer Clp_dualColumnSolution(Pointer model);
245 | /**
246 | * Original signature : double* Clp_rowLower(Clp_Simplex*)
247 | * native declaration : line 210
248 | */
249 | Pointer Clp_rowLower(Pointer model);
250 | /**
251 | * Original signature : double* Clp_rowUpper(Clp_Simplex*)
252 | * native declaration : line 212
253 | */
254 | Pointer Clp_rowUpper(Pointer model);
255 | /**
256 | * Original signature : double* Clp_objective(Clp_Simplex*)
257 | * native declaration : line 214
258 | */
259 | Pointer Clp_objective(Pointer model);
260 | /**
261 | * Original signature : double* Clp_columnLower(Clp_Simplex*)
262 | * native declaration : line 216
263 | */
264 | Pointer Clp_columnLower(Pointer model);
265 | /**
266 | * Original signature : double* Clp_columnUpper(Clp_Simplex*)
267 | * native declaration : line 218
268 | */
269 | Pointer Clp_columnUpper(Pointer model);
270 | /**
271 | * Original signature : int Clp_getNumElements(Clp_Simplex*)
272 | * native declaration : line 220
273 | */
274 | int Clp_getNumElements(Pointer model);
275 | /**
276 | * Original signature : CoinBigIndex* Clp_getVectorStarts(Clp_Simplex*)
277 | * native declaration : line 222
278 | */
279 | Pointer Clp_getVectorStarts(Pointer model);
280 | /**
281 | * Original signature : int* Clp_getIndices(Clp_Simplex*)
282 | * native declaration : line 224
283 | */
284 | Pointer Clp_getIndices(Pointer model);
285 | /**
286 | * Original signature : int* Clp_getVectorLengths(Clp_Simplex*)
287 | * native declaration : line 226
288 | */
289 | Pointer Clp_getVectorLengths(Pointer model);
290 | /**
291 | * Original signature : double* Clp_getElements(Clp_Simplex*)
292 | * native declaration : line 228
293 | */
294 | Pointer Clp_getElements(Pointer model);
295 | /**
296 | * Original signature : double Clp_objectiveValue(Clp_Simplex*)
297 | * native declaration : line 230
298 | */
299 | double Clp_objectiveValue(Pointer model);
300 | /**
301 | * Original signature : char* Clp_integerInformation(Clp_Simplex*)
302 | * native declaration : line 232
303 | */
304 | String Clp_integerInformation(Pointer model);
305 | /**
306 | * Original signature : double* Clp_infeasibilityRay(Clp_Simplex*)
307 | * native declaration : line 239
308 | */
309 | Pointer Clp_infeasibilityRay(Pointer model);
310 | /**
311 | * Original signature : double* Clp_unboundedRay(Clp_Simplex*)
312 | * native declaration : line 246
313 | */
314 | Pointer Clp_unboundedRay(Pointer model);
315 | /**
316 | * Original signature : void Clp_freeRay(Clp_Simplex*, double*)
317 | * native declaration : line 248
318 | */
319 | void Clp_freeRay(Pointer model, Pointer ray);
320 | /**
321 | * Original signature : int Clp_statusExists(Clp_Simplex*)
322 | * native declaration : line 250
323 | */
324 | int Clp_statusExists(Pointer model);
325 | /**
326 | * Original signature : char* Clp_statusArray(Clp_Simplex*)
327 | * native declaration : line 252
328 | */
329 | String Clp_statusArray(Pointer model);
330 | /**
331 | * Original signature : void Clp_copyinStatus(Clp_Simplex*, const unsigned char*)
332 | * native declaration : line 254
333 | */
334 | void Clp_copyinStatus(Pointer model, String statusArray);
335 | /**
336 | * Original signature : int Clp_getColumnStatus(Clp_Simplex*, int)
337 | * native declaration : line 258
338 | */
339 | int Clp_getColumnStatus(Pointer model, int sequence);
340 | /**
341 | * Original signature : int Clp_getRowStatus(Clp_Simplex*, int)
342 | * native declaration : line 260
343 | */
344 | int Clp_getRowStatus(Pointer model, int sequence);
345 | /**
346 | * Original signature : void Clp_setColumnStatus(Clp_Simplex*, int, int)
347 | * native declaration : line 262
348 | */
349 | void Clp_setColumnStatus(Pointer model, int sequence, int value);
350 | /**
351 | * Original signature : void Clp_setRowStatus(Clp_Simplex*, int, int)
352 | * native declaration : line 265
353 | */
354 | void Clp_setRowStatus(Pointer model, int sequence, int value);
355 | /**
356 | * Original signature : void Clp_setUserPointer(Clp_Simplex*, void*)
357 | * native declaration : line 269
358 | */
359 | void Clp_setUserPointer(Pointer model, Pointer pointer);
360 | /**
361 | * Original signature : void* Clp_getUserPointer(Clp_Simplex*)
362 | * native declaration : line 270
363 | */
364 | Pointer Clp_getUserPointer(Pointer model);
365 | /**
366 | * Original signature : void Clp_setLogLevel(Clp_Simplex*, int)
367 | * native declaration : line 288
368 | */
369 | void Clp_setLogLevel(Pointer model, int value);
370 | /**
371 | * Original signature : int Clp_logLevel(Clp_Simplex*)
372 | * native declaration : line 289
373 | */
374 | int Clp_logLevel(Pointer model);
375 | /**
376 | * Original signature : int Clp_lengthNames(Clp_Simplex*)
377 | * native declaration : line 291
378 | */
379 | int Clp_lengthNames(Pointer model);
380 | /**
381 | * Original signature : void Clp_rowName(Clp_Simplex*, int, char*)
382 | * native declaration : line 293
383 | */
384 | void Clp_rowName(Pointer model, int iRow, String name);
385 | /**
386 | * Original signature : void Clp_columnName(Clp_Simplex*, int, char*)
387 | * native declaration : line 295
388 | */
389 | void Clp_columnName(Pointer model, int iColumn, String name);
390 | /**
391 | * Original signature : int Clp_initialSolve(Clp_Simplex*)
392 | * native declaration : line 305
393 | */
394 | int Clp_initialSolve(Pointer model);
395 | /**
396 | * Original signature : int Clp_initialSolveWithOptions(Clp_Simplex*, Clp_Solve*)
397 | * native declaration : line 307
398 | */
399 | int Clp_initialSolveWithOptions(Pointer model, Pointer Clp_SolvePtr1);
400 | /**
401 | * Original signature : int Clp_initialDualSolve(Clp_Simplex*)
402 | * native declaration : line 309
403 | */
404 | int Clp_initialDualSolve(Pointer model);
405 | /**
406 | * Original signature : int Clp_initialPrimalSolve(Clp_Simplex*)
407 | * native declaration : line 311
408 | */
409 | int Clp_initialPrimalSolve(Pointer model);
410 | /**
411 | * Original signature : int Clp_initialBarrierSolve(Clp_Simplex*)
412 | * native declaration : line 313
413 | */
414 | int Clp_initialBarrierSolve(Pointer model);
415 | /**
416 | * Original signature : int Clp_initialBarrierNoCrossSolve(Clp_Simplex*)
417 | * native declaration : line 315
418 | */
419 | int Clp_initialBarrierNoCrossSolve(Pointer model);
420 | /**
421 | * Original signature : int Clp_dual(Clp_Simplex*, int)
422 | * native declaration : line 317
423 | */
424 | int Clp_dual(Pointer model, int ifValuesPass);
425 | /**
426 | * Original signature : int Clp_primal(Clp_Simplex*, int)
427 | * native declaration : line 319
428 | */
429 | int Clp_primal(Pointer model, int ifValuesPass);
430 | /**
431 | * Original signature : void Clp_idiot(Clp_Simplex*, int)
432 | * native declaration : line 322
433 | */
434 | void Clp_idiot(Pointer model, int tryhard);
435 | /**
436 | * Original signature : void Clp_scaling(Clp_Simplex*, int)
437 | * native declaration : line 325
438 | */
439 | void Clp_scaling(Pointer model, int mode);
440 | /**
441 | * Original signature : int Clp_scalingFlag(Clp_Simplex*)
442 | * native declaration : line 327
443 | */
444 | int Clp_scalingFlag(Pointer model);
445 | /**
446 | * Original signature : int Clp_crash(Clp_Simplex*, double, int)
447 | * native declaration : line 342
448 | */
449 | int Clp_crash(Pointer model, double gap, int pivot);
450 | /**
451 | * Original signature : int Clp_primalFeasible(Clp_Simplex*)
452 | * native declaration : line 349
453 | */
454 | int Clp_primalFeasible(Pointer model);
455 | /**
456 | * Original signature : int Clp_dualFeasible(Clp_Simplex*)
457 | * native declaration : line 351
458 | */
459 | int Clp_dualFeasible(Pointer model);
460 | /**
461 | * Original signature : double Clp_dualBound(Clp_Simplex*)
462 | * native declaration : line 353
463 | */
464 | double Clp_dualBound(Pointer model);
465 | /**
466 | * Original signature : void Clp_setDualBound(Clp_Simplex*, double)
467 | * native declaration : line 354
468 | */
469 | void Clp_setDualBound(Pointer model, double value);
470 | /**
471 | * Original signature : double Clp_infeasibilityCost(Clp_Simplex*)
472 | * native declaration : line 356
473 | */
474 | double Clp_infeasibilityCost(Pointer model);
475 | /**
476 | * Original signature : void Clp_setInfeasibilityCost(Clp_Simplex*, double)
477 | * native declaration : line 357
478 | */
479 | void Clp_setInfeasibilityCost(Pointer model, double value);
480 | /**
481 | * Original signature : int Clp_perturbation(Clp_Simplex*)
482 | * native declaration : line 366
483 | */
484 | int Clp_perturbation(Pointer model);
485 | /**
486 | * Original signature : void Clp_setPerturbation(Clp_Simplex*, int)
487 | * native declaration : line 367
488 | */
489 | void Clp_setPerturbation(Pointer model, int value);
490 | /**
491 | * Original signature : int Clp_algorithm(Clp_Simplex*)
492 | * native declaration : line 369
493 | */
494 | int Clp_algorithm(Pointer model);
495 | /**
496 | * Original signature : void Clp_setAlgorithm(Clp_Simplex*, int)
497 | * native declaration : line 371
498 | */
499 | void Clp_setAlgorithm(Pointer model, int value);
500 | /**
501 | * Original signature : double Clp_sumDualInfeasibilities(Clp_Simplex*)
502 | * native declaration : line 373
503 | */
504 | double Clp_sumDualInfeasibilities(Pointer model);
505 | /**
506 | * Original signature : int Clp_numberDualInfeasibilities(Clp_Simplex*)
507 | * native declaration : line 375
508 | */
509 | int Clp_numberDualInfeasibilities(Pointer model);
510 | /**
511 | * Original signature : double Clp_sumPrimalInfeasibilities(Clp_Simplex*)
512 | * native declaration : line 377
513 | */
514 | double Clp_sumPrimalInfeasibilities(Pointer model);
515 | /**
516 | * Original signature : int Clp_numberPrimalInfeasibilities(Clp_Simplex*)
517 | * native declaration : line 379
518 | */
519 | int Clp_numberPrimalInfeasibilities(Pointer model);
520 | /**
521 | * Original signature : int Clp_saveModel(Clp_Simplex*, const char*)
522 | * native declaration : line 386
523 | */
524 | int Clp_saveModel(Pointer model, String fileName);
525 | /**
526 | * Original signature : int Clp_restoreModel(Clp_Simplex*, const char*)
527 | * native declaration : line 389
528 | */
529 | int Clp_restoreModel(Pointer model, String fileName);
530 | /**
531 | * Original signature : void Clp_checkSolution(Clp_Simplex*)
532 | * native declaration : line 393
533 | */
534 | void Clp_checkSolution(Pointer model);
535 | /**
536 | * Original signature : int Clp_getNumRows(Clp_Simplex*)
537 | * native declaration : line 400
538 | */
539 | int Clp_getNumRows(Pointer model);
540 | /**
541 | * Original signature : int Clp_getNumCols(Clp_Simplex*)
542 | * native declaration : line 402
543 | */
544 | int Clp_getNumCols(Pointer model);
545 | /**
546 | * Original signature : int Clp_getIterationCount(Clp_Simplex*)
547 | * native declaration : line 404
548 | */
549 | int Clp_getIterationCount(Pointer model);
550 | /**
551 | * Original signature : int Clp_isAbandoned(Clp_Simplex*)
552 | * native declaration : line 406
553 | */
554 | int Clp_isAbandoned(Pointer model);
555 | /**
556 | * Original signature : int Clp_isProvenOptimal(Clp_Simplex*)
557 | * native declaration : line 408
558 | */
559 | int Clp_isProvenOptimal(Pointer model);
560 | /**
561 | * Original signature : int Clp_isProvenPrimalInfeasible(Clp_Simplex*)
562 | * native declaration : line 410
563 | */
564 | int Clp_isProvenPrimalInfeasible(Pointer model);
565 | /**
566 | * Original signature : int Clp_isProvenDualInfeasible(Clp_Simplex*)
567 | * native declaration : line 412
568 | */
569 | int Clp_isProvenDualInfeasible(Pointer model);
570 | /**
571 | * Original signature : int Clp_isPrimalObjectiveLimitReached(Clp_Simplex*)
572 | * native declaration : line 414
573 | */
574 | int Clp_isPrimalObjectiveLimitReached(Pointer model);
575 | /**
576 | * Original signature : int Clp_isDualObjectiveLimitReached(Clp_Simplex*)
577 | * native declaration : line 416
578 | */
579 | int Clp_isDualObjectiveLimitReached(Pointer model);
580 | /**
581 | * Original signature : int Clp_isIterationLimitReached(Clp_Simplex*)
582 | * native declaration : line 418
583 | */
584 | int Clp_isIterationLimitReached(Pointer model);
585 | /**
586 | * Original signature : double Clp_getObjSense(Clp_Simplex*)
587 | * native declaration : line 420
588 | */
589 | double Clp_getObjSense(Pointer model);
590 | /**
591 | * Original signature : void Clp_setObjSense(Clp_Simplex*, double)
592 | * native declaration : line 422
593 | */
594 | void Clp_setObjSense(Pointer model, double objsen);
595 | /**
596 | * Original signature : double* Clp_getRowActivity(Clp_Simplex*)
597 | * native declaration : line 424
598 | */
599 | Pointer Clp_getRowActivity(Pointer model);
600 | /**
601 | * Original signature : double* Clp_getColSolution(Clp_Simplex*)
602 | * native declaration : line 426
603 | */
604 | Pointer Clp_getColSolution(Pointer model);
605 | /**
606 | * Original signature : void Clp_setColSolution(Clp_Simplex*, const double*)
607 | * native declaration : line 427
608 | */
609 | void Clp_setColSolution(Pointer model, Pointer input);
610 | /**
611 | * Original signature : double* Clp_getRowPrice(Clp_Simplex*)
612 | * native declaration : line 429
613 | */
614 | Pointer Clp_getRowPrice(Pointer model);
615 | /**
616 | * Original signature : double* Clp_getReducedCost(Clp_Simplex*)
617 | * native declaration : line 431
618 | */
619 | Pointer Clp_getReducedCost(Pointer model);
620 | /**
621 | * Original signature : double* Clp_getRowLower(Clp_Simplex*)
622 | * native declaration : line 433
623 | */
624 | Pointer Clp_getRowLower(Pointer model);
625 | /**
626 | * Original signature : double* Clp_getRowUpper(Clp_Simplex*)
627 | * native declaration : line 435
628 | */
629 | Pointer Clp_getRowUpper(Pointer model);
630 | /**
631 | * Original signature : double* Clp_getObjCoefficients(Clp_Simplex*)
632 | * native declaration : line 437
633 | */
634 | Pointer Clp_getObjCoefficients(Pointer model);
635 | /**
636 | * Original signature : double* Clp_getColLower(Clp_Simplex*)
637 | * native declaration : line 439
638 | */
639 | Pointer Clp_getColLower(Pointer model);
640 | /**
641 | * Original signature : double* Clp_getColUpper(Clp_Simplex*)
642 | * native declaration : line 441
643 | */
644 | Pointer Clp_getColUpper(Pointer model);
645 | /**
646 | * Original signature : double Clp_getObjValue(Clp_Simplex*)
647 | * native declaration : line 443
648 | */
649 | double Clp_getObjValue(Pointer model);
650 | /**
651 | * Original signature : void Clp_printModel(Clp_Simplex*, const char*)
652 | * native declaration : line 445
653 | */
654 | void Clp_printModel(Pointer model, String prefix);
655 | /**
656 | * Original signature : double Clp_getSmallElementValue(Clp_Simplex*)
657 | * native declaration : line 448
658 | */
659 | double Clp_getSmallElementValue(Pointer model);
660 | /**
661 | * Original signature : void Clp_setSmallElementValue(Clp_Simplex*, double)
662 | * native declaration : line 449
663 | */
664 | void Clp_setSmallElementValue(Pointer model, double value);
665 | /**
666 | * Original signature : void ClpSolve_setSpecialOption(Clp_Solve*, int, int, int)
667 | * native declaration : line 456
668 | */
669 | void ClpSolve_setSpecialOption(Pointer Clp_SolvePtr1, int which, int value, int extraInfo);
670 | /**
671 | * Original signature : int ClpSolve_getSpecialOption(Clp_Solve*, int)
672 | * native declaration : line 457
673 | */
674 | int ClpSolve_getSpecialOption(Pointer Clp_SolvePtr1, int which);
675 | /**
676 | * Original signature : void ClpSolve_setSolveType(Clp_Solve*, int, int)
677 | * native declaration : line 468
678 | */
679 | void ClpSolve_setSolveType(Pointer Clp_SolvePtr1, int method, int extraInfo);
680 | /**
681 | * Original signature : int ClpSolve_getSolveType(Clp_Solve*)
682 | * native declaration : line 469
683 | */
684 | int ClpSolve_getSolveType(Pointer Clp_SolvePtr1);
685 | /**
686 | * Original signature : void ClpSolve_setPresolveType(Clp_Solve*, int, int)
687 | * native declaration : line 477
688 | */
689 | void ClpSolve_setPresolveType(Pointer Clp_SolvePtr1, int amount, int extraInfo);
690 | /**
691 | * Original signature : int ClpSolve_getPresolveType(Clp_Solve*)
692 | * native declaration : line 478
693 | */
694 | int ClpSolve_getPresolveType(Pointer Clp_SolvePtr1);
695 | /**
696 | * Original signature : int ClpSolve_getPresolvePasses(Clp_Solve*)
697 | * native declaration : line 480
698 | */
699 | int ClpSolve_getPresolvePasses(Pointer Clp_SolvePtr1);
700 | /**
701 | * Original signature : int ClpSolve_getExtraInfo(Clp_Solve*, int)
702 | * native declaration : line 481
703 | */
704 | int ClpSolve_getExtraInfo(Pointer Clp_SolvePtr1, int which);
705 | /**
706 | * Original signature : void ClpSolve_setInfeasibleReturn(Clp_Solve*, int)
707 | * native declaration : line 482
708 | */
709 | void ClpSolve_setInfeasibleReturn(Pointer Clp_SolvePtr1, int trueFalse);
710 | /**
711 | * Original signature : int ClpSolve_infeasibleReturn(Clp_Solve*)
712 | * native declaration : line 483
713 | */
714 | int ClpSolve_infeasibleReturn(Pointer Clp_SolvePtr1);
715 | /**
716 | * Original signature : int ClpSolve_doDual(Clp_Solve*)
717 | * native declaration : line 485
718 | */
719 | int ClpSolve_doDual(Pointer Clp_SolvePtr1);
720 | /**
721 | * Original signature : void ClpSolve_setDoDual(Clp_Solve*, int)
722 | * native declaration : line 486
723 | */
724 | void ClpSolve_setDoDual(Pointer Clp_SolvePtr1, int doDual);
725 | /**
726 | * Original signature : int ClpSolve_doSingleton(Clp_Solve*)
727 | * native declaration : line 488
728 | */
729 | int ClpSolve_doSingleton(Pointer Clp_SolvePtr1);
730 | /**
731 | * Original signature : void ClpSolve_setDoSingleton(Clp_Solve*, int)
732 | * native declaration : line 489
733 | */
734 | void ClpSolve_setDoSingleton(Pointer Clp_SolvePtr1, int doSingleton);
735 | /**
736 | * Original signature : int ClpSolve_doDoubleton(Clp_Solve*)
737 | * native declaration : line 491
738 | */
739 | int ClpSolve_doDoubleton(Pointer Clp_SolvePtr1);
740 | /**
741 | * Original signature : void ClpSolve_setDoDoubleton(Clp_Solve*, int)
742 | * native declaration : line 492
743 | */
744 | void ClpSolve_setDoDoubleton(Pointer Clp_SolvePtr1, int doDoubleton);
745 | /**
746 | * Original signature : int ClpSolve_doTripleton(Clp_Solve*)
747 | * native declaration : line 494
748 | */
749 | int ClpSolve_doTripleton(Pointer Clp_SolvePtr1);
750 | /**
751 | * Original signature : void ClpSolve_setDoTripleton(Clp_Solve*, int)
752 | * native declaration : line 495
753 | */
754 | void ClpSolve_setDoTripleton(Pointer Clp_SolvePtr1, int doTripleton);
755 | /**
756 | * Original signature : int ClpSolve_doTighten(Clp_Solve*)
757 | * native declaration : line 497
758 | */
759 | int ClpSolve_doTighten(Pointer Clp_SolvePtr1);
760 | /**
761 | * Original signature : void ClpSolve_setDoTighten(Clp_Solve*, int)
762 | * native declaration : line 498
763 | */
764 | void ClpSolve_setDoTighten(Pointer Clp_SolvePtr1, int doTighten);
765 | /**
766 | * Original signature : int ClpSolve_doForcing(Clp_Solve*)
767 | * native declaration : line 500
768 | */
769 | int ClpSolve_doForcing(Pointer Clp_SolvePtr1);
770 | /**
771 | * Original signature : void ClpSolve_setDoForcing(Clp_Solve*, int)
772 | * native declaration : line 501
773 | */
774 | void ClpSolve_setDoForcing(Pointer Clp_SolvePtr1, int doForcing);
775 | /**
776 | * Original signature : int ClpSolve_doImpliedFree(Clp_Solve*)
777 | * native declaration : line 503
778 | */
779 | int ClpSolve_doImpliedFree(Pointer Clp_SolvePtr1);
780 | /**
781 | * Original signature : void ClpSolve_setDoImpliedFree(Clp_Solve*, int)
782 | * native declaration : line 504
783 | */
784 | void ClpSolve_setDoImpliedFree(Pointer Clp_SolvePtr1, int doImpliedFree);
785 | /**
786 | * Original signature : int ClpSolve_doDupcol(Clp_Solve*)
787 | * native declaration : line 506
788 | */
789 | int ClpSolve_doDupcol(Pointer Clp_SolvePtr1);
790 | /**
791 | * Original signature : void ClpSolve_setDoDupcol(Clp_Solve*, int)
792 | * native declaration : line 507
793 | */
794 | void ClpSolve_setDoDupcol(Pointer Clp_SolvePtr1, int doDupcol);
795 | /**
796 | * Original signature : int ClpSolve_doDuprow(Clp_Solve*)
797 | * native declaration : line 509
798 | */
799 | int ClpSolve_doDuprow(Pointer Clp_SolvePtr1);
800 | /**
801 | * Original signature : void ClpSolve_setDoDuprow(Clp_Solve*, int)
802 | * native declaration : line 510
803 | */
804 | void ClpSolve_setDoDuprow(Pointer Clp_SolvePtr1, int doDuprow);
805 | /**
806 | * Original signature : int ClpSolve_doSingletonColumn(Clp_Solve*)
807 | * native declaration : line 512
808 | */
809 | int ClpSolve_doSingletonColumn(Pointer Clp_SolvePtr1);
810 | /**
811 | * Original signature : void ClpSolve_setDoSingletonColumn(Clp_Solve*, int)
812 | * native declaration : line 513
813 | */
814 | void ClpSolve_setDoSingletonColumn(Pointer Clp_SolvePtr1, int doSingleton);
815 | /**
816 | * Original signature : int ClpSolve_presolveActions(Clp_Solve*)
817 | * native declaration : line 515
818 | */
819 | int ClpSolve_presolveActions(Pointer Clp_SolvePtr1);
820 | /**
821 | * Original signature : void ClpSolve_setPresolveActions(Clp_Solve*, int)
822 | * native declaration : line 516
823 | */
824 | void ClpSolve_setPresolveActions(Pointer Clp_SolvePtr1, int action);
825 | /**
826 | * Original signature : int ClpSolve_substitution(Clp_Solve*)
827 | * native declaration : line 518
828 | */
829 | int ClpSolve_substitution(Pointer Clp_SolvePtr1);
830 | /**
831 | * Original signature : void ClpSolve_setSubstitution(Clp_Solve*, int)
832 | * native declaration : line 519
833 | */
834 | void ClpSolve_setSubstitution(Pointer Clp_SolvePtr1, int value);
835 |
836 |
837 | }
--------------------------------------------------------------------------------
/src/main/java/com/quantego/clp/CLPObjective.java:
--------------------------------------------------------------------------------
1 | package com.quantego.clp;
2 |
3 | /**
4 | * Holds a constraint of a {@link CLP} model.
5 | * @author Nils Loehndorf
6 | *
7 | */
8 | public class CLPObjective {
9 |
10 | CLP _solver;
11 |
12 | CLPObjective(CLP solver) {
13 | _solver = solver;
14 | }
15 |
16 | /**
17 | * Set the coefficient of the given variable.
18 | * @param variable
19 | * @param value
20 | * @return builder
21 | */
22 | public CLPObjective setTerm(CLPVariable variable, double value) {
23 | _solver.setObjectiveCoefficient(variable, value);
24 | return this;
25 | }
26 |
27 | /**
28 | * Set the quadratic coefficient of the given variable.
29 | * @param variable
30 | * @param value
31 | * @return builder
32 | */
33 | public CLPObjective setQuadTerm(CLPVariable variable, double value) {
34 | _solver.setQuadraticObjectiveCoefficient(variable, value);
35 | return this;
36 | }
37 |
38 | /**
39 | * Set the coefficient of the given variable.
40 | * @param variable
41 | * @param value
42 | * @return builder
43 | */
44 | public CLPObjective setTerm(double value) {
45 | _solver.setObjectiveOffset(value);
46 | return this;
47 | }
48 |
49 | /**
50 | *
51 | * @return the objective value.
52 | */
53 | public double getValue() {
54 | return _solver.getObjectiveValue();
55 | }
56 |
57 |
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/com/quantego/clp/CLPVariable.java:
--------------------------------------------------------------------------------
1 | package com.quantego.clp;
2 |
3 | /**
4 | * Holds a variable of a {@link CLP} model.
5 | * @author Nils Loehndorf
6 | *
7 | */
8 | public class CLPVariable {
9 |
10 | CLP _solver;
11 | int _index;
12 |
13 | CLPVariable(CLP solver, int index) {
14 | _solver = solver;
15 | _index = index;
16 | }
17 |
18 | /**
19 | * Variable name
20 | * @param name
21 | * @return builder
22 | */
23 | public CLPVariable name(String name) {
24 | _solver.setVariableName(this, name);
25 | return this;
26 | }
27 |
28 | /**
29 | * Objective coefficient of this variable.
30 | * @param value
31 | * @return builder
32 | */
33 | public CLPVariable obj(double value) {
34 | _solver.setObjectiveCoefficient(this,value);
35 | return this;
36 | }
37 |
38 | /**
39 | * Quadratic objective coefficient of this variable.
40 | * @param value
41 | * @return builder
42 | */
43 | public CLPVariable quad(double value) {
44 | _solver.setQuadraticObjectiveCoefficient(this,value);
45 | return this;
46 | }
47 |
48 | /**
49 | * Set variable bounds. By default variables are 0 <= x <= inf.
50 | * @param lb
51 | * @param ub
52 | * @return builder
53 | */
54 | public CLPVariable bounds(double lb, double ub) {
55 | _solver.setVariableBounds(this, lb, ub);
56 | return this;
57 | }
58 |
59 | /**
60 | * Set lower bound. By default variables are 0 <= x <= inf.
61 | * @param lb
62 | * @param ub
63 | * @return builder
64 | */
65 | public CLPVariable lb(double value) {
66 | _solver.setVariableLowerBound(this, value);
67 | return this;
68 | }
69 |
70 | /**
71 | * Set upper bound. By default variables are 0 <= x <= inf.
72 | * @param lb
73 | * @param ub
74 | * @return builder
75 | */
76 | public CLPVariable ub(double value) {
77 | _solver.setVariableUpperBound(this, value);
78 | return this;
79 | }
80 |
81 | /**
82 | * Defines this vaiable as free, -inf <= x <= inf.
83 | * @return builder
84 | */
85 | public CLPVariable free() {
86 | _solver.setVariableBounds(this, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
87 | return this;
88 | }
89 |
90 | /**
91 | *
92 | * @return the solution value
93 | */
94 | public double getSolution() {
95 | return _solver.getSolution(this);
96 | }
97 |
98 | @Override
99 | public String toString() {
100 | return _solver.getVariableName(_index);
101 | }
102 |
103 | }
104 |
--------------------------------------------------------------------------------
/src/main/java/com/quantego/clp/CLPVariableSet.java:
--------------------------------------------------------------------------------
1 | package com.quantego.clp;
2 |
3 |
4 | /**
5 | * Builder class for a set of {@link CLPVariable} with identical parameters.
6 | * @author Nils Loehndorf
7 | *
8 | */
9 | public class CLPVariableSet {
10 |
11 | CLP _solver;
12 | int _size;
13 | double _lb;
14 | double _ub = Double.POSITIVE_INFINITY;
15 | double _obj;
16 | double _qobj;
17 | String _name;
18 |
19 | CLPVariableSet(CLP solver, int size) {
20 | if (size<1) throw new IllegalArgumentException("The size of the set of variables must be greater than 1.");
21 | _solver = solver;
22 | _size = size;
23 | }
24 |
25 | /**
26 | * Common name of these variables. An underscore followed by the index will be added automaticall.y
27 | * @param name
28 | * @return builder
29 | */
30 | public CLPVariableSet name(String name) {
31 | _name = name;
32 | return this;
33 | }
34 |
35 | /**
36 | * Objective coefficient for these variables.
37 | * @param value
38 | * @return builder
39 | */
40 | public CLPVariableSet obj(double value) {
41 | _obj = value;
42 | return this;
43 | }
44 |
45 | /**
46 | * Quadratic objective coefficient for these variables.
47 | * @param value
48 | * @return builder
49 | */
50 | public CLPVariableSet quad(double value) {
51 | _qobj = value;
52 | return this;
53 | }
54 |
55 | /**
56 | * Lower bounds of these variables. By default variables are 0 <= x <= inf.
57 | * @param lb
58 | * @param ub
59 | * @return builder
60 | */
61 | public CLPVariableSet lb(double value) {
62 | _lb = value;
63 | return this;
64 | }
65 |
66 | /**
67 | * Upper bounds of these variables. By default variables are 0 <= x <= inf.
68 | * @param lb
69 | * @param ub
70 | * @return builder
71 | */
72 | public CLPVariableSet ub(double value) {
73 | _ub = value;
74 | return this;
75 | }
76 |
77 | /**
78 | * Defines this vaiable as free, -inf <= x <= inf.
79 | * @return builder
80 | */
81 | public CLPVariableSet free() {
82 | _lb = Double.NEGATIVE_INFINITY;
83 | _ub = Double.POSITIVE_INFINITY;
84 | return this;
85 | }
86 |
87 | /**
88 | * @return a list of {@link CLPVariable} with the given parameters.
89 | */
90 | public CLPVariable[] build() {
91 | CLPVariable[] set = new CLPVariable[_size];
92 | for (int i=0; i<_size; i++) {
93 | CLPVariable var = _solver.addVariable();
94 | if (_name!=null) var.name(_name+"_"+i);
95 | if (_lb!=0)var.lb(_lb);
96 | if (_ub!=Double.POSITIVE_INFINITY) var.ub(_ub);
97 | if (_obj!=0) var.obj(_obj);
98 | if (_qobj!=0) var.quad(_qobj);
99 | set[i] = var;
100 | }
101 | return set;
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/src/main/java/com/quantego/clp/NativeLoader.java:
--------------------------------------------------------------------------------
1 | package com.quantego.clp;
2 |
3 | import jnr.ffi.LibraryLoader;
4 |
5 | import java.io.File;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.io.OutputStream;
10 |
11 | class NativeLoader {
12 |
13 | static String prefix = "CLPExtractedLib";
14 | static String library = "clp-1.16.15";
15 | static String pathSep = System.getProperty("file.separator");
16 |
17 | public static void main(String... args) {
18 | CLP clp = new CLP();
19 | CLPVariable x1 = clp.addVariable();
20 | clp.createExpression().add(4).add(-2, x1).asObjective();
21 | clp.createExpression().add(x1).leq(2);
22 | CLPVariable x2 = clp.addVariable();
23 | clp.createExpression().add(6).add(-2, x2).asObjective();
24 | clp.createExpression().add(x2).leq(3);
25 | clp.minimize();
26 | System.out.println(clp.toString());
27 | }
28 |
29 | static CLPNative load() {
30 | File tempDir = createTempDir(prefix);
31 | String osArch = System.getProperty("os.arch").toLowerCase();
32 | String osName = System.getProperty("os.name").toLowerCase();
33 | String path;
34 | String[] libs;
35 | String selectedArch = null;
36 | String coinUtils = null;
37 | if (osName.startsWith("mac")) {
38 | if (osArch.equals("aarch64")) {
39 | path = library+"/darwin-aarch64/";
40 | libs = new String[]{"libCoinUtils.3.dylib","libClp.dylib"};
41 | coinUtils = "CoinUtils.3";
42 | selectedArch = "mac-aarch64";
43 | }
44 | else {
45 | path = library+"/darwin-x86/";
46 | libs = new String[]{"libCoinUtils.3.dylib","libClp.dylib"};
47 | coinUtils = "CoinUtils.3";
48 | selectedArch = "mac-x86_64";
49 | }
50 | } else if (osName.startsWith("win") && osArch.contains("64")) {
51 | path = library+"/win64/";
52 | libs = new String[]{"libgcc_s_seh-1.dll","libstdc++-6.dll","libCoinUtils-3.dll","Clp.dll"};
53 | coinUtils = "libCoinUtils-3.dll";
54 | selectedArch = "win-x86_64";
55 | } else if (osName.startsWith("linux")) {
56 | if (osArch.equals("aarch64")) {
57 | path = library + "/linux-aarch64/";
58 | libs = new String[]{"libCoinUtils.so.3", "libClp.so"};
59 | coinUtils = "CoinUtils";
60 | //BridJ.addNativeLibraryDependencies("Clp", new String[]{"CoinUtils"});
61 | selectedArch = "linux-aarch64";
62 | } else {
63 | path = library+"/linux-x86/";
64 | libs = new String[]{"libCoinUtils.so.3","libClp.so"};
65 | coinUtils = "CoinUtils";
66 | //BridJ.addNativeLibraryDependencies("Clp", new String[]{"CoinUtils"});
67 | selectedArch = "linux-x86_64";
68 | }
69 | } else {
70 | throw new UnsupportedOperationException("Platform " + osName + ":" + osArch + " not supported");
71 | }
72 | for (String lib : libs)
73 | loadLibrary(tempDir,path,lib);
74 | return LibraryLoader
75 | .create(CLPNative.class)
76 | .search(tempDir.getAbsolutePath())
77 | .library(coinUtils)
78 | .load("Clp");
79 | }
80 |
81 | public static File createTempDir(String prefix) {
82 | String tmpDirName = System.getProperty("java.io.tmpdir");
83 | if (tmpDirName.endsWith(pathSep))
84 | tmpDirName += prefix+System.nanoTime()+pathSep;
85 | else
86 | tmpDirName += pathSep+prefix+System.nanoTime()+pathSep;
87 | File dir = new File(tmpDirName);
88 | dir.mkdir();
89 | dir.deleteOnExit();
90 | return dir;
91 | }
92 |
93 | public static void loadLibrary(File dir, String path, String name) {
94 | InputStream in = null;
95 | OutputStream out = null;
96 | try {
97 | in = NativeLoader.class.getClassLoader().getResourceAsStream(path+name);
98 | File file = new File(dir, name);
99 | file.deleteOnExit();
100 | file.createNewFile();
101 | out = new FileOutputStream(file);
102 | int cnt;
103 | byte buf[] = new byte[16 * 1024];
104 | while ((cnt = in.read(buf)) >= 1) {
105 | out.write(buf, 0, cnt);
106 | }
107 | } catch (IOException e) {
108 | e.printStackTrace();
109 | } finally {
110 | if (in != null) {
111 | try {
112 | in.close();
113 | } catch (IOException ignore) {
114 | }
115 | }
116 | if (out != null) {
117 | try {
118 | out.close();
119 | } catch (IOException ignore) {
120 | }
121 | }
122 | }
123 | }
124 |
125 | }
126 |
--------------------------------------------------------------------------------
/src/main/javadoc/overview.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Overview
4 |
Installation
5 |
Download the latest jar file and add it to your build path, or clone the source into a local git repository.
6 |
Usage
7 |
8 | To build a new linear programming model, create a {@link com.quantego.clp.CLP} instance. Instances of all other classes are created from there. Builders are provided to get as close as possible to algebraic modeling.
9 |
10 |
11 | To get started quickly, check out the following functions:
12 |
13 |
{@link com.quantego.clp.CLP#addVariable()} adds a {@link com.quantego.clp.CLPVariable} to the model.
14 |
{@link com.quantego.clp.CLPVariable} serves as a builder for variables. For example {@link com.quantego.clp.CLPVariable#ub(double)} adds the variable upper bound, or {@link com.quantego.clp.CLPVariable#obj(double)} sets the objective coefficient.
15 |
{@link com.quantego.clp.CLP#createExpression()} provides a builder to create linear expressions. Simply call {@link com.quantego.clp.CLPExpression#leq(double)} to add a {@link com.quantego.clp.CLPExpression} as less-or-equal {@link com.quantego.clp.CLPConstraint}.
16 |
17 |
18 |
19 | {@link com.quantego.clp.CLP#toString()} returns the complete model in .lp format, for cross-validation. To solve the model use {@link com.quantego.clp.CLP#minimize()} or {@link com.quantego.clp.CLP#maximize()}.
20 |
21 |
22 | The solution can be obtained via {@link com.quantego.clp.CLPVariable#getSolution()}.
23 |