Tuesday, October 2, 2012

Setting CPLEX Parameters

UPDATE: I have new versions of the code, and a new post (superseding this one) documenting how to get and use the code.

When I write Java programs that link to CPLEX (typically for research purposes), I often want to specify some CPLEX parameters, such as time limit for runs, on the command line. Unfortunately, CPLEX has about as many parameters as the US tax code has loopholes. When I know I'll only be tweaking a few parameters, I write code the looks specifically for those parameters, which is mildly tedious. For a current project, though, I want to open a wider range of parameters to experimentation, and writing code to check for each one in the command line would be brutal.

So I wrote a Java class that lets the user set any CPLEX parameter by specifying the parameter name (case-sensitive) and value in strings, the way they would come from the command line. Suppose, for example, that I have a Java program in a JAR file named myprog.jar, and I want to set a time limit of 37.5 seconds and turn off the presolver. My command line would look like

java -Djava.library.path=<path to CPLEX> -jar myprog.jar TiLim 37.5 PreInd false

The code would look like the following:

try {
  IloCplex cplex = new IloCplex();  // create a CPLEX critter
  // assume the command line stuff is in String args[]
  CplexParamSetter.set(cplex, args[0], args[1]); // set TiLim
  CplexParamSetter.set(cplex, args[2], args[3]); // set PreInd
  // do stuff ...
} catch (...) {
  // panic and run for the hills
}

with class CplexParamSetter properly imported and with a whole slew of exceptions it might throw correctly caught and dealt with. (The exceptions are documented via Javadoc in the code.)

I've run a few unit tests on the code, and it seems to work properly, but I make no guarantees. Feel free to download the source code for CplexParamSetter and use it under the Eclipse Public License.

Update: I just modified the code to work with CPLEX 12.5.1 (which made some changes to the Java API that affected parameter recognition). Hopefully it is backward compatible, but I've only tested against 12.5.1. Also, I moved the code from Google Drive to Bitbucket (and updated the link above).

Update: It's no longer on Bitbucket. Please use the link at the top of the post (in the red box).

3 comments:

  1. Hi Professor Rubin,

    My question is, if you are coding an algorithm where the solution of a "main model" will trigger the creation of "subproblems", which modifies your main model, and so on... just like in a Column Generation scheme, how can you limit the whole algorithm computation time (comprising the solution of several models)?

    ReplyDelete
    Replies
    1. There's no way to do it (at least none I know of) with a single setting. What I do is set the time limit parameter before each call to solve() on any of the problems. Usually (but not always) there's no graceful way to continue with the overall algorithm if one of the subproblems times out, so I just allocate all remaining time (difference between a hard completion time limit and the current system clock) to whichever problem is being solved next.

      Delete
  2. Wow, very clever! I'll use it right away. Thanks for your expertise and promptness!

    ReplyDelete

Due to intermittent spamming, comments are being moderated. If this is your first time commenting on the blog, please read the Ground Rules for Comments. In particular, if you want to ask an operations research-related question not relevant to this post, consider asking it on Operations Research Stack Exchange.