Closed mlubin closed 7 years ago
I think it would be best to port the C wrappers in this package into pure Julia code with ccalls. It doesn't look like it's very long or complicated.
For Windows binaries I'd greatly prefer using WinRPM vs manually building and posting binaries somewhere. This will allow Ipopt and Bonmin binaries to easily depend on the same ampl library.
I have some initial cross-compiled binaries of the more modern AMPL/MP version of libasl in my personal project at the openSUSE build service. I had several patches to https://github.com/ampl/mp a few weeks ago to improve this, but it's still not ideal because it runs a few executables at build time. I can use wine to run them, but that's not acceptable as a permanent solution because 32-bit wine can't execute 64-bit Windows cross-compiled executables. The openSUSE build service is set up so all cross-compiled packages are noarch, and get compiled from both 32 and 64 bit build workers. I can take the approach I used for HDF5 and include locally generated versions of the output files if necessary.
@vitaut, any update on https://github.com/ampl/mp/issues/9 ? The same concern applies for arithchk
as well as gen-expr-info
.
The only difficulty in porting the C wrappers to Julia will be mirroring the ASL struct, which will be a bit of a pain but still tractable. I agree that this will help with distributing (and maintaining) the code.
I've added expr-info.cc
to the repo in https://github.com/ampl/mp/commit/4c447a25a066ec637c7d0f9b82cc2d3d29ea7a4e so running gen-expr-info
shouldn't be necessary unless you change the code. arith.h
is a bit more tricky as it detects target floating-point format. Perhaps it can be deduced from CMAKE_SYSTEM_PROCESSOR
with fallback to running arithchk
for unknown processors.
What's wrong with building from source on OSX?
I initially started this project by trying to mirror the ASL data structure, but it turned out to be far easier to write C wrappers. An advantage of the C wrappers is that they can be used for other languages as well. I don't think the ASL structure will change, either at all, or so much as to break the C wrappers.
@dpo the majority of OS X users of Julia don't have a compiler installed, and we don't require them to do so for JuliaOpt packages.
But anyway packaging binaries on OS X is relatively easy by using the internal Homebrew.jl bottles.
We can stick with the C wrappers if we really need to, but it makes distributing Windows binaries a good deal messier. Would need to either patch them in as additional source files and libraries in the CMakeLists.txt of ampl/mp, or make a separate download for them.
Where's the definition of the ASL struct, by the way?
@mlubin here, I think: https://github.com/ampl/mp/blob/03e7e60a678ad88212670962a6d6fb976526536a/src/asl/solvers/asl.h#L620-L624
It does look like the binary layout of the ASL struct has changed as recently as a few months ago, so will want to be sure all platforms are referring to the same version of ASL.
@tkelman Actually there are several ASL structures. The one you linked to is linear. There is also a nonlinear version here: https://github.com/ampl/mp/blob/03e7e60a678ad88212670962a6d6fb976526536a/src/asl/solvers/nlp.h#L214-L219, and two more here: https://github.com/ampl/mp/blob/03e7e60a678ad88212670962a6d6fb976526536a/src/asl/solvers/psinfo.h#L285-L303. They do change from time to time.
Thanks @vitaut. To you and @dpo, what would you think of moving the jampl.c
wrapper into the upstream repository and building it as an optional solver? Maybe with a different name. Or would there already be a generic C-API solver that could provide the same functionality built-in?
Having a simple C API that doesn't depend on accessing internal structures would also be useful for calling asl from a number of other high-level languages that have C FFIs.
I am fine with moving the C wrapper with some minor changes to https://github.com/ampl/mp if that's OK with @dpo and if it can be distributed under our usual MIT license. It should probably be a library as it is now rather than a solver (executable). The easiest is to make it a part of asl-shared
.
Out of curiosity, how does https://github.com/ampl/mp relate to www.ampl.com and the official ASL? I see the official logo on https://github.com/ampl. @vitaut Are you affiliated with AMPL LLC? Is the ASL you distribute identical to the official one?
Wanted to follow up on this to see if we can make some progress ahead of INFORMS. @dpo, are you okay with relicensing the C wrapper so it can be included in ampl/mp?
Looks like yes? d74150bb3c1540c04dbc9e9754bb1e6dd302ac1c
Sorry I've been so caught up with other stuff. I'd be happy for ampl.jl to be distributed with ampl/mp but I'd like to keep this repo as is as the main development area of Julia/AMPL. Is it possible to pull this repo as a submodule of ampl/mp?
@dpo I think what would be best is factoring things out so any C code wrappers could be contributed to ampl/mp, and all Julia code stays here. That will make managing binaries across all platforms much easier.
@tkelman That's a good idea.
@vitaut:
ampl.jl
is with Homebrew. Would it be better to change the asl.rb
Homebrew formula to pull your releases instead of Dave's Would it be better to change the asl.rb Homebrew formula to pull your releases instead of Dave's which are never versioned (and cause infinite trouble)?
+1
On Windows, I'm not sure what to do.
I got it covered. https://build.opensuse.org/package/show/home:kelman:mingw-coinor/mingw64-ampl-mp will allow us to use WinRPM.
@dpo Thanks for relicensing the code.
- Would it be better to change the asl.rb Homebrew formula to pull your releases instead of Dave's who are never versioned (and cause infinite trouble)?
Sounds good. The ASL in ampl/mp repo is regularly updated, so there shouldn't be any difference apart from new the versioning.
- How should I migrate the C wrapper to ampl/mp? Submit a PR?
PR would be great. Alternatively, I can add this repo as an optional submodule of ampl/mp as it is done with other modules like gsl or gecode.
I have nothing to contribute at the moment, but happy to see things moving along!
Thanks for going through with the PR @dpo, and for merging it @vitaut. Is the code in the upstream repository usable by the Julia package yet? Assuming a near-future release gets tagged when ready with the new code in roughly the state it's in today?
Also for clarity I think this package will probably need a slightly more specific name. Maybe AmplEvaluator
or something? Since in addition to this package we will also have an AmplMathProgInterface
, and an AmplNlWriter
(or similar), all serving slightly different purposes and with slightly different dependency directions.
@tkelman When @vitaut is ready to make a new release with the interface built into the shared lib, I'll be able to test.
We'll need the Homebrew formula for asl
to be accepted in Homebrew.jl
. Once that's done, writing a build.jl
shouldn't be too difficult.
Regarding the name, how about AmplModel
? That's already the name of the main type actually.
Can you test on master to see if there are any issues ahead of time? (temporarily do something like https://github.com/ampl/mp/archive/$sha.tar.gz
) Or does it still need work to build into the shared lib?
This package can only import and evaluate functions from a model that's been previously created elsewhere, right? So this isn't creating models straight from mathematical formulations in Julia code quite like JuMP/Convex do, it's primarily importing models that are created in AMPL? Or is there the capability here of populating an AMPL model entirely from Julia code?
The build system still needs work to build the shared lib.
No, this package doesn't create AMPL mod
and dat
files. It imports nl
files and provides a convenient interface. Maybe AmplNlReader
is better then?
AmplNlReader
(or AmplNLReader
?) sounds good to me. This will fit in with the ecosystem of AMPL-related packages that will soon be published and also makes it more clear that the package is not a replacement for AMPL.
The feature/libasl
branch prepares for the external library. There is a tentative build.jl
that builds from source or picks up the libraries build via Homebrew. For now the OSX build fails on Travis because libasl
doesn't yet include the new interface, and the Linux build fails because Ubuntu 12.04 has an outdated cmake
.
I updated build.jl
to build the latest libasl
, but it seems it's not being detected. The odd thing is that if I brew install asl
, then the version previously installed by BinDeps is detected. Anything seems wrong in build.jl
?
Looks like it should work, not sure? Try adding a dlopen
of the dylib, see if there's an error message?
The [:libasl => :libasl]
will give a deprecation warning that can be avoided with the Compat.jl package via @compat @BinDeps.install Dict(:libasl => :libasl)
, that will let you use the deps.jl
cached file to avoid requiring BinDeps at runtime - it's only necessary for Pkg.build
, not using
the package.
libasl.so
doesn't properly specify a dependency on libmp:
ERROR: could not load module /home/mlubin/.julia/v0.3/ampl/deps/usr/lib/libasl.so: libmp.so.1: cannot open shared object file: No such file or directory
in dlopen at c.jl:19
also ldd -r libasl.so
lists tons of missing symbols.
CC @vitaut
Okay, there is a dependency on libmp.so.1
but without a path. So this would work if LD_LIBRARY_PATH
was set, although this shouldn't be needed at all.
I removed the [:libasl => :libasl]
altogether. I suppose there's no harm in also exporting libmp
. And ampl.jl
now include
s deps.jl
. Is that what you meant?
On OSX, I get
$ otool -L ~/.julia/v0.3/ampl/deps/usr/lib/libasl.dylib
/Users/dpo/.julia/v0.3/ampl/deps/usr/lib/libasl.dylib:
@rpath/libasl.1.dylib (compatibility version 1.0.0, current version 1.4.0)
@rpath/libmp.1.dylib (compatibility version 1.0.0, current version 1.4.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
Perhaps -rpath
wasn't specified when building the dynamic lib?!
@mlubin Sorry, forgot to update the so versions which could cause missing symbols if wrong version of the library is picked up. Fixed in https://github.com/ampl/mp/releases/tag/2.0.1. I'll have a look why libmp
dependency is not working. Probably need to set rpath or something.
@vitaut I'm still having the same issue.
@dpo If you mean the dependency issue, then I haven't looked into it yet. A trivial workaround is to link with both libasl
and libmp
.
There could be a way to force BinDeps to load libmp
before libasl
, wasn't able to figure it out though.
According to CMake RPATH handling, CMake clears the RPATH when installing targets. So libasl.so
will find libmp.so
if it is installed in one of the standard library directories (tested on Linux). Feel free to submit an issue or a PR to AMPL/MP if you want it to be found in non-standard locations.
Might help if we try manually setting -DCMAKE_INSTALL_RPATH=$prefix/lib
?
So compilation from source via BinDeps is working now. @tkelman, is asl already in opensuse?
Yes - https://build.opensuse.org/package/show/windows:mingw:win64/mingw64-ampl-mp @vitaut you may want to have a look at a patch the opensuse guys added, I think they bumped to gcc 5.1.0 and that may have introduced a problem that they added a patch to fix. I'll try to see if I can reproduce the issue at some point.
It looks like there's a dependency now on an unregistered "NLP.jl" package, which I don't think is appropriately named, nor does it contain enough information to actually be fully useful. It looks like it's just storing counts of variables and different types of constraints, but if this package and CUTEst.jl both want to use the same data structure I think the type could probably be added to MathProgBase?
The idea is to merge whatever's in NLP.jl
that isn't already in MathProgBase
into MathProgBase
when it's ready. Currently, NLP.jl
helps me experiment with modifying optimization problems in place.
Almost all of the information in the NLP.jl structure is available through the MathProgBase nonlinear interface, but perhaps in a less convenient form for using it to transform problems when writing a solver. I'd like to see some convergence between the two interfaces, but as a short-term solution I think it would be okay to just move the data structure into MathProgBase
. This would let us move forward with registering this package and moving it into JuliaOpt, that is, if you (@dpo) believe that the package is ready.
@mlubin Sure that sounds good to me. I think ampl.jl
is in good shape and I'd like to consolidate everything as well.
@tkelman The issue with GCC 5 is fixed in https://github.com/ampl/mp/commit/40c1f7fbf4a1647c6fadb9969343a68d244b8e48, thanks!
@dpo, ready to go ahead with this? The next steps are to rename the package to AmplNLReader
(as discussed) and publish what's in the develop branch in metadata.
And uncomment the WinRPM lines in deps/build.jl
(the package on opensuse is named "ampl-mp"
, not "asl"
though), add @windows WinRPM
to REQUIRE
, and turn on appveyor
Almost there. Any idea why this would fail on win32 and nowhere else? https://ci.appveyor.com/project/dpo/amplnlreader-jl/build/1.0.4/job/jrdgtr5bp8vf3b8d#L62
Integer literals being 32 bit there, probably. Would likely also fail on 32 bit Linux but that's kinda tricky to get working on Travis.
ERROR: `convert` has no method matching convert(::Type{Array{Int64,1}}, ::UnitRange{Int32})
in NLPModelMeta at C:\Users\appveyor\.julia\v0.3\MathProgBase\src\NLP\nlp_types.jl:108
in AmplModel at C:\Users\appveyor\.julia\v0.3\AmplNLReader\src\AmplNLReader.jl:74
Continuing the discussion from #4, this package would be a good addition for JuliaOpt. Here's a checklist of what needs to be done:
CC @IainNZ @tkelman