COPT from Java with ojAlgo
COPT (Cardinal Optimizer) is a commercial solver for LP, QP, MIP and more. ojAlgo's modelling API, ExpressionsBasedModel, builds LP, QP and MIP models in Java and other JVM languages such as Kotlin and Scala. ojAlgo solves them with its own pure Java solvers, and the integration module ojalgo-copt lets the same models be solved by COPT instead, without changing the model code. For an application that already uses ojAlgo, moving to COPT takes two dependencies and one line of code.
Upgrading an existing ojAlgo application
When an application's models outgrow ojAlgo's built-in solvers, they can be handed to COPT without rewriting them:
- Add
ojalgo-coptand COPT'scopt.jarto the project, as described below. Keep your existing ojAlgo dependency. - Register COPT once, at start-up:
ExpressionsBasedModel.addIntegration(SolverCOPT.INTEGRATION); - Nothing else changes. Models are built, solved and read as before, and the time limit, gap tolerance and number of threads set in
model.optionsare passed on to COPT.
To try COPT on one model first, leave out the registration and call model.maximise(SolverCOPT.INTEGRATION) (or minimise) on that model. The same model solved with model.maximise() uses ojAlgo's own solvers, so the two results can be compared directly.
Installation
Prerequisites. Java 11 or later, and COPT installed and licensed as described in COPT's installation guide. ojalgo-copt is built and tested with COPT 8.0.
Add the integration to your project. The module is on Maven Central and brings ojAlgo with it:
<dependency>
<groupId>org.ojalgo</groupId>
<artifactId>ojalgo-copt</artifactId>
<version>1.1.0</version>
</dependency>
ojAlgo is released more often than the integration. To use a newer ojAlgo than the one ojalgo-copt was built with, declare ojAlgo as well; the version you declare takes precedence:
<dependency>
<groupId>org.ojalgo</groupId>
<artifactId>ojalgo</artifactId>
<version>57.4.0</version>
</dependency>
Add the COPT Java package. The COPT Java API, copt.jar, is part of the COPT installation and is found in $COPT_HOME/lib. It is not on Maven Central, and ojalgo-copt does not bring it with it. Install it in your local Maven repository, using your COPT version:
mvn install:install-file -Dfile=$COPT_HOME/lib/copt.jar \
-DgroupId=copt -DartifactId=copt -Dversion=8.0.7 -Dpackaging=jar
and add it to your project:
<dependency>
<groupId>copt</groupId>
<artifactId>copt</artifactId>
<version>8.0.7</version>
</dependency>
Native libraries. At run time the JVM must find COPT's native libraries. Pass the library directory to the JVM:
-Djava.library.path=$COPT_HOME/lib
Example
Register COPT once; from then on ExpressionsBasedModel uses it to solve the models.
import org.ojalgo.optimisation.*;
import org.ojalgo.optimisation.solver.copt.SolverCOPT;
ExpressionsBasedModel.addIntegration(SolverCOPT.INTEGRATION);
ExpressionsBasedModel model = new ExpressionsBasedModel();
// Whole units only; the weight is the profit per unit
Variable chairs = model.newVariable("Chairs").lower(0).integer().weight(45);
Variable tables = model.newVariable("Tables").lower(0).integer().weight(80);
// Making any tables means running the table line, at a fixed cost of 900
Variable tableLine = model.newVariable("TableLine").binary().weight(-900);
model.newExpression("MachineHours").upper(400).set(chairs, 2).set(tables, 5);
model.newExpression("Wood").upper(450).set(chairs, 4).set(tables, 3);
model.newExpression("LineCapacity").upper(0).set(tables, 1).set(tableLine, -60);
Optimisation.Result result = model.maximise(); // OPTIMAL 6475.0: 75 chairs, 50 tables
Models can also be read from MPS or LP files with ExpressionsBasedModel.parse(file).
Parameters
ojalgo-copt passes these model options on to COPT. COPT logging is switched off.
ojAlgo option (model.options) |
COPT parameter |
|---|---|
time_suffice / time_abort (the shorter one) |
TimeLimit |
parallelism(n) |
Threads |
feasibility, when changed from the default |
FeasTol, IntTol |
| the integer strategy's gap tolerance, when changed | RelGap, AbsGap |
Any other COPT parameter is set with a configurator: extend SolverCOPT.Configurator, override configure, and register it.
import copt.*;
import org.ojalgo.optimisation.Optimisation;
import org.ojalgo.optimisation.solver.copt.SolverCOPT;
public class MyCOPTConfigurator extends SolverCOPT.Configurator {
@Override
protected void configure(final copt.Model model, final Optimisation.Options options) {
super.configure(model, options);
try {
model.setIntParam(IntParam.Logging, 1);
model.setDblParam(DblParam.RelGap, 1e-6);
} catch (CoptException cause) {
throw new RuntimeException(cause);
}
}
}
ExpressionsBasedModel.setConfigurator(new MyCOPTConfigurator());
More
- Java LP, QP and MIP Solvers: ojAlgo's own solvers, and the other solver integrations
- Optimisation Cookbook: complete models for common problem shapes
- ojalgo-copt on Maven Central
- Questions and support: Support & Community