FICO Xpress from Java with ojAlgo
FICO Xpress is a high-performance commercial solver for LP, QP, MIP and more. ojAlgo is an open source, pure Java library for mathematical optimisation, with a modelling API, ExpressionsBasedModel. The integration module ojalgo-xpress lets models built with ojAlgo be solved by Xpress — whether you already use ojAlgo and want Xpress's solving power, or are looking for a convenient way to use Xpress from Java.
Already using ojAlgo: upgrade to Xpress
Switching to Xpress takes two dependencies and one line of code. You need Xpress installed and licensed. Then:
-
Add two dependencies:
ojalgo-xpress, and Xpress's own Java package,xprs.jar, which comes with the Xpress installation (details below). Keep your existing ojAlgo dependency.<dependency> <groupId>org.ojalgo</groupId> <artifactId>ojalgo-xpress</artifactId> <version>1.2.0</version> </dependency> -
Register Xpress once, at start-up:
ExpressionsBasedModel.addIntegration(SolverXpress.INTEGRATION);
That is all. Your model code stays exactly as it is, and Xpress now solves your models.
To try Xpress on one model first, leave out the registration and call model.maximise(SolverXpress.INTEGRATION) (or minimise) on that model.
New to ojAlgo: Xpress from Java
ojAlgo is made for the Java ecosystem:
- One Maven dependency, pure Java, no further dependencies, MIT licensed. It works with Maven, Gradle and every other JVM build tool, and from Kotlin, Scala and any other JVM language.
- Models are plain Java objects. No modelling language, no model files, no code generation: variables and constraints are created in code, with your IDE's completion and refactoring, from your application's own data.
Set up. You need Java 11 or later, and FICO Xpress installed and licensed; ojalgo-xpress is built and tested with Xpress 47.01. Add ojalgo-xpress, which brings ojAlgo with it, and Xpress's Java package, described below:
<dependency>
<groupId>org.ojalgo</groupId>
<artifactId>ojalgo-xpress</artifactId>
<version>1.2.0</version>
</dependency>
Write a model. A furniture maker decides how many chairs and tables to make. Each variable has bounds and a weight, its contribution to the objective (here the profit per unit); each expression with a limit is a constraint. The table line has a fixed cost, modelled with a binary variable.
import org.ojalgo.optimisation.ExpressionsBasedModel;
import org.ojalgo.optimisation.Optimisation;
import org.ojalgo.optimisation.Variable;
import org.ojalgo.optimisation.solver.xpress.SolverXpress;
public class ProductionPlan {
public static void main(final String[] args) {
// Register Xpress once; from then on it solves the models
ExpressionsBasedModel.addIntegration(SolverXpress.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();
System.out.println(result.getState() + " " + result.getValue());
System.out.println("Chairs: " + chairs.getValue().toPlainString());
System.out.println("Tables: " + tables.getValue().toPlainString());
System.out.println("TableLine: " + tableLine.getValue().toPlainString());
}
}
Run it. Run it with Xpress's native libraries on the library path (-Djava.library.path=<xpressmp>/lib) and the two environment variables described below set. The result is OPTIMAL with a profit of 6475: 75 chairs and 50 tables, with the table line running.
Models can also be read from MPS or LP files with ExpressionsBasedModel.parse(file). The Optimisation Cookbook has complete models for common problem shapes — assignment, scheduling, bin packing, blending and more.
Xpress's Java package
The Xpress Java API, xprs.jar, is part of the Xpress installation and is found in <xpressmp>/lib. It is not on Maven Central, and ojalgo-xpress does not bring it with it. Install it in your local Maven repository (here with the Xpress version ojalgo-xpress is built with; use your own):
mvn install:install-file -Dfile=<xpressmp>/lib/xprs.jar \
-DgroupId=com.fico.xpress -DartifactId=xprs -Dversion=47.01 -Dpackaging=jar
and add it to your project:
<dependency>
<groupId>com.fico.xpress</groupId>
<artifactId>xprs</artifactId>
<version>47.01</version>
</dependency>
At run time the JVM must find Xpress's native libraries, which are in the same directory: -Djava.library.path=<xpressmp>/lib. Xpress also needs two environment variables:
| Variable | Value |
|---|---|
XPRESSDIR |
the installation directory, <xpressmp> |
XPAUTH_PATH |
the licence file, <xpressmp>/bin/xpauth.xpr |
Typical installation directories are /Applications/FICO Xpress/xpressmp on macOS, /opt/xpressmp on Linux and C:\xpressmp on Windows.
Versions
ojalgo-xpress brings the ojAlgo version it was built with. ojAlgo is released more often, and a version of ojAlgo you declare yourself takes precedence:
<dependency>
<groupId>org.ojalgo</groupId>
<artifactId>ojalgo</artifactId>
<version>57.5.0</version>
</dependency>
Parameters
ojalgo-xpress passes these model options on to Xpress. Xpress's own output is switched off.
ojAlgo option (model.options) |
Xpress parameter |
|---|---|
time_suffice / time_abort (the shorter one) |
MAXTIME |
parallelism(n) |
THREADS |
feasibility, when changed from the default |
FEASTOL, MIPTOL |
| the integer strategy's gap tolerance, when changed | MIPRELSTOP, MIPABSSTOP |
Any other Xpress parameter is set with a configurator: extend SolverXpress.Configurator, override configure, and register it.
import com.dashoptimization.XPRSconstants;
import com.dashoptimization.XPRSprob;
import org.ojalgo.optimisation.Optimisation;
import org.ojalgo.optimisation.solver.xpress.SolverXpress;
public class MyXpressConfigurator extends SolverXpress.Configurator {
@Override
protected void configure(final XPRSprob problem, final Optimisation.Options options) {
super.configure(problem, options);
problem.setIntControl(XPRSconstants.CUTSTRATEGY, 2);
}
}
ExpressionsBasedModel.setConfigurator(new MyXpressConfigurator());
More
- Mathematical optimisation with ojAlgo
- Optimisation Cookbook: complete models for common problem shapes
- ojalgo-xpress on Maven Central
- Questions and support: Support & Community