├── .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 ![y \in \mathbb{R}](https://latex.codecogs.com/gif.latex?y%20%5Cin%20%5Cmathbb%7BR%7D), 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, ![3x + 4y \leq 10](https://latex.codecogs.com/gif.latex?3x+4y%20%5Cleq%2010) 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 |

24 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/resources/clp-1.16.15/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantego/clp-java/40ad15b1faa294a9450399a3beaf6305d54ed7e2/src/main/resources/clp-1.16.15/.DS_Store -------------------------------------------------------------------------------- /src/main/resources/clp-1.16.15/darwin-aarch64/libClp.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantego/clp-java/40ad15b1faa294a9450399a3beaf6305d54ed7e2/src/main/resources/clp-1.16.15/darwin-aarch64/libClp.dylib -------------------------------------------------------------------------------- /src/main/resources/clp-1.16.15/darwin-aarch64/libCoinUtils.3.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantego/clp-java/40ad15b1faa294a9450399a3beaf6305d54ed7e2/src/main/resources/clp-1.16.15/darwin-aarch64/libCoinUtils.3.dylib -------------------------------------------------------------------------------- /src/main/resources/clp-1.16.15/darwin-x86/libClp.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantego/clp-java/40ad15b1faa294a9450399a3beaf6305d54ed7e2/src/main/resources/clp-1.16.15/darwin-x86/libClp.dylib -------------------------------------------------------------------------------- /src/main/resources/clp-1.16.15/darwin-x86/libCoinUtils.3.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantego/clp-java/40ad15b1faa294a9450399a3beaf6305d54ed7e2/src/main/resources/clp-1.16.15/darwin-x86/libCoinUtils.3.dylib -------------------------------------------------------------------------------- /src/main/resources/clp-1.16.15/linux-aarch64/libClp.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantego/clp-java/40ad15b1faa294a9450399a3beaf6305d54ed7e2/src/main/resources/clp-1.16.15/linux-aarch64/libClp.so -------------------------------------------------------------------------------- /src/main/resources/clp-1.16.15/linux-aarch64/libCoinUtils.so.3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantego/clp-java/40ad15b1faa294a9450399a3beaf6305d54ed7e2/src/main/resources/clp-1.16.15/linux-aarch64/libCoinUtils.so.3 -------------------------------------------------------------------------------- /src/main/resources/clp-1.16.15/linux-x86/libClp.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantego/clp-java/40ad15b1faa294a9450399a3beaf6305d54ed7e2/src/main/resources/clp-1.16.15/linux-x86/libClp.so -------------------------------------------------------------------------------- /src/main/resources/clp-1.16.15/linux-x86/libCoinUtils.so.3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantego/clp-java/40ad15b1faa294a9450399a3beaf6305d54ed7e2/src/main/resources/clp-1.16.15/linux-x86/libCoinUtils.so.3 -------------------------------------------------------------------------------- /src/main/resources/clp-1.16.15/win64/Clp.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantego/clp-java/40ad15b1faa294a9450399a3beaf6305d54ed7e2/src/main/resources/clp-1.16.15/win64/Clp.dll -------------------------------------------------------------------------------- /src/main/resources/clp-1.16.15/win64/libCoinUtils-3.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantego/clp-java/40ad15b1faa294a9450399a3beaf6305d54ed7e2/src/main/resources/clp-1.16.15/win64/libCoinUtils-3.dll -------------------------------------------------------------------------------- /src/main/resources/clp-1.16.15/win64/libgcc_s_seh-1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantego/clp-java/40ad15b1faa294a9450399a3beaf6305d54ed7e2/src/main/resources/clp-1.16.15/win64/libgcc_s_seh-1.dll -------------------------------------------------------------------------------- /src/main/resources/clp-1.16.15/win64/libstdc++-6.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quantego/clp-java/40ad15b1faa294a9450399a3beaf6305d54ed7e2/src/main/resources/clp-1.16.15/win64/libstdc++-6.dll -------------------------------------------------------------------------------- /src/test/java/com/quantego/clp/CLPTest.java: -------------------------------------------------------------------------------- 1 | package com.quantego.clp; 2 | 3 | import jnr.ffi.Pointer; 4 | import jnr.ffi.Runtime; 5 | import org.junit.Test; 6 | 7 | import java.io.File; 8 | import java.net.URL; 9 | import java.util.Random; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | 14 | public class CLPTest { 15 | 16 | @Test 17 | public void testPointer() { 18 | double[] arr = new double[]{1,2,3}; 19 | Pointer p = CLP.arrayToPointer(arr); 20 | assertEquals(p.getDouble(0),0.,1); 21 | assertEquals(p.getDouble(1),1.,2); 22 | assertEquals(p.getDouble(2),2.,3); 23 | Pointer p2 = CLP.copyOfDoublePointer(p,3); 24 | assertEquals(p2.getDouble(0),0.,1); 25 | assertEquals(p2.getDouble(1),1.,2); 26 | assertEquals(p2.getDouble(2),2.,3); 27 | } 28 | 29 | @Test 30 | public void testObjective() { 31 | CLPNative NATIVE = NativeLoader.load(); 32 | Runtime RUNTIME = Runtime.getSystemRuntime(); 33 | Pointer model = NATIVE.Clp_newModel(); 34 | NATIVE.Clp_addColumns(model, 35 | 2, 36 | CLP.arrayToPointer(new double[]{0.0,0.0}), 37 | CLP.arrayToPointer(new double[]{10.0,10.0}), 38 | CLP.arrayToPointer(new double[]{1.8,3.6}), 39 | CLP.arrayToPointer(new double[]{0}), 40 | CLP.arrayToPointer(new double[0]), 41 | CLP.arrayToPointer(new double[0])); 42 | Pointer p = NATIVE.Clp_getObjCoefficients(model); 43 | assertEquals(p.getDouble(0),1.8,1e-10); 44 | assertEquals(p.getDouble(1*Double.BYTES),3.6,1e-10); 45 | } 46 | 47 | @Test 48 | public void testBuffers() { 49 | CLP model = new CLP().buffer(10).presolve(false).maxIterations(1); 50 | int size1 = 10; 51 | int size2 = 1000; 52 | Random gen = new Random(11); 53 | CLPVariable[][] massTransport = new CLPVariable[size1][size2]; 54 | for (int i=0; i