Skip to content
apete edited this page May 15, 2016 · 2 revisions

MPS (Mathematical Programming System) is a file format for describing linear programming (LP) and mixed integer programming (MIP) problems. It's an old format developed by IBM for one of their early optimisation products, but it's still widely used and supported by all the major commercial LP solvers. The ojAlgo optimisation models and solvers can be initiated using MPS files. A large part of ojAlgo's optimisation test cases are based on (standard) MPS files found in various "collections" around the web.

WikipediA has a description of the format as well as a very small example file. (I've seen this particular model/file used in other places, and we'll use it for this example.) It's a text file so it is human readable. If you just know a little bit about linear programming you can read the model (since it's so small).

NAME          TESTPROB
ROWS
 N  COST
 L  LIM1
 G  LIM2
 E  MYEQN
COLUMNS
    XONE      COST                 1   LIM1                 1
    XONE      LIM2                 1
    YTWO      COST                 4   LIM1                 1
    YTWO      MYEQN               -1
    ZTHREE    COST                 9   LIM2                 1
    ZTHREE    MYEQN                1
RHS
    RHS1      LIM1                 5   LIM2                10
    RHS1      MYEQN                7
BOUNDS
 UP BND1      XONE                 4
 LO BND1      YTWO                -1
 UP BND1      YTWO                 1
ENDATA

There are 3 columns/variables named XONE, YTWO and ZTHREE, and a number of constraints as well as an objective function (named COST).

Example code

import java.io.File;

import org.ojalgo.OjAlgoUtils;
import org.ojalgo.netio.BasicLogger;
import org.ojalgo.optimisation.Expression;
import org.ojalgo.optimisation.ExpressionsBasedModel;
import org.ojalgo.optimisation.MathProgSysModel;
import org.ojalgo.optimisation.Optimisation.Result;
import org.ojalgo.optimisation.Variable;

/**
 * A program that shows how to use an MPS file with ojAlgo
 *
 * @author apete
 */
public class UsingMPS {

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

        BasicLogger.debug();
        BasicLogger.debug(UsingMPS.class.getSimpleName());
        BasicLogger.debug(OjAlgoUtils.getTitle());
        BasicLogger.debug(OjAlgoUtils.getDate());
        BasicLogger.debug();

        // Get a refrence to the MPS-file
        final File tmpFile = new File("./src/testprob.mps");

        // Instantiate the MPS-model
        final MathProgSysModel tmpModelMPS = MathProgSysModel.make(tmpFile);

        // Optionally validate the model
        if (tmpModelMPS.validate()) {
            BasicLogger.debug("MPS-model ok!");
        } else {
            BasicLogger.debug("MPS-model problem!");
        }
        BasicLogger.debug(tmpModelMPS);

        // The MPS format does not include a standard way to specify if the
        // model/problem is meant to be minimised or maximised. There is a convention
        // to include an OBJSENSE section where this would be specified, but this
        // is not a requirement. By default ojAlgo will minimise the problem.
        final Result tmpSolveResult = tmpModelMPS.solve();

        // Print the result
        BasicLogger.debug("Solved => " + tmpSolveResult);
        // The solution variable values are returned in the order the columns/variables
        // were defined in the MPS-file.

        // Optionally you may explicitly call minimise() or maximise() rather than solve().
        final Result tmpMaxResult = tmpModelMPS.maximise();
        final Result tmpMinResult = tmpModelMPS.minimise();

        BasicLogger.debug("Maximised => " + tmpMaxResult);
        BasicLogger.debug("Minimised => " + tmpMinResult);

        // Internally MathProgSysModel contains an ExpressionsBasedModel. You may
        // extract that and continue working with it. ExpressionsBasedModel is ojAlgo's
        // main modelling "tool".
        final ExpressionsBasedModel tmpExtracted = tmpModelMPS.getExpressionsBasedModel();

        // Among other things you get explicit access to model variables...
        BasicLogger.debug();
        BasicLogger.debug("=== Variables ===");
        for (final Variable tmpVariable : tmpExtracted.getVariables()) {
            BasicLogger.debug(tmpVariable);
        }

        // ...and expressions.
        BasicLogger.debug();
        BasicLogger.debug("=== Expressions ===");
        for (final Expression tmpExpression : tmpExtracted.getExpressions()) {
            BasicLogger.debug(tmpExpression);
        }
        BasicLogger.debug();

        // Alter the two inequalities to allow a slightly wider range
        tmpExtracted.getExpression("LIM1").upper(5.5); // Change from 5.0 to 5.5
        tmpExtracted.getExpression("LIM2").lower(9.5); // Change from 10.0 to 9.5
        BasicLogger.debug("Modified => " + tmpExtracted.minimise());
        // Now the solution is no longer integer valued (as it was before),
        // but we can add that requirement to each of the variables...
        for (final Variable tmpVariable : tmpExtracted.getVariables()) {
            tmpVariable.integer(true);
        }
        // We get the old solution back
        BasicLogger.debug("Integer constrained => " + tmpExtracted.minimise());

    }

}

Console output


UsingMPS
ojAlgo
2015-01-11

MPS-model ok!
############################################
0 <= XONE <= 4.000000
-1.000000 <= YTWO <= 1.000000
0 <= ZTHREE
7.000000 <= MYEQN: 0.0 <= 7.000000
10.000000 <= LIM2: 0.0
COST: 0.0 (1.000000)
LIM1: 0.0 <= 5.000000
############################################

Solved => OPTIMAL 54.0 @ [4.0, -1.0, 6.0]
Maximised => OPTIMAL 80.0 @ [4.0, 1.0, 8.0]
Minimised => OPTIMAL 54.0 @ [4.0, -1.0, 6.0]

=== Variables ===
0 <= XONE: 4.000000 <= 4.000000
-1.000000 <= YTWO: -1.000000 <= 1.000000
0 <= ZTHREE: 6.000000

=== Expressions ===
7.000000 <= MYEQN <= 7.000000
10.000000 <= LIM2
COST (1.000000)
LIM1 <= 5.000000

Modified => OPTIMAL 53.5 @ [3.5, -1.0, 6.0]
Integer constrained => OPTIMAL 54.0 @ [4.0, -1.0, 6.0]