Library / SDK
stevengj/nlopt avatar
stevengj/nlopt

NLopt: one interface over many nonlinear optimization algorithms

library for nonlinear optimization, wrapping many algorithms for global and local, constrained or unconstrained, optimization

2,280 stars685 forksCNOASSERTION

At a glance

What is it?
A C library that wraps a collection of free nonlinear optimization algorithms behind a single API, with bindings for a dozen languages. The interesting engineering is in the wrapper rather than the math.
Who is it for?
NLopt fits a specific job: you have a nonlinear problem, you want to compare gradient and derivative-free solvers without rewriting your code for each, and you want that choice to stay visible in your source rather than hidden behind one library's opinion.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 128 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What NLopt actually is: a wrapper with a stable surface

The README is short and precise about the scope. NLopt is a library for nonlinear local and global optimization, for functions with and without gradient information, designed as a simple unified interface and packaging of several free and open-source nonlinear optimization libraries.

That last clause is the whole design. The algorithms are not the project; the consistent API across them is. Once you have set up an objective function, bounds and constraints through one set of calls, swapping the solver underneath is a configuration change rather than a rewrite. For research code and parameter tuning, that property is usually the reason to reach for it.

The two axes in that description are worth keeping separate, because they are independent choices. Local versus global determines whether you can expect the best answer in a region or only a good point found without knowing where the basin is. Constrained versus unconstrained determines whether you supply bounds, inequality constraints or nothing at all. A method that is excellent on one combination can be the wrong tool on another, which is why a library that exposes the choice rather than hiding it is useful even when you only ever use two algorithms.

The gradient distinction follows from that and matters most in practice. NLopt works for functions with and without gradient information, so a simulation that can only return a scalar cost still fits, at the price of methods that would otherwise converge faster. If your problem has cheap analytic gradients and you are choosing a method, excluding derivative-free solvers is often the single biggest win available.

The README hands installation off to readthedocs, and says so plainly

There is no build recipe in the README. Installation instructions are a link to the hosted manual, and the manual is where a first-time user is expected to go. That is a deliberate boundary rather than an omission, and the README states it in one sentence: to build it, refer to the installation instructions.

What the repository itself tells you is the shape of the build. The tree carries CMakeLists.txt and CMakePresets.json, plus cmake/ for modules, src/ for the sources, test/ for the test suite, and nlopt.pc.in and nlopt_config.h.in as the inputs to a generated pkg-config file and a generated config header. So the project builds with CMake and installs as a library that other tools can locate through pkg-config. Presets are the modern way to encode build configurations, which suggests the project supports a configure-and-build flow rather than a hand-written Makefile.

For a rough shape of what that looks like, the generic CMake sequence is:

bash
cmake .
make

Treat those two lines as orientation rather than as the project's instructions. The actual flags, the options for building the optional language bindings, and the install step live in the hosted manual, and the presence of CMakePresets.json means the preset names are probably the better entry point if your CMake is recent enough to use them.

Downloads are handled the same way. Rather than describing platforms or package managers, the README points at the releases page on GitHub for the latest version and at readthedocs for the manual.

Language bindings are the reason most people arrive here

The README lists interfaces for C, C++, Fortran, Python, Matlab and GNU Octave, OCaml, GNU Guile, GNU R, Lua, Perl, Rust, Ruby, Julia and Java, and says interfaces for other languages may be added in the future. That is an unusually broad surface, and the documentation behind it is per-language, with separate reference manuals for C, C++, Fortran, Python, Matlab and Guile, and Java.

Not all of these are equal, and the README's own formatting makes that clear. Several entries link to third-party projects rather than to pages on readthedocs: OCaml points at a Bitbucket repository, GNU R at a university page, Lua, Rust, Perl and Julia at their own repositories, and Ruby at a separate project. Java is the recent exception, since the 2.10.0 release notes record new Java bindings in this repository.

So there are two categories of binding and the practical consequence is about support. A binding maintained in this repository is released and documented alongside the C core. A binding hosted elsewhere is a separate project with its own release cycle, and a mismatch between its expected NLopt version and the C library you installed is a realistic failure. If you are choosing a language, check which category the binding for that language falls into before you commit to a version plan.

The C reference manual is what everything else is generated from conceptually, so it is also the reference to consult when a wrapper's behaviour is unclear.

Release notes that describe parameter tuning rather than features

The 2.11.0 release, published on 2026-06-05, added two parameters for the CCSA and MMA methods, `inner_gradients` and `always_improve`, along with assorted minor bug fixes. The 2.10.1 release four months earlier is a pure defect list: an Octave 10.x build fix, an SLSQP constraints count fix, a build fix for libstdc++ debug iterators, and a PRAXIS evaluations count fix.

Read those together and they describe a library in a mature phase. Adding a named parameter to specific methods is not new capability, it is giving callers control over behaviour those methods already had. Fixing a constraints count and an evaluations count is not new functionality either; those are numbers that were being reported incorrectly, which matters because a wrong count changes how you interpret a run.

The 2.10.0 release is the one with an item worth quoting, because it is a compatibility decision rather than a fix. It restored the `LD_LBFGS_NOCEDAL` enum value, which had been dropped in 2.9, specifically to ease backwards compatibility for wrappers in other languages, while noting in the same line that the algorithm is currently unimplemented. So the constant exists to keep existing code compiling, not because the algorithm behind it is available.

That same release also added the ability to disable exceptions with `set_exceptions_enabled`, which is the kind of option that matters when you are calling from a language whose error model does not use exceptions, or when you are on a boundary where throwing is unacceptable.

Licence metadata says NOASSERTION while the tree ships COPYING and COPYRIGHT

The repository's licence field reports NOASSERTION, which is GitHub's way of saying its licence detection did not recognise a standard licence identifier. At the same time, the file tree contains both a COPYING file and a COPYRIGHT file. Those two facts are recorded here side by side because picking one for the reader would be a guess.

A repository that vendors algorithms from many authors is exactly the case where the answer is not a single MIT or BSD string. The upstream solvers NLopt wraps carry their own terms, which is likely why the project carries explicit COPYING and COPYRIGHT documents instead of a single licence identifier at the root. NOASSERTION may simply reflect that the root has no licence file GitHub recognises as a standard one.

The way to settle it is to read the two documents. Open COPYING for the terms applying to the distribution as a whole, and COPYRIGHT for the per-file or per-algorithm attributions that tell you which upstream solvers are included and under what terms. If you are considering this for a product you intend to ship, those files are the ones to read, and the AUTHORS file in the tree is a useful third reference for who wrote what.

Choosing an algorithm when the library will not choose for you

Because NLopt exposes the algorithm as configuration, the documentation on algorithm selection matters more than usual, and it is not on the README page. The hosted manual is where the methods and their properties are described. What the README does establish is the frame you should be choosing within, and it is worth being blunt about how wide that frame is.

The search questions people bring to this library are mostly about the underlying mathematics, not about NLopt. That is a reasonable instinct and it also points at the main risk: picking a method from a general description of nonlinear optimization and then discovering your problem has equality constraints, or a discontinuous region, or an objective that is cheap to evaluate but expensive to differentiate.

The mitigations are all in the project's structure rather than in any single document. Read the per-method reference before committing, because a wrapper's uniformity does not extend to each solver's convergence behaviour or its tolerance parameters. If you plan to tune stopping criteria, notice that 2.10.0 made the `tolg` tolerance parameter configurable for the Luksan gradient stopping condition, which is the kind of knob that only matters once you know you need it.

One last practical note on the packaging. Since the core is C and the library installs through CMake with a generated pkg-config file, a pure-Ruby or pure-Rust deployment without a C toolchain needs a prebuilt or vendored copy. That is the constraint most likely to decide the question for a serverless function.

Editorial conclusion

NLopt fits a specific job: you have a nonlinear problem, you want to compare gradient and derivative-free solvers without rewriting your code for each, and you want that choice to stay visible in your source rather than hidden behind one library's opinion. It is the wrong dependency when you need guarantees about convergence for a single method, when a compiled C core is a problem for your deployment, or when you want the solver's own documentation, which lives outside this project. Start at the hosted manual linked from the README, confirm the licence position by reading COPYING and COPYRIGHT yourself, and pick your algorithm by constraint structure rather than by the one you have used before.

Frequently asked questions

How do I install NLopt?

The README does not give commands and points to the installation instructions in the hosted manual instead. The repository builds with CMake, carrying a CMakeLists.txt, CMakePresets.json and a cmake/ directory, and produces a library described through a generated pkg-config file. Releases are downloaded from the GitHub releases page.

Which programming languages can I call NLopt from?

The README lists C, C++, Fortran, Python, Matlab and GNU Octave, OCaml, GNU Guile, GNU R, Lua, Perl, Rust, Ruby, Julia and Java. Java bindings were added in the 2.10.0 release, while several others such as OCaml, Lua, Rust, Perl and Julia live in separately maintained third-party projects.

What licence is NLopt released under?

The repository's licence field reports NOASSERTION, meaning no standard licence was detected, while the file tree ships both COPYING and COPYRIGHT documents. The two together suggest per-algorithm terms from the upstream solvers rather than one blanket licence, so read those files rather than assuming a single identifier.

Official sources

  1. Issues
  2. README
  3. Releases
  4. stevengj/nlopt on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/stevengj-nlopt.svg)](https://hysenlabs.com/projects/stevengj-nlopt)