ebertolazzi / mexIPOPT

MATLAB interface for IPOPT
108 stars 25 forks source link

Compilation under Octave #13

Open DenisSbragion opened 3 years ago

DenisSbragion commented 3 years ago

Hello,

I tried to compile the mex interface under Octave but there are some minor problems. The main issue it that mxArray is defined as a void under Octave, so function definitions with parameters like:

MatlabFunctionHandle::bind( mxArray const p[], char const error_msg[] )

Give an error, as arrays of voids aren't allowed under C++. To work it needs to be defined as:

MatlabFunctionHandle::bind( mxArray const * p, char const error_msg[] )

I think this different definition should have no adverse effect in the Matlab environment, but I couldn't check as I don't have Matlab.

At the end a patch which fix the few function definitions having the problem, and ipopt.m in order to accept the architectures used by Octave under Windows. This probably needs further fixes to work with Octave under Linux or Mac, but I have no way to check the architectures reported by the computer() function under those operating systems.

Thanks for this very well designed interface.

Bye,

Denis Sbragion

** Patch following **

diff -ru mexIPOPT.orig/toolbox/lib/ipopt.m mexIPOPT/toolbox/lib/ipopt.m
--- mexIPOPT.orig/toolbox/lib/ipopt.m   2021-07-24 00:08:51.000000000 +0200
+++ mexIPOPT/toolbox/lib/ipopt.m    2021-09-09 10:22:41.849937500 +0200
@@ -249,7 +249,7 @@
 function [x,info] = ipopt( varargin )
   cmp = computer;
   if ispc
-    if strcmp( cmp, 'PCWIN64') == 1
+    if strcmp( cmp, 'PCWIN64') == 1 || strcmp( cmp, 'x86_64-w64-mingw32') == 1 || strcmp( cmp, 'i686-w64-mingw32') == 1
       [x,info] = ipopt_win(varargin{:});
     else
       error('IPOPT: No support for architecture %s\n', cmp );
@@ -263,12 +263,12 @@
   elseif isunix
     if strcmp( cmp, 'GLNXA64') == 1
       myCCompiler = mex.getCompilerConfigurations('C','Selected');
-      switch str2num(myCCompiler.Version)
-      case {1,2,3,4,5}
+      switch myCCompiler.Version(1:1)
+      case {'1','2','3','4','5'}
         error('mexIPOPT do not support gcc < gcc6');
-      case {6}
+      case {'6'}
         [x,info] = ipopt_linux_3(varargin{:});
-      case {7,8}
+      case {'7','8'}
         [x,info] = ipopt_linux_4(varargin{:});
       otherwise
         [x,info] = ipopt_linux_5(varargin{:});
diff -ru mexIPOPT.orig/toolbox/src/IpoptInterfaceCommon.cc mexIPOPT/toolbox/src/IpoptInterfaceCommon.cc
--- mexIPOPT.orig/toolbox/src/IpoptInterfaceCommon.cc   2021-07-24 00:08:51.000000000 +0200
+++ mexIPOPT/toolbox/src/IpoptInterfaceCommon.cc    2021-09-08 17:30:35.533599800 +0200
@@ -286,7 +286,7 @@
   // is up to the user to ensure that the MATLAB array is a valid
   // function handle.
   void
-  MatlabFunctionHandle::bind( mxArray const p[], char const error_msg[] ) {
+  MatlabFunctionHandle::bind( mxArray const * p, char const error_msg[] ) {

     IPOPT_DEBUG("In MatlabFunctionHandle::bind");

@@ -324,9 +324,9 @@
   void
   MatlabFunctionHandle::eval(
     Index           n_lhs,
-    mxArray       * lhs[],
+    mxArray       ** lhs,
     Index           n_rhs,
-    mxArray const * rhs[]
+    mxArray const ** rhs
   ) const {

     IPOPT_DEBUG("In MatlabFunctionHandle::eval");
diff -ru mexIPOPT.orig/toolbox/src/IpoptInterfaceCommon.hh mexIPOPT/toolbox/src/IpoptInterfaceCommon.hh
--- mexIPOPT.orig/toolbox/src/IpoptInterfaceCommon.hh   2021-07-24 00:08:51.000000000 +0200
+++ mexIPOPT/toolbox/src/IpoptInterfaceCommon.hh    2021-09-08 17:29:04.261774400 +0200
@@ -134,7 +134,7 @@
     // It is up to the user to ensure that the MATLAB array is a valid
     // function handle.
     void
-    bind( mxArray const p[], char const error_msg[] );
+    bind( mxArray const * p, char const error_msg[] );

     // This method is used to call the MATLAB function, provided inputs
     // to the function. It is up to the user to make sure that the
@@ -143,9 +143,9 @@
     void
     eval(
       Index           n_lhs,
-      mxArray       * lhs[],
+      mxArray       ** lhs,
       Index           n_rhs,
-      mxArray const * rhs[]
+      mxArray const ** rhs
     ) const;

     // Returns true if and only if the function handle is not null.
@@ -170,7 +170,7 @@

     void setup( mxArray * ptr );
     void getStructure( Index rows[], Index cols[] ) const;
-    void getValues( std::string const & func, mxArray ptr[], Number values[] ) const;
+    void getValues( std::string const & func, mxArray * ptr, Number values[] ) const;
   } SparseMatrix;

   /*
@@ -214,7 +214,7 @@
     // this MATLAB array must be a structure array in which each field
     // is a function handle.
     explicit
-    CallbackFunctions( mxArray const mx_x0[], mxArray const ptr[] );
+    CallbackFunctions( mxArray const * mx_x0, mxArray const * ptr );

     // The destructor.
     ~CallbackFunctions();
@@ -225,7 +225,7 @@
     std::vector<Number> const & getx0() const { return m_x0; }

     bool
-    from_cell_array( mxArray const ptr[], Index n, Number * x ) const;
+    from_cell_array( mxArray const * ptr, Index n, Number * x ) const;

     Index numVariables() const { return mx_x_nv; }
rdzman commented 2 years ago

I too would like to see mexIPOPT modified to work seamlessly on Octave.

On a macOS Big Sur 11.6.1 with Octave 6.2, computer returns: x86_64-apple-darwin18.7.0 On Ubuntu 20.04.3 LTS with Octave 6.4, computer returns: x86_64-pc-linux-gnu

FWIW, using the MatlabInterface code from IPOPT 3.11.9, I am still able to build an IPOPT MEX file for Octave for the current IPOPT version (3.14.4).

ebertolazzi commented 1 year ago

I have added cmake build not tested for octave. Can you add a cmake support for Octave?

rdzman commented 1 year ago

Can you add a cmake support for Octave?

I'm not sure if that question was directed at me but, unfortunately, I'm swamped with other commitments and don't really have the expertise to do it anyway.

DenisSbragion commented 1 year ago

I have added cmake build not tested for octave. Can you add a cmake support for Octave?

I'm not sure I got this right, BTW sooner or later I'll have to recompile Octave to the latest version, so I will necessarily test any change introduced.

rdzman commented 1 year ago

FWIW, I use mexIPOPT 1.1.6 to build an IPOPT MEX that works with Octave on GitHub runners. Actually, it's in my own fork of mexIPOPT in a branch without binaries and IPOPT source.

See the action.yml in https://github.com/MATPOWER/action-install-ipopt-octave] to see what is working for me on Linux (with Octave and IPOPT installed via apt-get) and macOS (with Octave installed by brew and IPOPT compiled from source).