Thursday, December 29, 2011

Launching Windows Apps with Wine

Although I work almost 100% with Linux these days, I have a few Windows applications I find useful (including IrfanView for quick image edits and OCR -- much simpler, albeit less powerful, than GIMP) and PathSync for synchronizing local directories with my thumb drives. I also find PDF-XChange Viewer handy for adding annotations to PDF files.  All these programs run fine under Wine, with one small "gotcha".  When I install them (by downloading the Windows installer and then running "wine name-of-installer.exe" in a terminal), shortcuts to them are added to the Wine submenu of the GNOME menu ... but the shortcuts are often  dysfunctional.  They attempt to launch the Windows .lnk file added to the (virtual) Windows start menu, and typically I either get a "file not found" pop-up or the launch simply fails silently.

The solution I have found is to manually edit the shortcuts.  Suppose that I am logged in as user "paul" and I've just installed IrfanView.  My first step is to track down the Windows path to the executable.  Assuming defaults were used (generally a good thing when installing software under Wine), I open a terminal and drill down to /home/paul/.wine/drive-c/Program\ Files, where I find the IrfanView directory and, in that, the i_view32.exe executable.

The next step is to run

env WINEPREFIX="/home/paul/.wine" wine "C:\Program Files\IrfanView\i_view32.exe"

in a terminal and make sure that it launches correctly.  Note that the path to the executable is written Windows-style (backslashes, no escaping things) in quotation marks.  If the program launches properly, I close it, copy the entire line to the clipboard, find the launcher in the GNOME menu, right-click and choose "Edit properties", and replace the contents of the "Command:" field with the contents of the clipboard.  I also confirm that launcher type is "Application" and not "Application in Terminal".  With that done, I close the launcher edit panel and test it.  Sometimes it seems to take a while before the menu detects and adopts the change I just made.  I'm not sure, shy of logging out (overkill?), what the best way to impose the change immediately is.  I've tried "killall gnome-panel" (possibly also overkill) with mixed success.

Thursday, December 22, 2011

Extracting Variables in CPLEX

It's never happened to me, but apparently some CPLEX users (working with one of the programming APIs) inherit a fully formed problem, an instance of IloCplex or perhaps IloModel, without having access to the Concert code that constructed it.  You only need the problem object to solve it and get the solution status and objective value; but in order to get the values of the variables in an optimal solution, you need to pass either an array of variables (IloNumVar[]) or individual variables in function calls (so that CPLEX can return values matched to the corresponding variables).  If all you have is the problem object, how do you know what the variables are?

This has been asked more than once on help forums, so I list below a Java function that I believe will extract all variables from an instance of IloCplex.  Something quite similar should work in the C++ API, and hopefully if you use the C API you can make the leap from the Java code.  The Python API seems to provide a VariablesInterface class that I think provides a mechanism (if it's even needed in Python -- I don't really know).  I'm blissfully ignorant about the Matlab API.

I've tried to stress-test the Java code, but nonetheless you use it at your own peril.


  private IloNumVar[] parse(IloCplex cplex) throws IloException {
    HashSet<IloNumVar> vars = new HashSet<IloNumVar>();
    Iterator it = cplex.iterator();
    IloLinearNumExpr expr;
    IloLinearNumExprIterator it2;
    while (it.hasNext()) {
      IloAddable thing = (IloAddable) it.next();
      if (thing instanceof IloRange) {
        expr = (IloLinearNumExpr) ((IloRange) thing).getExpr();
        it2 = expr.linearIterator();
        while (it2.hasNext()) {
          vars.add(it2.nextNumVar());
        }
      } else if (thing instanceof IloObjective) {
        expr = (IloLinearNumExpr) ((IloObjective) thing).getExpr();
        it2 = expr.linearIterator();
        while (it2.hasNext()) {
          vars.add(it2.nextNumVar());
        }
      } else if (thing instanceof IloSOS1) {
        vars.addAll(Arrays.asList(((IloSOS1) thing).getNumVars()));
      } else if (thing instanceof IloSOS2) {
        vars.addAll(Arrays.asList(((IloSOS2) thing).getNumVars()));
      } else if (thing instanceof IloLPMatrix) {
        vars.addAll(Arrays.asList(((IloLPMatrix) thing).getNumVars()));
      }
    }
    IloNumVar[] varray = vars.toArray(new IloNumVar[1]);
    return varray;
  } 
 
Update: I have updated the code, incorporating some suggestions I received on a CPLEX forum. The parser is now a static method in a class of its own. You can download the source code (one file, plain text) from Google Docs. To use it, you will likely want to change the package name. Also feel free to delete the various print statements, which are there only for demonstration purposes.

Wednesday, December 7, 2011

Indexing an Array with a Variable

Sometimes, in the context of a mathematical program, someone wants to use a variable $x$ to index a vector $y$, as in \[z = y[x].\] As a starting point, we should assume that $x$ is an integer variable whose domain equals, or at least is a subset of, the index set of $y$. If you try to set $z=y[2.71828]$, or $z=y[5]$ when $y$ is indexed by ${1,\dots,4}$, you should expect Bad Things To Happen.

With that stipulation, $z=y[x]$ poses no problem in a constraint program. It cannot, however, be expressed directly in a mathematical program. If the domain of $x$ is not too large, it can be implemented somewhat obliquely in a mathematical program using binary variables.

Let's assume that $y$ is indexed over $1,\dots,N$ (with $N$ known at the outset), and that $y$ is a parameter. (We'll treat the case where $y$ is a variable in a minute.) Create $N$ binary variables $x_1,\dots,x_N$ and add the constraint \[x_1+\dots+x_N=1,\] which makes $\{x_1,\dots,x_N\}$ a type 1 special ordered set (SOS1). Then define $z$ via \[z=\sum_{i=1}^N y[i]*x_i.\]

You can do exactly this when $y$ is a vector of variables, but it adds a nonconvex quadratic constraint to the model, which likely prevents you from finding a guaranteed optimum, and greatly restricts what algorithms/software you can use. If we know a priori lower and upper bounds for $y$, say \[L_i \le y[i] \le U_i \forall i\in {1,\dots,N}\] with $L_i$ and $U_i$ parameters, we can add the $x_i$ as above and use the following set of constraints to define $z$: \[\begin{eqnarray*}y[i] -z \le (U_i - \hat{L})(1-x_i)  \forall i\in {1,\dots,N}\\ y[i] - z \ge (L_i - \hat{U})(1-x_i)  \forall i\in {1,\dots,N}\end{eqnarray*}\]where $\hat{L}=\min_{i=1,\dots,N} L_i$ and $\hat{U}=\max_{i=1,\dots,N} U_i$.