Showing posts with label open source. Show all posts
Showing posts with label open source. Show all posts

Friday, June 14, 2019

A Java Container for Parameters

A few days ago, I posted about a Swing class (and supporting stuff) that I developed to facilitate my own computations research, and which I have now made open-source in a Bitbucket repository. I finally got around to cleaning up another Java utility class I wrote, and which I use regularly in experiments. I call it ParameterBlock. It is designed to be a container for various parameters that I need to set during experiments.

It might be easiest if I start with a couple of screen shots. The first one shows a Swing application I was using in a recent project. Specifically, it shows the "Settings" menu, which has multiple entries corresponding to different computational stages (the overall solver, an initial heuristic, two phases of post-heuristic number crunching), along with options to save and load settings.

Parameter settings menu

Computational research can involve a ton of choices for various parameters. CPLEX alone has what seems to be an uncountable number of them. In the Dark Ages, I hard-coded parameters, which meant searching the source code (and recompiling) every time I wanted to change one. Later I graduated to putting them on the command line, but that gets old quickly if there are more than just a handful. When I started writing simple Swing platforms for my work (like the one shown above), I added menu options to call up dialogs that would let me see the current settings and change them. Over time, this led me to my current solution.

I put each collection of parameters in a separate subclass of the (abstract) ParameterBlock class. So clicking on "Solver" would access on subclass, clicking on "Heuristic" would access a different subclass, and so on. A parameter block can contain parameters of any types. The next shot shows a dialog for the solver parameters in my application. Two of the parameters are boolean (and have check boxes), two are Java enumerations (and have radio button groups), and three are numeric (and have text fields). String parameters are also fine (handled by text boxes).

Defining a parameter block is easy (in my opinion). It pretty much boils down to deciding how many parameters you are going to have, assigning a symbolic name to each (so that in other parts of the code you can refer to "DOMINANCE" and not need to remember if it parameter 1, parameter 2 or whatever), giving each one a label (for dialogs), a type (such as boolean.class or double.class), a default value and a tool tip. The ParameterBlock class contains a static method for generating a dialog like the one below, and one or two other useful methods.

Solver parameters

You can more details in the README file at the GitLab repository I set up for this. The repository contains a small example for demonstration purposes, but to use it you just need to copy ParameterBlock.java into your application. As usual, I'm releasing it under a Creative Commons license. Hopefully someone besides me will find it useful.

Tuesday, June 11, 2019

A Swing Platform for Computational Experiments

Most of my research involves coding algorithms and running computational experiments with them. It also involves lots of trial-and-error, both with the algorithms themselves and with assorted parameters that govern their functioning. Back in the Dark Ages, I did all this with programs that ran at a command prompt (or, in Linux terms, in a terminal) and wrote any output to the terminal. Eventually I got hip and started writing simple GUI applications for those experiments. A GUI application lets me load different problem without having to stop and restart the program, lets me change parameter settings visually (without having to screw around with lots of command line options ... is the switch for using antisymmetry constraints -A or -a?), and save output to text files when it's helpful.

Since I code (mostly) in Java, the natural way to do this is with a Swing application. (When I use R, I typically use an R notebook.) Since there are certain features I always want, I found myself copying code from old projects and then cutting out the project-specific stuff and adding new stuff, which is a bit inefficient. So I finally got around to creating a minimal template version of the application, which I'm calling "XFrame" (short for "Experimental JFrame" or "JFrame for Experiments" or something).

I just uploaded it to Bitbucket, where it is open-source under a very nonrestrictive Creative Commons license. Feel free to download it if you want to try it. There's an issue tracker where you can report any bugs or sorely missing features (but keep in mind I'm taking a fairly minimalist approach here).

Using it is pretty simple. The main package (xframe) contains two classes and an interface. You can just plop them into your application somewhere. One class (CustomOutputStream) you will probably not want to change. The actual GUI is the XFrame class. You will want to add menu items (the only one it comes with is File > Exit) and other logic. Feel free to change the class name as well if you wish. Finally, your program needs to implement the interface defined in XFrameController so that XFrame knows how to talk to the program.

The layout contains a window title at the top and a status message area at the bottom, both of which can be fetched and changed by code. The central area is a scrollable text area where the program can write output. It has buttons to save the content and to clear it, and the program will not exit with unsaved text unless you explicitly bless the operation.

There is a function that lets the program open nonmodal, scrollable dialog (which can be left open while the main window is in use, and whose content can be saved to a file). Another function allows the program to pop up modal dialogs (typically warnings or error messages). Yet another function provides a place where you can insert logic to tell the GUI when to enable/disable menu choices (and maybe other things). Finally, there is a built-in extension of SwingWorker that lets you launch a computational operation in a separate thread (where it will not slow down or freeze the GUI).

I included a small "Hello world!" application to show it works. I'll end with a couple of screen shots, one of the main window and the other of the nonmodal dialog (both from the demo). If it looks like something you might want to use, please head over to Bitbucket and grab the source.

Main window
Nonmodal dialog


Wednesday, June 1, 2016

Using CLP with Java

The COIN-OR project provides a home to a number of open source software projects useful in operations research, primarily optimization programs and libraries. Possibly the most "senior" of these projects is CLP, a single-threaded linear program solver. Quoting the project description:
CLP is a high quality open-source LP solver. Its main strengths are its Dual and Primal Simplex algorithms. It also has a barrier algorithm for Linear and Quadratic objectives. There are limited facilities for Nonlinear and Quadratic objectives using the Simplex algorithm. It is available as a library and as a standalone solver. It was written by John Forrest, jjforre at us.ibm.com.
Like most of the projects at COIN-OR, CLP is coded in C++, which can make it a bit of a pain to use from Java. So I was quite interested when Nils Löhndorf wrote to me that he had written a Java interface to CLP, clp-java, which he has released as open source. I have an academic license for CPLEX, so I'm not really motivated to switch to CLP, but in the past I've found myself working on open source projects in which I would like to have embedded an LP solver. Since the intent is that people be able to use the program at no cost, embedding a somewhat expensive commercial solver is clearly a non-starter.

So I downloaded clp-java and took it for a test drive. I coded a basic assignment model in Java, with randomly generated assignment costs and a user-selectable dimension. (By "dimension" I mean number of slots and number of assignees.) Each run solves a single assignment problem twice, once with CLP and once with CPLEX. Since CLP is limited to a single thread, I throttled CPLEX to a single thread as well.

My primary objective was not to see which was faster. Hans Mittelmann at Arizona State University maintains solver benchmarks in his Decision Tree for Optimization Software. You can see there that CLP sometimes beats CPLEX (rather handily) but frequently is slower. (The same can be said for CLP in comparison to Gurobi.) What I wanted to know was the following:
  • is clp-java easy to use (yes!) and well-documented (pretty well);
  • does it produce correct answers (yes, at least on my tests -- CLP and CPLEX obtained identical solutions on all tests);
  • is there any performance penalty for using the clp-java interface (not that I can see).
I started with a dimension of 5 and doubled it with each new run, up to 1280 for the final run. Here's a log-log plot of total end-to-end solution times:
plot of total solution times
CPLEX beat CLP consistently, but as problem dimension grew the ratio of times seemed fairly steady, and the difference (a bit over 25 seconds on my quad-core PC) doesn't strike me as horrible. IMPORTANT DISCLAIMER: We're looking at one replication at each problem size of one particular LP (assignment problem). Ascribe any significance to anything I say at your own peril. Also, I repeated a few replications, and the times varied significantly, even though the seed for the random number generator was held constant (meaning the repeated problems should have been identical to the original versions). So the teeny sample size is exacerbated by fairly high variance.

I broke the timing down into three parts: setting up the model; solving the model; and recovering the solution (getting the solver to cough up the values of the assignment variables). Here are log-log plots for each.

Setup

log-log plot of setup times
CPLEX seemed to be a bit faster creating a model object than CLP was, but the difference was pretty minimal (2.3 seconds with 1,280 assignees).

Solution

log-log plot of solution times
The bulk of the time for either program is spent solving the problem, so this plot resembles the plot of overall execution times.

Recovery

log-log plot of time to recover the solution
For the small models, both program returned the variables values so quickly that the recorded time (in milliseconds) was zero. Interestingly (at least to me), on the larger instances CLP returned solution values faster than did CPLEX.

Again, the takeaway from the experiments is not which solver is better; it's that Nils's interface works correctly and does not seem to introduce any glaring inefficiencies. Overall, I am quite impressed with Nils's creation. He provides an all-in-one jar file that contains not only his code but also CLP and some third-party libraries. You only have to import clp-java into your project and put the jar in the class path. When you run your program, the necessary libraries are unpacked into a temporary directory. Before the program exits, it cleans up after itself, deleting the temporary directory. (I confirmed that it left no digital artifacts behind.)

There is one bug yet to be worked out (as of this writing). At least on Ubuntu 14.04 and Linux Mint 17.2 (based on Ubuntu 14.04), "out of the box" you get linking errors at run time. Apparently, despite the fact that the COIN libraries CLP uses are sitting in the same temporary directory that CLP is sitting in, it looks for them elsewhere and can't find them. The workaround is to install the coinor-clp package (and a couple of dependencies) from the Canonical repositories, using apt or Synaptic. That fixed the linking problem for me and one other user. I have no idea if the same problem crops up in other operating systems.

So if you are programming in Java and looking for an open-source LP solver that you can build into a project, check out clp-java and CLP.

Monday, May 30, 2016

Java "Deep Learning" Library

If you are a Java (or Scala) (or maybe Clojure?) programmer interested in analytics, and in particular machine learning, you should take a look at Deeplearning4j (DL4J). Quoting their web site:
Deeplearning4j is the first commercial-grade, open-source, distributed deep-learning library written for Java and Scala. Integrated with Hadoop and Spark, DL4J is designed to be used in business environments on distributed GPUs and CPUs. Skymind is its commercial support arm.
In essence, DL4J is a library for building "deep" neural networks, where "deep" apparently means more than one hidden layer. The software is open source (Apache 2.0 license). There is some free support available (from the user community, and possibly the developers). Commercial users needing serious support apparently can buy a support contract from Skymind.

Now, I don't know much about neural networks, although I do have some interest. Right now, I don't have time to put DL4J through its paces. Someday, if I find the time, I'll probably post some observations here. Meanwhile, I did download and install DL4J, along with the examples they provide, and I ran several of the examples successfully (and none unsuccessfully).

Their web site is very well done, with more links to general resources, documentation and tutorials than I think I've seen for any open source project before. So if the notion of coding serious (not just toy) neural nets in a JVM language appeals to you, I think you'd be well served to check them out.

Tuesday, May 20, 2014

A Java Slider/Text Combo

A few years back I was coding (in Java, of course) the <shudder>GUI</shudder> for a research program. I needed to provide controls that would let a user specify priorities (0-100) scale for various things. Two possibilities occurred to me, with pretty much diametrically opposed strengths and weaknesses.

Sliders have a few virtues.
  • Grabbing and yanking the handle is usually faster than typing.
  • When you have more than one, they provide a sort of quasi-horizontal bar graph of the inputs -- it's easy to tell from their relative positions which inputs are larger than which others.
  • It's immediately obvious if you are the absolute maximum or minimum value for the input.
When your input range is something like {1, 2, 3, 4, 5}, it's pretty easy to look at a slider and see what the exact value is. When your input range is {0, 1, ..., 100}, that's a lot harder, which led me to consider text fields. Text fields have their own virtues.
  • It's easy to be precise, regardless of the legal range of inputs. (Try hitting exactly 58, rather than 57, on a 0-100 slider.)
  • You can immediately see exactly what value is being set.
On the other hand, the sort of approximate ratio information you get just by looking at two sliders requires a bit of mental arithmetic with two text fields. Also, if the range of legal values is not obvious to the user, it can be hard to know whether a particular input is at (or near) the maximum or minimum legal value.

Hoping for the best of both worlds, I went looking for Java Swing control that combined a slider with an editable text entry field, and did not find one I liked (which may say more about how picky I am and how good my search skills are than about their availability). So I rolled my own.

Fast-forward to this month, where I'm working on a program for an entirely different research project and once again wanted a slider/text combo control. I dusted off the old code and decided to pretty it up a (very) little, add some documentation and release it into the wild. The project name is ComboSlider, and you can find its repository on Bitbucket. I released it under the EPL 1.0 open source license. Source code, a compiled jar file and documentation are all in the repository. The jar file includes a small demonstration program.

Here is a screen shot of the demo program:


The ComboSlider control is in the orange rectangle. Pull the slider and the text field updates. Type a legal value in the text field and the slider automatically repositions.

The top two text fields demonstrate how to redefine the domain of the ComboSlider on the fly. The bottom text label updates automatically when you change the input value, demonstrating how to use a change listener to monitor the ComboSlider's value. (In an ordinary input dialog, though, you would not need the change listener; you would just wait for the dialog to complete and then use ComboSlider.getValue() to find out what the input value is.)

There are two limitations I probably should mention: it only accepts integer inputs (positive or negative); and, while you can set the size of the entire ComboSlider using the usual setters for minimum/maximum/preferred size, the separate dimensions of the slider and text field are hard coded in the constructor.

Sunday, May 11, 2014

Setting CPLEX Parameters in Java Revisited

A bit more than a year and a half ago, I wrote some Java code to facilitate setting parameters for the CPLEX optimizer using their Concert API. Since then, I've added support for their CP Optimizer, and IBM has refactored the handling of parameters in CPLEX, necessitating an update to my code. This post (which supersedes the previous one) describes how to get and use my code, which is licensed under the Eclipse Public License.

Purpose


When using any of the programming APIs to CPLEX or CP Optimizer, the conventional ways to set parameters for the solver are to hard-code them, or to hard-code methods of setting specific parameters (for instance, write a method that sets the solver time limit using an argument fetched from somewhere). Unfortunately, picking parameter values for either solver is an NP-annoying task, with lots of possible combinations to consider. I therefore prefer to set them either from command line arguments or possibly from user inputs obtained from a GUI for my program. My utility library provides the necessary infrastructure for doing that.

Requirements


Other than Java 7 or later (once a "later" becomes available), all you need to use the code are the same jar and binary files for CPLEX and/or CP Optimizer that your program needs to use those solvers. If you are only using one of the solvers, you will not need to link the other library in order to use my code.

Versions


Due to the aforementioned refactoring, I was forced to create two versions of the utility, with the second version not backward-compatible. I'll provide usage example for both below. As best I can tell, they work identically with CPOptimizer, other than needing (version 2) or not needing (version 1) to have a class instance created. CPOptimizer does not have hierarchical parameter names, and none of its parameter names are ambiguous.

Both versions use strings for both the parameter name and the parameter value (since a string is how the value would be obtained from the command line); the utility takes care of interpreting strings representing numerical or logical values.

Version 1.0


Version 1 of my utility works with CPLEX 12.5.1 or earlier. It uses the (mercifully short) parameter names in force prior to the IBM refactoring, so for instance you can specify the time limit parameter as "TiLim". Parameter names in this version are case-sensitive (so "TiLim" works but neither "tilim" nor "Tilim" will). Version 1.0 also works with CPLEX 12.6 using the old parameter names, but it will not recognize the new names. For instance, when setting the branching direction in CPLEX 12.6, version 1.0 will recognize the old name "BrDir" but not the new name "MIP.Strategy.Branch". According to the CPLEX documentation, the old parameter names are deprecated, so version 1 of my utility will work with CPLEX 12.6 and probably with any minor upgrades (a hypothetical 12.6.1, say), but may stop working with some future version of CPLEX.

Version 1 uses a static method to set parameters (see the example below) and does not require that an instance of the parameter setter class be created.

Version 1 does not contain a main program; it is purely a library.

Version 2.0


Version 2 of my utility works with CPLEX 12.6 but not with earlier versions of CPLEX, as it only knows the new parameter names. Thus, reversing the previous example, version 2 will recognize "MIP.Strategy.Branch" but not "BrDir". Unlike version 1, parameter names in version 2 are not case-sensitive; "mip.strategy.branch" and "MIP.strategy.branch" will work just as well as "MIP.Strategy.Branch".

The new parameter names, which reflect a class hierarchy, are a PITA to type, so version 2 will accept shortened versions when no ambiguity exists. In the case of the branch direction, "Strategy.Branch" and just "Branch" will work equally well. The name "Display", however, maps to seven (!) distinct parameters, so you need to provide enough of the hierarchy to eliminate the ambiguity. If you want to adjust the simplex display, you can use "IloCplex.Param.Simplex.Display" (have fun typing that!) or "Param.Simplex.Display" or "Simplex.Display" (which gets my vote), but not just "Display". Failure to use enough of the hierarchy to uniquely identify the target parameter will result in an AmbiguousParameterException being thrown.

The inevitable one exception to this is the time limit. Three parameters answer to the name "TimeLimit", but for somewhat arcane reasons I coded the utility to recognize "TimeLimit" as meaning "IloCplex.Param.TimeLimit". (For the other two parameters, you'll need "Tune.TimeLimit" and either "DistMIP.Rampup.TimeLimit" or just "Rampup.TimeLimit".)

Version 2, in contrast to version 1, does not employ a static parameter setter, and so you need to create an instance of the parameter setter in order to use it. Again, see the example below.

Version 2 contains a main program. If you run it, it will list all the parameters it can find for both CPLEX and CPOptimizer. If you have one but not the other linked, you'll want to comment out the portion of the code that lists parameters for the solver you are not using.

Examples


In the following examples, I will assume that you want to set the time limit (double) for both CPLEX and CPOptimizer, the log verbosity (integer) for CPOptimizer, the solution limit (long) for CPLEX, and the presolve switch (logical) for CPLEX. For the CPLEX 12.6 parameters, I'll use the shortest legal name. Left to the reader as an exercising: import statements and wrapping portions of the code in try-catch blocks as needed.

Version 1.0


// create solver instances
IloCplex cplex = new IloCplex();
IloCP cp = new IloCP();

// parameter names (would normally come from command line or GUI)
String[] cplexNames = new String[] {"TiLim", "IntSolLim", "PreInd"};
String[]  cpNames = new String[] {"TimeLimit", LogVerbosity"};

// parameter values  (would normally come from command line or GUI)
String[] cplexValues = new String[] {"23.5", "1000", "false"};
String[] cpValues = new String[] {"23.5", 1};

// set the CPLEX parameters
for (int i = 0; i < cplexNames.length; i++) {
   cplexutils.CplexParamSetter.set(cplex, cplexNames[i], cplexValues[i]);
}

// set the CPOptimizer parameters
for (int i = 0; i < cpNames.length; i++) {
  cplexutils.CPOptimizerParamSetter.set(cp, cpNames[i], cpValues[i]);
}

Version 2.0


// create solver instances
IloCplex cplex = new IloCplex();
IloCP cp = new IloCP();

// create parameter setter instances
CplexParameterSetter csetter = new CplexParameterSetter();
CPOptimizerParameterSetter cpsetter = new CPOptimizerParameterSetter();

// parameter names (would normally come from command line or GUI)
String[] cplexNames = new String[] {"TimeLimit", "Limits.Solutions", "Presolve"};
String[]  cpNames = new String[] {"TimeLimit", LogVerbosity"};

// parameter values  (would normally come from command line or GUI)
String[] cplexValues = new String[] {"23.5", "1000", "false"};
String[] cpValues = new String[] {"23.5", 1};

// set the CPLEX parameters
for (int i = 0; i < cplexNames.length; i++) {
   csetter.set(cplex, cplexNames[i], cplexValues[i]);
}

// set the CPOptimizer parameters
for (int i = 0; i < cpNames.length; i++) {
  cpsetter.set(cp, cpNames[i], cpValues[i]);
}


Obtaining the code


You can download either version from the project's downloads page on Bitbucket. Binaries are available from the "Downloads" tab, source code from the "Tags" tab. If you run into a bug (unlikely, but you never know), please let me know. There's an issue tracker under the "Issues" link.
Please see the more recent post Updated Java Utilities for CPLEX and CP Optimizer for a description of the contents of the library and links to both source code and a binary distribution. Please note that version 1.0 no longer exists; the links in the updated post will take you to the most recent version.

Thursday, April 3, 2014

The Definition of "Open"

Before I climb up on my soapbox, I probably should make a couple of disclaimers to put what follows in perspective.
  • I am a heavy user of open source software, and in particular of products from the Mozilla Project. My primary email client is Thunderbird. My first web browser was Netscape Navigator (which predates the Mozilla Project), which eventually morphed into Mozilla and, most recently, Firefox. I've used other browsers, depending on the platform, but Firefox remains my primary choice (although I may have to rethink that based on what follows). In fact, I'm typing this entry into Firefox.
  • I am in favor of the legalization of gay marriage. For that matter, I'm in favor of legalizing polygyny and polyandry. I'm not saying that I want to try any of them; I just don't see any reason that the government (at any level) has a compelling interest in forbidding any of them, and doing so clearly creates inequality in the treatment of citizens. (Actually, while I don't want to get into the subject in detail, my personal preference would be to take the government out of the marriage business entirely. Religions should be free to define "marriage" any way they want; the government should let any adults of legal age file paperwork somewhere designating individuals to fill the "marital" roles for which the government has a legitimate interest, such as parenting, advanced health care decisions, mingling and division of assets, etc.)
Wondering what brought all that up? I was sitting in a coffee shop this afternoon, catching up on some reading, when I came across a story that nearly caused me to do a spit take: Mozilla CEO Brendan Eich resigns amid controversy. Here's a short summary of the events it describes:
  1. The Mozilla Foundation, in need of a new CEO, hires Brendan Eich (their CTO).
  2. The fact that Eich donated $1,000 (presumably of his own money) in 2008 to support California's Proposition 8 (a bill to ban gay marriage) resurfaces.
  3. Mozilla's corner of the universe reacts (sample here), or possibly overreacts, to the hiring. As best I can tell from reading a few articles, the reaction is largely if not entirely negative.
  4. Three members of the Mozilla Foundation board resign, but allegedly due to a disagreement on hiring an internal candidate and not due to the donation. (This is reported to be half the board, raising the question of how Eich got hired if half the board was so opposed to him that they would resign in protest.)
  5. Eich resigns (possibly under pressure) and Mozilla issues a statement about it (which reads like a mea culpa for having hired him in the first place).
I have never met Mr. Eich, I have no idea whether he was a good pick for the CEO position, and I'm massively confused about how he would be selected with so much apparent board opposition. As noted above, I don't agree with Eich's position on Prop. 8. What caused me to choke on my coffee, though, is nicely illustrated by this line from the Mozilla blog post:
Mozilla believes both in equality and freedom of speech. Equality is necessary for meaningful speech. And you need free speech to fight for equality. Figuring out how to stand for both at the same time can be hard.

So I think they've figured the "hard" part out. You start out by appointing yourself the arbiter of "equality", and then you define "free speech" to mean "you're free to make speeches agreeing with us". Somewhere on the AfterLifeNet, Voltaire and Evelyn B. Hall are probably installing new browsers. I may need to join them (with the browsers, not the after life, just to be clear).

Postscript: For a list of some choice quotes from Voltaire (or at least attributed to him), you might like "Famous Quotations From Voltaire That Still Apply to the Modern World".