Stan Math Library
5.0.0
Automatic Differentiation
|
Thanks for checking out these docs. This is where you'll find information on contributing to the Math library, how the source code is laid out, and other technical details that could help. This wiki focuses on things relevant to the Math library. There's also a separate Stan wiki for things related to the language, services, algorithms.
For the most up to date guide on contributing to Stan Math see the Getting Started Guide, Common Pitfalls, and Adding New Distributions Guide.
This wiki is a work in progress. If you have suggestions, please update the wiki or mention it on our forums on this thread.
The Stan Math library, referred to as Math or the Math library, is a C++ library for automatic differentiation. It's designed to be usable, extensive and extensible, efficient, scalable, stable, portable, and redistributable in order to facilitate the construction and utilization of algorithms that utilize derivatives.
The Math library implements:
Some key features of the Math library's reverse mode automatic differentiation:
For implementation details of the Math library's automatic differentiation, please read the arXiv paper "[The Stan Math Library: Reverse-Mode Automatic Differentiation in C++](https://arxiv.org/abs/1509.07164)."
We're committed to having a permissive open-source license. The Math library is licensed with the BSD 3-Clause License and we only accept changes to the code base that compatible with this license.
Thanks for reading! We love contributions from everyone in the form of good discussion, issues, and pull requests.
We reserve issues for bugs and feature requests that are defined well enough for a developer to tackle. If you have general questions about the Math library, please see the Discussion section.
Ideally, bug reports will include these pieces of information:
If there's an error and you can produce any of these pieces, it's much appreciated!
We track the development of new features using the same issue tracker. Ideally, feature requests will have:
Open feature requests should be the ones we want to implement in the Math library. We'll try to close vague feature requests that don't have enough information and move the discussion to the forums.
All changes to the Math library are handled through pull requests. Each pull request should correspond to an issue. We follow a modified GitFlow branching model for development.
When a contributor creates a pull request for inclusion to the Math library, here are some of the things we expect:
develop
branch to always be in a good statePull requests are code reviewed after they pass our continuous integration tests. We expect all the above before a pull request is merged. We are an open-source project and once code makes it into the repository, it's on the community to maintain.
It is the responsibility of the contributor submitting the pull request that the code meets these requirements. We're open-source. Once the code gets into the code base, the community of developers take ownership of it.
For general questions, please ask on the forums with the "Developers" tag.
(These are also listed on the wiki)
All pull requests must have these things:
Most of the above is subjective, so please use your best judgement.
Pull requests should be narrow in scope. Please don't let inadvertent changes get into the code base.
It would help if anyone that's knowledgable in the code base reviews code. This is also for those that aren't active developers, but can read C++ fluently!
Members of the Stan development team that contribute regularly to the Math library are allowed to merge the pull requests.
If all tests pass and the pull request has been reviewed, if no one merges, @syclik will do so (not on any schedule, but at least once a week).
Thanks! Here are some guidelines on how to review. At a high level, you're making sure the code submitted is indeed what the submitter says they have submitted. If an issue exists and is good, then it should be fixed. There are lots of ways to solve a problem – we're not always looking for the perfect solution. We're looking for something that can get into the code base without putting a maintenance burden on other developers.
Feel free to review a narrow part of the pull request. By that, I mean one of these things: build process, numerical computation, template metaprogramming. If you're reviewing a small portion of the pull request, please mention it in the comment and only mark it as a comment (not as an "Approve"). In most cases, this won't matter, but in the ones that span across different concerns, one of the core developers will coordinate the review and approve.
Nota bene: these build instructions are not in the released version yet. This is for the develop
branch (post v2.18.0. Prior to this, the build instructions are similar, but not identical.
The Math library is designed as a header-only library. Everything is included in a single translation unit.
Some of the external libraries require libraries to be linked in. These are:
Within the Math library, the only build targets are the tests (there are no other executables to build directly from Math). The makefile can be used to build other C++ executables, with all the correct compiler flags for Math.
To customize how the tests are built in C++, variables can be set in a file called make/local
. This is the preferred way of customizing the build.
There are a lot of make variables that can be set. In general, CXXFLAGS_*
is for C++ compiler flags, CPPFLAGS_*
is for C preprocessor flags, LDFLAGS_*
is for linker flags, and LDLBIS_*
is for libraries that need to be linked in.
These are the more common make flags that could be set:
CXX
: C++ compilerCXXFLAGS_OS
: compiler flags specific to the operating system.CPPFLAGS_OS
: C preprocessor flags specific to the operating system.O
: optimization level. Defaults to 3
.INC_FIRST
: this is a C++ compiler option. If you need to include any headers before Math's headers, this is where to specify it. Default is empty.LDFLAGS_OS
: linker flags for the operating systemLDLIBS_OS
: link libraries for the operating systemThese are the rest of the variables that can be set:
CXXFLAGS_LANG
: sets the language. Currently defaults to -std=c++17
CXXFLAGS_WARNINGS
: compiler options to squash compiler warningsCXXFLAGS_BOOST
: Boost-specific compiler flagsCXXFLAGS_EIGEN
: Eigen-specific compiler flagsCXXFLAGS_OPENCL
: OpenCL-specific compiler flagsCXXFLAGS_MPI
: MPI-specific compiler flagsCPPFLAGS_LANG
:CPPFLAGS_WARNINGS
CPPFLAGS_BOOST
CPPFLAGS_EIGEN
CPPFLAGS_OPENCL
CPPFLAGS_MPI
LDFLAGS_LANG
LDFLAGS_WARNINGS
LDFLAGS_BOOST
LDFLAGS_EIGEN
LDFLAGS_OPENCL
LDFLAGS_MPI
LDLIBS_LANG
LDLIBS_WARNINGS
LDLIBS_BOOST
LDLIBS_EIGEN
LDLIBS_OPENCL
LDLIBS_MPI
OS
: operating system. Defaults to Darwin
, Linux
, or WindowsNT
.MATH
: the location of the math library. Defaults to empty variable (used for Stan and CmdStan).EIGEN
: location of the Eigen headersBOOST
: location of the Boost headersSUNDIALS
: location of the Sundials headersINC
: the includes for the C++ compilerINC_SUNDIALS
: the Sundials includesINC_GTEST
: the Google test includesEXE
: the executable file extension. On Windows, defaults to .EXE
. On other operating system, defaults to an empty variable.For debugging, there's a useful target for printing Stan variables. It's print-*
where *
is the variable. For example, on a Mac:
The main function of the makefiles is to build test executables. The typical way to build test executables is to use the runTests.py
python script, but we can use make to directly generate a test executable.
The name of the test executable is the name of the test with the file extension removed for Linux and Mac or replacing the file extension with .exe
for Windows. For example, to run the test test/unit/math_include_test.cpp
, we build on Linux and Mac with:
or on Windows with:
We can then run the executable from the command line.
Along with the test executable, the makefiles generate dependency files. The dependency files are generated by using the C++ compiler to list the headers that the test depends on. The dependency file is automatically generated by make and included by make so it knows what header files the test depends on. If none of those files changed, then the executable doesn't need to be rebuilt.
We can build the dependency file directly. For the test/unit/math_include_test.cpp
example, we can build the dependency file using make:
If you look at the first couple of lines, you'll see:
Make uses the timestamp of the files to determine whether it needs to be rebuilt. If any of the files listed after the targets (after the :
) are updated, the executable will be rebuilt. If you've built all the unit tests and only change a single header file, building the unit tests again will selectively rebuild the tests that depends on that header.
The easiest way to build and run tests is to use the runTests.py
python script. To run unit tests:
The Stan testing process depends on the makefiles in Math.
Stan's development is across multiple repositories. When in doubt of which one to open an issue in, we ask that you make your best guess. We can always move it for you.
Language or compiler issues: stanc3
Algorithm issues: stan
Function or derivative issues: math
Running tests in the Stan Math Library require these libraries, which are all included in the repository:
No additional configuration is necessary to start running with the default libraries.
If you want to use custom locations for the library locations, set these makefile variables:
EIGEN
BOOST
GTEST
CPPLINT
(optional)Example make/local
file:
To run tests, you will need a copy of the Math library, a C++ compiler, make, and python 2.x (for the test script).
To run the unit tests, type:
To run the auto-generated distribution tests, type:
To run the multiple translation unit tests, type:
If you see this message:
the library paths have not been configured correctly.
To test headers,
This would have been an "faq," but nothing really gets asked frequently. We'll just collect thoughts on the Math library here.
As of v2.18 (12/2018).
We try to keep the behavior of the functions in the Math library consistent for edge cases. Unfortunately, we implemented a lot of functions before we started realizing we should be consistent. That said, we prefer backwards compatibility to consistency – we shouldn't change behavior until we get to a major version change. If we throw, we want well-formed messages because they do get passed back to the user from within Stan.
We follow these rules in order:
Without including this, Boost will assert if certain inputs do not meet the preconditions of the function. Assertions are difficult to trap and recover from and we want to continue to have control over this behavior.
See Discourse: Boost defines for more details.