PKG Add nlopt package (#1034)

This commit is contained in:
Michael Greminger 2021-01-07 12:22:38 -06:00 committed by GitHub
parent 7ac95d0259
commit 3e89750d16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 234 additions and 0 deletions

View File

@ -19,6 +19,7 @@ Additional build prerequisites are:
- PyYAML
- FreeType 2 development libraries to compile Matplotlib.
- Cython to compile SciPy
- SWIG to compile NLopt
- gfortran (GNU Fortran 95 compiler)
- [f2c](http://www.netlib.org/f2c/)
- [ccache](https://ccache.samba.org) (optional) *highly* recommended for much faster rebuilds.
@ -30,6 +31,7 @@ On Mac, you will also need:
- coreutils for md5sum and other essential Unix utilities (`brew install coreutils`)
- cmake (`brew install cmake`)
- Cython to compile SciPy (`brew install cython`)
- SWIG to compile NLopt (`brew install swig`)
- pkg-config (`brew install pkg-config`)
- openssl (`brew install openssl`)
- gfortran (`brew cask install gfortran`)

23
packages/nlopt/meta.yaml Normal file
View File

@ -0,0 +1,23 @@
package:
name: nlopt
version: 2.7.0
source:
url: https://github.com/stevengj/nlopt/archive/v2.7.0.tar.gz
sha256: b881cc2a5face5139f1c5a30caf26b7d3cb43d69d5e423c9d78392f99844499f
extras:
-
- src/setup.py
- ./setup.py
requirements:
run:
- numpy
build:
cxxflags: -std=c++11
test:
imports:
- nlopt

159
packages/nlopt/src/setup.py Normal file
View File

@ -0,0 +1,159 @@
#!/usr/bin/env python
import os
import re
from pathlib import Path
from subprocess import check_call
from setuptools import setup, Extension
from setuptools.command.build_py import build_py
from numpy import get_include
def create_pkg_directory():
with open("CMakeLists.txt") as f:
content = f.read()
version = []
for s in ("MAJOR", "MINOR", "BUGFIX"):
m = re.search(f"NLOPT_{s}_VERSION *['\"](.+)['\"]", content)
version.append(m.group(1))
version = ".".join(version)
pkg_folder = Path("nlopt")
pkg_folder.mkdir(exist_ok=True)
with (pkg_folder / "__init__.py").open("w") as f:
f.write(
f"""
from .nlopt import *
__version__ = '{version}'
""".strip()
+ "\n"
)
return version
def configure_with_cmake():
# There are 2 header files that are created by cmake (nlopt_config.h
# and nlopt.hpp)
# cmake is used to configure only, actual compile will be handled
# by setuptools build_ext
cmd = [
"emcmake",
"cmake",
"-LAH",
"-DNLOPT_GUILE=OFF",
"-DNLOPT_MATLAB=OFF",
"-DNLOPT_OCTAVE=OFF",
".",
]
check_call(cmd, env=os.environ)
# Need to generate nlopt.hpp
cmd = [
"emcmake",
"cmake",
"-DAPI_SOURCE_DIR=./src/api",
"-P",
"./cmake/generate-cpp.cmake",
]
check_call(cmd, env=os.environ)
version = create_pkg_directory()
class build_py_after_build_ext(build_py):
def run(self):
configure_with_cmake()
self.run_command("build_ext")
return super().run()
setup(
name="nlopt",
version=version,
packages=["nlopt"],
install_requires=["numpy >=1.14"],
ext_modules=[
Extension(
"nlopt._nlopt",
[
"src/algs/direct/DIRect.c",
"src/algs/direct/direct_wrap.c",
"src/algs/direct/DIRserial.c",
"src/algs/direct/DIRsubrout.c",
"src/algs/cdirect/cdirect.c",
"src/algs/cdirect/hybrid.c",
"src/algs/praxis/praxis.c",
"src/algs/luksan/plis.c",
"src/algs/luksan/plip.c",
"src/algs/luksan/pnet.c",
"src/algs/luksan/mssubs.c",
"src/algs/luksan/pssubs.c",
"src/algs/crs/crs.c",
"src/algs/mlsl/mlsl.c",
"src/algs/mma/mma.c",
"src/algs/mma/ccsa_quadratic.c",
"src/algs/cobyla/cobyla.c",
"src/algs/newuoa/newuoa.c",
"src/algs/neldermead/nldrmd.c",
"src/algs/neldermead/sbplx.c",
"src/algs/auglag/auglag.c",
"src/algs/bobyqa/bobyqa.c",
"src/algs/isres/isres.c",
"src/algs/slsqp/slsqp.c",
"src/algs/esch/esch.c",
"src/api/general.c",
"src/api/options.c",
"src/api/optimize.c",
"src/api/deprecated.c",
"src/api/f77api.c",
"src/util/mt19937ar.c",
"src/util/sobolseq.c",
"src/util/timer.c",
"src/util/stop.c",
"src/util/redblack.c",
"src/util/qsort_r.c",
"src/util/rescale.c",
"src/algs/stogo/global.cc",
"src/algs/stogo/linalg.cc",
"src/algs/stogo/local.cc",
"src/algs/stogo/stogo.cc",
"src/algs/stogo/tools.cc",
"src/algs/ags/evolvent.cc",
"src/algs/ags/solver.cc",
"src/algs/ags/local_optimizer.cc",
"src/algs/ags/ags.cc",
"src/swig/nlopt.i",
],
include_dirs=[
"./src/util",
"./",
"./src/api",
"./src/algs/praxis",
"./src/algs/direct",
"./src/algs/stogo",
"./src/algs/ags",
"./src/algs/cdirect",
"./src/algs/luksan",
"./src/algs/crs",
"./src/algs/mlsl",
"./src/algs/mma",
"./src/algs/cobyla",
"./src/algs/newuoa",
"./src/algs/neldermead",
"./src/algs/auglag",
"./src/algs/bobyqa",
"./src/algs/isres",
"./src/algs/esch",
"./src/algs/slsqp",
get_include(),
],
swig_opts=["-c++", "-interface", "_nlopt", "-outdir", "./nlopt"],
)
],
zip_safe=False,
cmdclass={"build_py": build_py_after_build_ext},
)

View File

@ -0,0 +1,50 @@
def test_nlopt(selenium):
selenium.load_package("nlopt")
assert selenium.run(
"""
import numpy as np
import nlopt
# objective function
def f(x, grad):
x0 = x[0]
x1 = x[1]
y = 67.8306620138889-13.5689721666667*x0-3.83269458333333*x1+\
0.720841066666667*x0**2+0.3427605*x0*x1+\
0.0640322916666664*x1**2
grad[0] = 1.44168213333333*x0 + 0.3427605*x1 - 13.5689721666667
grad[1] = 0.3427605*x0 + 0.128064583333333*x1 - 3.83269458333333
return y
# inequality constraint (constrained to be <= 0)
def h(x, grad):
x0 = x[0]
x1 = x[1]
z = -3.72589930555515+128.965158333333*x0+0.341479166666643*x1-\
0.19642666666667*x0**2+2.78692500000002*x0*x1-\
0.0000104166666686543*x1**2-468.897287036862
grad[0] = -0.39285333333334*x0 + 2.78692500000002*x1 + 128.965158333333
grad[1] = 2.78692500000002*x0 - 2.08333333373086e-5*x1 + 0.341479166666643
return z
opt = nlopt.opt(nlopt.LD_SLSQP, 2)
opt.set_min_objective(f)
opt.set_lower_bounds(np.array([2.5, 7]))
opt.set_upper_bounds(np.array([7.5, 15]))
opt.add_inequality_constraint(h)
opt.set_ftol_rel(1.0e-6)
x0 = np.array([5, 11])
xopt = opt.optimize(x0)
np.linalg.norm(xopt - np.array([2.746310775, 15.0])) < 1e-7
"""
)