Getting Started#

Below are short snippets providing a first glimpse of MParT usage. For more detailed examples, check out the Tutorials page and the corresponding MParT-Examples repository.

At the core of MParT’s monotone parameterizations are functions with the general form

\[T_d(\mathbf{x}_{1:d}; \mathbf{w}) = f(x_1,\ldots, x_{d-1},0; \mathbf{w}) + \int_0^{x_d} g( \partial_d f(x_1,\ldots, x_{d-1},t; \mathbf{w}) ) dt,\]

where \(\mathbf{x}\in\mathbb{R}^d\) is the function input, \(\mathbf{w}\) is a vector of parameters, and \(g:\mathbb{R}\rightarrow\mathbb{R}^+\) is positive-valued “rectifier”. The function \(f(\mathbf{x})\) is a general non-monotone function, which MParT represents with a linear expansion of the form

\[f(\mathbf{x}) = \sum_{\mathbf{\alpha}\in\mathcal{A}} w_{\mathbf{\alpha}} \Phi_{\mathbf{\alpha}}(\mathbb{x})\]

and the multivariate basis functions \(\Phi_{\mathbf{\alpha}}\) are defined through the multiindex \(\mathbf{\alpha}\in \mathbb{N}^d\) and the tensor-product of 1d basis functions, i.e.,

\[\Phi_{\mathbf{\alpha}}(\mathbb{x}) = \prod_{j=1}^d \phi_{\alpha_j}(x_j),\]

where \(\phi_{\alpha_j}\) will typically be a polynomial of order \(\alpha_j\).

The monotone component \(T_d\) is therefore defined by five main options:

  1. Which family of 1d basis functions are used to define \(\phi_{\alpha_j}\) (e.g., Hermite polynomials)

  2. The multiindex set \(\mathcal{A}\), which defines the terms that are included in the linear expansion. A common, although not always optimal, choice is to choose the set containing terms with a maximum total order, i.e., \(\mathcal{A} = \{\mathbf{\alpha} \in \mathbb{Z}^+ : \|\mathbf{\alpha}\|_1 \leq a_{max}\}\)

  3. The coefficient vector \(\mathbf{w}\in\mathbb{R}^{|\mathcal{A}|}\)

  4. The choice of rectifier function \(g\).

  5. How the integral is approximated numerically.

Overview

The code snippets below construct a single component \(T_d : \mathbb{R}^2\rightarrow \mathbb{R}\) by first defining the multiindex set \(\mathcal{A}\) and then using default options for the other choices.

The multiindex set is given by

\[\mathcal{A} = \left\{ [0,1],[2,0],[1,1] \right\}\]

After installing MParT from conda or compiling with the python bindings, you will be able to import mpart into python, create a multiindex set to define a parameterization, and then construct your first monotone function.

import mpart as mt
import numpy as np

multis = np.array([[0,1],[2,0],[1,1]])
mset = mt.MultiIndexSet(multis)
fixedSet = mset.fix(True)

opts = mt.MapOptions()
mapComponent = mt.CreateComponent(fixedSet,opts)

nc = mapComponent.numCoeffs
print(nc)

This should display 3 as the number of coefficients is equal to the number of multi-indices in the set. See Tutorials for several examples using MParT for measure transport in python.

The number of threads used by Kokkos can be set via the environment variable KOKKOS_NUM_THREADS before importing MParT, e.g.,:

import os
os.environ['KOKKOS_NUM_THREADS'] = '8'
import mpart as mt

Currently, only the Python bindings support GPU-acceleration via CUDA backend. MParT relies on templates in c++ to dictate which Kokkos execution space is used, but in python we simply prepend d to classes and functions leveraging device execution (e.g., GPU). For example, the c++ CreateComponent<Kokkos::HostSpace> function corresponds to the mt.CreateComponent while the CreateComponent<mpart::DeviceSpace> function, which will return a Monotone component that leverages the Cuda backend, corresponds to the python function dCreateComponent.

See the section Julia Source Installation for information on how to set up the Julia environment manually. After this setup, you should now be able to use MParT from Julia by including MParT as a local package. For example, the following creates a map component from a custom multi-index set in dimension 2:

using MParT

multis = [0 1;2 0;1 1]
mset = MultiIndexSet(multis)
fixedSet = Fix(mset, true)

opts = MapOptions()
mapComponent = CreateComponent(fixedSet,opts)

nc = numCoeffs(mapComponent)
print(nc)

This should display 3 as the number of coefficients is equal to the number of multi-indices in the set.

Number of threads used by Kokkos can be set via the environment variable KOKKOS_NUM_THREADS, e.g.,

export KOKKOS_NUM_THREADS=8

In Matlab you need the specify the path where the matlab bindings are installed:

addpath(genpath('<your/MParT/install/path>'))

Number of threads used by Kokkos can be set using the Matlab function KokkosInitialize e.g.,

num_threads = 8;
KokkosInitialize(num_threads);

Should now be able to use MParT in Matlab! For example, the following creates a map component from a custom multi-index set in dimension 2:

multis = [0,1;2,0;1,1];
mset = MultiIndexSet(multis);
fixedSet = mset.Fix();

opts = MapOptions();
mapComponent = CreateComponent(fixedSet,opts);

nc = mapComponent.numCoeffs;
disp(nc)

This should display 3 as the number of coefficients is equal to the number of multi-indices in the set.

Linking to MParT is straightforward using CMake. Let’s say you want to compile the following code, which simply creates a map component from a custom multiindex set.

SmallExample.cpp#
#include <Kokkos_Core.hpp>
#include <Eigen/Core>
#include <MParT/MultiIndices/MultiIndexSet.h>
#include "MParT/MultiIndices/FixedMultiIndexSet.h"
#include <MParT/ConditionalMapBase.h>
#include <MParT/MapFactory.h>


using namespace mpart;

int main(){
    args.num_threads = 8
    Kokkos::initialize(args);
    {
    Eigen::MatrixXi multis(3,2);
    multis << 0,1,
            2,0,
            1,1;

    MultiIndexSet mset = MultiIndexSet(multis);
    FixedMultiIndexSet<Kokkos::HostSpace> fixedSet = mset.Fix();

    MapOptions opts;
    std::shared_ptr<ConditionalMapBase<Kokkos::HostSpace>> mapComponent;
    mapComponent = MapFactory::CreateComponent<Kokkos::HostSpace>(fixedSet,opts);

    unsigned int nc = mapComponent->numCoeffs;
    std::cout<<nc<<std::endl;

    }
    Kokkos::finalize();
    return 0;
}

The following CMakeLists.txt file can be used to configure the executable.

CMakeLists.txt#
cmake_minimum_required (VERSION 3.13)

project(SimpleExample)

set(CMAKE_CXX_STANDARD 17)

find_package(Kokkos REQUIRED)
find_package(MParT REQUIRED)
message(STATUS "KOKKOS_FOUND = ${Kokkos_FOUND}")
message(STATUS "MPART_FOUND = ${MParT_FOUND}")

add_executable(Simple SimpleExample.cpp)
target_link_libraries(Simple MParT::mpart Kokkos::kokkos Eigen3::Eigen)

Building the Simple binary involves running cmake and then make:

mkdir build; cd build   # Create a build directory
cmake ..                # Run CMake to configure the build
make                    # Call make to build the executable
./Simple                # Run the executable

If CMake throws an error saying it couldn’t find KokkosConfig.cmake, try manually specifying the path to your MParT (or Kokkos) installations in your cmake call using X_ROOT. For example,

cmake -DCMAKE_PREFIX_PATH=<your/MParT/install/path> ..