Library / SDK
mlpack/ensmallen avatar
mlpack/ensmallen

ensmallen: a header-only C++ optimizer library you drop into an existing build

A header-only C++ library for numerical optimization --

815 stars141 forksC++NOASSERTION

At a glance

What is it?
ensmallen is a header-only C++14 library for non-linear numerical optimization, from L-BFGS and SGD to CMAES and simulated annealing. It is aimed at C++ developers who already use Armadillo and want optimizers without a build-system dependency.
Who is it for?
Adopt ensmallen if you write C++ numerical code against Armadillo and want L-BFGS, SGD, CMAES or simulated annealing without adding a compiled library to your build. Do not adopt it if your stack is Python, or if you need a solver outside the optimizer families the documentation lists.
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 19 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 September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The gap ensmallen fills for C++ numerical code

Most optimization libraries arrive as a compiled dependency: a shared object to link, a package to install, a version to pin. ensmallen takes the opposite route. It is a header-only C++ library, so the optimizers become part of your translation unit rather than a separate artifact your build has to find at link time. The README describes it as "a high-quality C++ library for non-linear numerical optimization" and lists gradient descent techniques, gradient-free optimizers, and constrained optimization among the categories it covers.

The audience is narrow and specific. You need a C++ compiler with C++14 support, Armadillo version 10.8.2 or later, and a BLAS or LAPACK implementation such as OpenBLAS, Intel MKL or LAPACK. If your project already uses Armadillo for matrix types, ensmallen slots in without introducing a second linear algebra convention. If you work in Python, R or Julia, this library is not for you; there is no binding mentioned in the README, and the whole design assumes you are compiling C++.

The named optimizers in the README are L-BFGS, SGD, CMAES and Simulated Annealing. That list is illustrative rather than exhaustive, and the README points to ensmallen.org for the full documentation. Treat the README as a signpost, not a catalogue.

How the header-only design actually works

The repository layout makes the mechanism visible. The top level contains include/, and inside it the README refers to a single entry header, include/ensmallen.hpp, plus a directory, include/ensmallen_bits. That split matters. ensmallen.hpp is the umbrella header you include; ensmallen_bits holds the per-optimizer implementation headers that the umbrella pulls in. Because everything is a header, there is no compilation step for the library itself and no ABI to match between your code and a prebuilt binary.

The cost of that design is compile time and code bloat. Every translation unit that includes the umbrella header instantiates whatever it uses, and template-heavy optimizer code is not free to compile. The README does not discuss build-time impact or suggest including narrower headers instead of the umbrella, so a reader who cares about incremental build times has to measure it. A second consequence is that bug fixes arrive as source changes: upgrading means replacing headers and recompiling, not swapping a shared library.

The library also supports optional callbacks, which the README mentions as a way to customize the optimization process. That is the extension point for logging, early stopping or per-iteration inspection, and it is the part most worth reading the full documentation for, since the README gives no signature or example.

Installing ensmallen with cmake, or without root

The README gives two installation paths. The cmake route checks requirements and can optionally build the tests. With root access, the sequence is the standard out-of-source build. Note that the README's example uses sudo make install, so it writes into a system prefix by default.

bash
mkdir build
cd build
cmake ..
sudo make install

Without root, the same commands take a prefix pointing at a directory you own. The README uses /home/blah/ as its placeholder and notes that this creates /home/blah/include/ and places all ensmallen headers there. Adapt the path to your own home directory.

bash
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/home/blah/
make install

If you want to run the test suite, the README adds two commands after cmake has run. The first builds the test binary, the second runs it with a durations report.

bash
make ensmallen_tests
./ensmallen_tests --durations yes

Manual installation skips cmake entirely: copy include/ensmallen.hpp and the associated include/ensmallen_bits directory into a location your compiler searches, such as /usr/include/. The README stresses that both the header and the directory are needed. cmake 3.3 or later is required for the cmake route, and cmake.org is where the README says to get it.

Compiling and running a first optimization

Once the headers are in place, compilation depends on where they landed. For a standard location such as /usr/include/, the README's command links Armadillo and enables optimization.

bash
g++ prog.cpp -o prog -O2 -larmadillo

For a non-standard prefix, add an include path. The README gives the gcc and clang form with -I.

bash
g++ prog.cpp -o prog -O2 -I /home/blah/include/ -larmadillo

For actual usage, the README points at example.cpp in the repository root and says it demonstrates the L-BFGS optimizer in a linear regression setting. That file is the concrete starting point: read it, compile it with one of the commands above, and use it as the template for your own objective function. The README does not reproduce the example inline, so the repository file is the reference rather than the prose. If you want the optimizer list beyond L-BFGS, SGD, CMAES and simulated annealing, the README defers to ensmallen.org.

Where ensmallen is the wrong choice

The header-only model has a real failure mode that the README does not address: nothing in the installation description covers uninstalling or downgrading. There is no package manager entry described, no versioned install target, and no rollback procedure. If you install into a system prefix with sudo make install and later need the previous release, you are reversing a file copy by hand. The repository does carry an UPDATING.txt file at the top level, which suggests upgrade guidance exists, but the README does not summarize it, so read that file before you upgrade a production build.

The dependency floor is another boundary. Armadillo 10.8.2 or later and a C++14 compiler are hard requirements, and the README offers no fallback for older toolchains. On a locked-down platform with an older Armadillo, ensmallen is simply unavailable.

Finally, this is a numerical optimization library, not a machine learning framework. The topics list includes deep-learning and machine-learning, and the contributor list is long, but the README describes optimizers and callbacks, not model training pipelines, data loading or serialization. If you want an end-to-end training stack, this is a component, not a solution.

ensmallen and mlpack: related, not interchangeable

The related searches pair ensmallen with Mlpack, and the connection is real: ensmallen grew out of the mlpack machine learning library and shares maintainers and an Armadillo foundation. The difference in approach is scope. mlpack is a full machine learning library with methods and models built on top of optimization; ensmallen is the optimization layer alone, extracted so it can be used by code that has no interest in the rest of mlpack.

That extraction is the point. If you already depend on mlpack, ensmallen is likely present transitively and you may not need to think about it. If you have your own C++ codebase and only need a minimizer, pulling in mlpack to reach L-BFGS would be the heavier choice, and ensmallen is the lighter one. The reverse also holds: choosing ensmallen when you actually want classifiers, clustering or model serialization means assembling those yourself. The README does not compare the two, so this is a judgement about scope rather than a claim from the documentation.

Licence, maintenance and the cost of upgrades

The README states that, unless stated otherwise, the source code is licensed under the 3-clause BSD license, with a copy in LICENSE.txt and a link to the Open Source Initiative text. The repository metadata reports the licence as NOASSERTION, which means the automated classifier could not resolve it. Those two facts are not in conflict, but they do mean you should open LICENSE.txt and COPYRIGHT.txt rather than rely on a badge. The permissive BSD terms are the kind that generally allow commercial and closed-source use, but that is a general property of the licence family, not legal advice, and the COPYRIGHT.txt file may carve out exceptions the README's "unless stated otherwise" phrase hints at.

Maintenance looks current by the only measure available here. The repository is not archived, and the last push was on 2026-08-12. Releases are named and versioned: 3.10.0 ("Unexpected Rain") on 2025-09-30, 3.11.0 ("Sunny Day") on 2025-12-16, and 3.11.1 ("Sunny Day") on 2026-07-29. The gap between 3.11.0 and 3.11.1 is a patch release roughly seven months after the minor, which fits a steady rather than rapid cadence.

Upgrade cost is where the header-only design bites. There is no soname to track and no link-time compatibility question, but there is also no binary compatibility guarantee to lean on. A new release means recompiling everything that includes the headers, and the README does not document rollback if a new version changes optimizer behaviour in your pipeline. The UPDATING.txt file in the repository root is the place to look, and the HISTORY.md file records what changed between releases.

Editorial conclusion

Adopt ensmallen if you write C++ numerical code against Armadillo and want L-BFGS, SGD, CMAES or simulated annealing without adding a compiled library to your build. Do not adopt it if your stack is Python, or if you need a solver outside the optimizer families the documentation lists. Before committing, verify two things: that your compiler and Armadillo version meet the C++14 and 10.8.2 requirements, and that the optimizer you need appears in the documentation at ensmallen.org, since the README names only a handful of examples. The repository's last push was on 2026-08-12, so the codebase is current, but the licence file resolves as NOASSERTION on the repository metadata, so read LICENSE.txt yourself rather than trusting a badge.

Frequently asked questions

What is ensmallen and what does it do?

ensmallen is a header-only C++ library for non-linear numerical optimization. The README lists gradient descent techniques, gradient-free optimizers and constrained optimization, with L-BFGS, SGD, CMAES and simulated annealing as named examples.

How do I install ensmallen?

The README gives a cmake route (mkdir build, cd build, cmake .., sudo make install, or the same with -DCMAKE_INSTALL_PREFIX:PATH for a prefix you own) and a manual route that copies include/ensmallen.hpp plus the include/ensmallen_bits directory into a location your compiler searches.

What are the requirements to use ensmallen?

The README lists a C++ compiler with C++14 support, Armadillo version 10.8.2 or later, and OpenBLAS, Intel MKL or LAPACK. The cmake installation checks these requirements for you.

Is ensmallen related to mlpack?

They share an Armadillo foundation and the related searches pair the two names, but the README describes ensmallen only as a standalone optimization library. mlpack is a broader machine learning library, while ensmallen is the optimization layer alone.

What licence does ensmallen use?

The README says the source code is licensed under the 3-clause BSD license unless stated otherwise, with a copy in LICENSE.txt. The repository metadata reports the licence as NOASSERTION, so read LICENSE.txt and COPYRIGHT.txt directly.

Official sources

  1. Issues
  2. mlpack/ensmallen on GitHub
  3. Project website
  4. README
  5. Releases
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/mlpack-ensmallen.svg)](https://hysenlabs.com/projects/mlpack-ensmallen)