linear programming

Is there anything built in or an XOP which can be used for linear programming purposes? E.g.
http://en.wikipedia.org/wiki/Linear_programming

There is code out there:
http://lpsolve.sourceforge.net/5.5/

and I wonder if there were already attempts to make use of that for Igor and if not what would it take to do it?

Cheers
C
I have thought about it (briefly) but have never acted on those thoughts. Right now we are not in a position to pursue such projects, but I certainly have it on the long list of things that would be good to add to Igor.

The link you give is to code licensed under LGPL. Our understanding of this license (which is difficult to understand, and causes long threads on any developer forum where the topic comes up) is that we can use such code, but only with some difficulty. Another option, since you don't have the restrictions resulting from publishing a for-profit application, is to write an XOP that wraps up the API in that library.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
johnweeks wrote:
Another option, since you don't have the restrictions resulting from publishing a for-profit application, is to write an XOP that wraps up the API in that library.


I somehow feared that answer because currently writing an XOP is beyond my skills (I never looked into that and I don't have any experience in C). On the other hand, in my case the number of calls to lp_solve won't be excessive and a work-around for me could be to use Igor to write an input file which can then be processed simply from the command line of the operating system (on Mac in my case). Is there any way of executing a command from the system terminal via Igor and read out whatever lp_solve puts out? I guess that is in a very simplified manner what an XOP does, but would that be feasible?
You can use ExecuteScriptText to run an Apple Script program. You can probably use AppleScript to open a terminal window and run a command-line function, but I don't really know much about how to do that. I know we have customers who have done things like this, hopefully one of them will see this and comment.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
In a nutshell ...

* create a shell script that will run what you need when given two inputs, the input file and the output file
* put that shell script in your $PATH
* call that shell script from Igor using ExecuteScript

ExecuteScript "mylpsolver 'input file name' 'output file name'"


* wait for the return from the ExecuteScript command
* read the output file from Igor

--
J. J. Weimer
Chemistry / Chemical & Materials Engineering, UAHuntsville
johnweeks wrote:
You can use ExecuteScriptText to run an Apple Script program. You can probably use AppleScript to open a terminal window and run a command-line function, but I don't really know much about how to do that. I know we have customers who have done things like this, hopefully one of them will see this and comment.

I have not done this with AppleScript, but using Igor's ExecuteScriptText to run a Windows DOS BAT file. Igor was used to create the input file, call the BAT file (which ran a FORTRAN executable), wait for output file read access, read, analyze, and display the results. A bit kludgy, but should work with any executable whose input and output file formats are known.

Here is an example to call the unix "ls -al" command.

Function/S DirList(dstr)
    string dstr

    string exStr, uStr
   
    sprintf uStr, "ls -al \'%s\'" dstr
    sprintf exStr, "do shell script \"%s\"" uStr
   
    ExecuteScriptText exStr
       
    return S_value
end


print DirList("/Users/jjw") --> prints directory listing

Suppose the shell level command in your $PATH is lpsolver with flags -r (recursive). You want to run lpsolver on file /Users/jjw/Documents/Data Files/April 23, 2012/first set/run002.dat. You want the output in the same directory as lp_run002.dat. Here is an example off the top of my head that should work.

Function/S MyLPSolver(iPath,iFile,flags)
    string iPath, iFile, flags

    string iStr, oStr, exStr, uStr

    sprintf iStr, "\'%s/%s\'" iPath,iFile   // define the input file path
        sprintf oStr, "\'%s/lp_%s\'" iPath,iFile  // define the output file path

    sprintf uStr, "lpsolver -%s \'%s\' \'%s\'", flags, iStr, oStr  // generate the shell script command
    sprintf exStr, "do shell script \"%s\"" uStr // generate the ExecuteScriptText command
   
    ExecuteScriptText exStr
       
    return S_value
end


MyLPSolver("/Users/jjw/Documents/Data Files/April 23, 2012/first set","run002.dat","r")

--
J. J. Weimer
Chemistry / Chemical & Materials Engineering, UAHuntsville
The manual actually contains an example function to call a unix command from the terminal, based on ExecuteScriptText. This together with J.J.'s suggestion to wrap the lp-solver commands into a shell script returns the solver output directly as string! That's nice and should do for the moment!

John, would be great if linear programming and even a solver for non-linear constrained optimisation problems could be added in the future but I understand version 7 has priority now.

Thanks everyone!
C
just in case someone is interested - here is my present solution.

function lp_solve(gg, AA, bb)
    wave gg, AA, bb  
   
    // minimises                sum { x[i] * gg[i] }            by solving for x[i]
    // subject to the contraint         AA[i][j] * x[i] = bb[j]
   
       
    //****************
    // (1) write input file
    //****************
   
    variable IgorIn
    string fileName = "IgorModel.lp"        // fixed input file name for shell script (see below)
    NewPath/Q/O SolverPath, "Macintosh HD:Users:Christian_At_Work:DropBox:Igor:lp_solver"  // path to lp_solve unix executable folder
   
    variable i, j
    variable numVar = numpnts(gg)
   
    Open/Z/P=SolverPath IgorIn as fileName 
       
    fprintf IgorIn, "min: "
     
    // write objective function  
    for (i=0; i<numVar; i+=1)      
        fprintf  IgorIn, num2str(gg[i]) + "x"+num2str(i) + " "         
    endfor
    fprintf  IgorIn, ";\r"
   
    //write contraints 
    for (j=0; j<Dimsize(AA, 1); j+=1)      
        for (i=0; i<DimSize(AA, 0); i+=1)      
            fprintf  IgorIn, num2str(AA[i][j]) + "x"+num2str(i)
            if (i < DimSize(AA, 1) )
                fprintf IgorIn, " + "
            endif  
        endfor     
        fprintf IgorIn, " = " + num2str(bb[j]) + ";\r" 
    endfor
   
    Close IgorIn
   
   
    //************************************************************************************
    // (2) run pre-defined unix shell script (here lpsolve.sh) using ExecuteScriptTest; returns lp_solve output in S_value 
    //************************************************************************************
   
    string uCmd = "lpsolve.sh"
    string cmd
    sprintf cmd, "do shell script \"%s\"", uCmd
    ExecuteScriptText cmd
    //Print S_value
   
       
    //******************************************
    //  (3) analyse S_value and writes results to W_LPsolved
    //******************************************
   
    Make/O/D/N=(numVar) W_LPsolved
   
    string buffer  
    buffer = Replacestring("\r", S_value, "")    // get rid of carriage return
    buffer = Replacestring(" ", buffer, "")     // collapse white space
   
    for (i=0; i<numVar; i+=1)                   // format string such that it is analysable using NumberByKey
        buffer = Replacestring( "x" + num2str(i) , buffer, ";x" + num2str(i) + "=")
    endfor
   
    for (i=0; i<numVar; i+=1)                   // extract result values and write to W_lpsolved
        W_LPsolved[i] = NumberByKey("x"+num2str(i), buffer, "=", ";")
    endfor 
   
end



An input file looks like, e.g.

min: -0.275x0 -0.12x1 -0.15x2 ;
1x0 + 1x1 + 0x2 = 0.4;
1x0 + 0x1 + 1x2 = 0.1;


and S_value:

 "
Value of objective function: -0.06350000

Actual values of the variables:
x0                            0.1
x1                            0.3
x2                              0"





The bottleneck here is obviously the writing-to-disk part.