Optimisation-as-a-Service

The main benefit with ojAlgo’s suite of mathematical optimisation solvers is that it’s open source pure Java. It allows to solve mathematical optimisation problems directly in the JVM – no dependencies, no license management, no native code libraries or service calls.

Another benefit is that if it, later, turns out the capabilities of a commercial native code solver are required; you can just plug it in. You do of course then need to install that software as well as pay for and manage the license, but you do not need to change any of the Java code.

Now Optimatika introduces another alternative – Optimisation-as-a-Service. It frees you from the burdon of setting up and maintaining a server running optimisation code. Everything required to use this service is already in ojAlgo (v52.0.0 and later).

Calling this service does not require dealing with JSON, XML or anything like that. Using the service is just a matter of configuring to use that “solver” rather than the usual ones.

The server running the service is packaged as a Docker image – easy to deploy anywhere. There is a test/demo service available. Below is example code that demonstrates how to use Optimatika’s Optimisation-as-a-Service. If you run the code the optimisation problem is solved by that test/demo service.

Example Code

OptimisationAsAService.java
import java.io.File;

import org.ojalgo.OjAlgoUtils;
import org.ojalgo.netio.BasicLogger;
import org.ojalgo.optimisation.ExpressionsBasedModel;
import org.ojalgo.optimisation.Optimisation.Result;
import org.ojalgo.optimisation.service.ServiceIntegration;

/**
 * A program that shows how to use Optimatika's Optimisation-as-a-Service.
 *
 * @see https://www.ojalgo.org/2022/10/optimisation-as-a-service/
 */
public class OptimisationAsAService {

    public static void main(final String[] args) {

        BasicLogger.debug();
        BasicLogger.debug(OptimisationAsAService.class);
        BasicLogger.debug(OjAlgoUtils.getTitle());
        BasicLogger.debug(OjAlgoUtils.getDate());
        BasicLogger.debug();

        /*
         * The service is essentially a collection of solvers running on a remote machine. Its front is an
         * implementation of the Optimisation.Solver interface that simply forwards the problem. To be able to
         * make use of this there needs to be an implementation of the Optimisation.Integration interface
         * specific for that forwarding solver. When we instantiate such an integration we need to provide
         * information about where the service is located.
         */

        ServiceIntegration serviceIntegration = ServiceIntegration.newInstance("http://test-service.optimatika.se");

        /*
         * ...and then we need to configure ExpressionsBasedModel to make use of it.
         */

        ExpressionsBasedModel.addIntegration(serviceIntegration);

        /*
         * That's it! Everything else is the same as it would be in any other case.
         */

        File file = new File("./testprob.mps"); // File containing an optimisation problem

        ExpressionsBasedModel model = ExpressionsBasedModel.parse(file);

        Result result = model.minimise(); // Solution to that problem

        BasicLogger.debug("Minimised => " + result);

        /*
         * The main purpose of having an optimisation service is that it's possible to offload heavy workload
         * to a separate machine running more/other/better solvers than the built-in pure Java ojAlgo solvers.
         */

        /*
         * In fact maybe you want to solve some smaller models locally, and only use the service for larger
         * models.
         */

        ExpressionsBasedModel.Integration<?> configuredIntegration = serviceIntegration.withCapabilityPredicate(m -> m.countVariables() > 1000);

        /*
         * With that a new integration is created, configured to only report that it's capable of solving a
         * particular model if there are more than 1000 variables. If it's not "capable" the default solvers
         * will be used instead.
         */

        /*
         * To use that configured service integration rather than the unconfigured we used before it needs to
         * be cleared first.
         */

        ExpressionsBasedModel.clearIntegrations();
        ExpressionsBasedModel.addIntegration(configuredIntegration);

        result = model.minimise(); // This time solved locally since that test problem is very small

        BasicLogger.debug("Minimised => " + result);

    }

}

The service endpoint used in the example above is for test and demonstration purposes only. That means NOT for production use! It may be restricted or removed, at any time, without warning. At the time of writing this post it is fully functional and unrestricted (running on a low spec server). Most likely there will always be some kind of test service endpoint available, but that will be with limited capabilities. Optimisation-as-a-Service is a commercial product/service. If you’d like access to an unrestricted service instance for (private) production use, you should contact Optimatika.