-
-
Notifications
You must be signed in to change notification settings - Fork 208
Using MPS
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).
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());
}
}
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]