├── .docker ├── Dockerfile └── environment.yml ├── .dockerignore ├── .github ├── environment.yml ├── install-doxygen.sh └── workflows │ ├── build-bindings.yml │ ├── build-doc.yml │ ├── build-external-lib-tests.yml │ ├── build-push-docker.yml │ ├── build-tests.yml │ └── pypi-deploy.yml ├── .gitignore ├── CITATION.cff ├── CMakeLists.txt ├── Config.cmake.in ├── LICENSE.txt ├── MParT ├── AffineFunction.h ├── AffineMap.h ├── ComposedMap.h ├── ConditionalMapBase.h ├── DerivativeFlags.h ├── Distributions │ ├── DensityBase.h │ ├── Distribution.h │ ├── GaussianSamplerDensity.h │ ├── PullbackDensity.h │ ├── PullbackSampler.h │ ├── PushforwardDensity.h │ ├── PushforwardSampler.h │ ├── SampleGenerator.h │ └── TransportDistributionFactory.h ├── HermiteFunction.h ├── IdentityMap.h ├── Initialization.h ├── LinearizedBasis.h ├── MapFactory.h ├── MapObjective.h ├── MapOptions.h ├── MonotoneComponent.h ├── MonotoneIntegrand.h ├── MultiIndices │ ├── FixedMultiIndexSet.h │ ├── MultiIndex.h │ ├── MultiIndexLimiter.h │ ├── MultiIndexNeighborhood.h │ └── MultiIndexSet.h ├── MultivariateExpansion.h ├── MultivariateExpansionWorker.h ├── OrthogonalPolynomial.h ├── ParameterizedFunctionBase.h ├── PositiveBijectors.h ├── Quadrature.h ├── Sigmoid.h ├── SummarizedMap.h ├── TensorProductFunction.h ├── TrainMap.h ├── TrainMapAdaptive.h ├── TriangularMap.h └── Utilities │ ├── ArrayConversions.h │ ├── EigenTypes.h │ ├── GPUtils.h │ ├── KokkosHelpers.h │ ├── KokkosSpaceMappings.h │ ├── LinearAlgebra.h │ ├── MathFunctions.h │ ├── Miscellaneous.h │ ├── RootFinding.h │ └── Serialization.h ├── README.md ├── bindings ├── common │ ├── include │ │ └── CommonUtilities.h │ └── src │ │ └── CommonUtilities.cpp ├── julia │ ├── CMakeLists.txt │ ├── include │ │ ├── CommonJuliaUtilities.h │ │ └── JlArrayConversions.h │ └── src │ │ ├── AffineMap.cpp │ │ ├── CommonJuliaUtilities.cpp │ │ ├── ComposedMap.cpp │ │ ├── ConditionalMapBase.cpp │ │ ├── JlArrayConversions.cpp │ │ ├── MapFactory.cpp │ │ ├── MapObjective.cpp │ │ ├── MapOptions.cpp │ │ ├── MultiIndex.cpp │ │ ├── ParameterizedFunctionBase.cpp │ │ ├── TrainMap.cpp │ │ ├── TrainMapAdaptive.cpp │ │ ├── TriangularMap.cpp │ │ └── Wrapper.cpp ├── matlab │ ├── CMakeLists.txt │ ├── external │ │ ├── mexplus │ │ │ ├── LICENSE │ │ │ ├── mexplus.h │ │ │ └── mexplus │ │ │ │ ├── arguments.h │ │ │ │ ├── dispatch.h │ │ │ │ ├── mxarray.h │ │ │ │ └── mxtypes.h │ │ └── mexplus_eigen.h │ ├── include │ │ ├── MexArrayConversions.h │ │ ├── MexOptionsConversions.h │ │ └── MexWrapperTypes.h │ ├── mat │ │ ├── ATMOptions.m │ │ ├── AdaptiveTransportMap.m │ │ ├── AffineMap.m │ │ ├── ComposedMap.m │ │ ├── ConditionalMap.m │ │ ├── CreateComponent.m │ │ ├── CreateTriangular.m │ │ ├── DeserializeMap.m │ │ ├── FixedMultiIndexSet.m │ │ ├── GaussianKLObjective.m │ │ ├── KokkosInitialize.m │ │ ├── MapOptions │ │ │ ├── BasisTypes.m │ │ │ ├── MapOptions.m │ │ │ ├── PosFuncTypes.m │ │ │ └── QuadTypes.m │ │ ├── MultiIndex.m │ │ ├── MultiIndexSet.m │ │ ├── ParameterizedFunction.m │ │ ├── TrainMap.m │ │ ├── TrainOptions.m │ │ └── TriangularMap.m │ ├── src │ │ ├── BasisTypes_mex.cpp │ │ ├── ConditionalMap_mex.cpp │ │ ├── FixedMultiIndexSet_mex.cpp │ │ ├── KokkosUtilities_mex.cpp │ │ ├── MapObjective_mex.cpp │ │ ├── MexArrayConversions.cpp │ │ ├── MexOptionsConversions.cpp │ │ ├── MultiIndexSet_mex.cpp │ │ ├── MultiIndex_mex.cpp │ │ └── ParameterizedFunctionBase_mex.cpp │ └── tests │ │ ├── FixedMultiIndexSetTest.m │ │ ├── Test_AffineMap.m │ │ ├── Test_ComposedMap.m │ │ ├── Test_MultiIndex.m │ │ ├── Test_MultiIndexSet.m │ │ ├── Test_ParameterizedFunction.m │ │ ├── Test_TriangularMap.m │ │ ├── TrainMapAdaptiveTest.m │ │ ├── TrainMapTest.m │ │ └── runtests.m └── python │ ├── CMakeLists.txt │ ├── include │ └── CommonPybindUtilities.h │ ├── package │ ├── __init__.py │ ├── torch.py │ └── torch_helpers.py │ ├── src │ ├── AffineMap.cpp │ ├── CommonPybindUtilities.cpp │ ├── ComposedMap.cpp │ ├── ConditionalMapBase.cpp │ ├── IdentityMap.cpp │ ├── MapFactory.cpp │ ├── MapObjective.cpp │ ├── MapOptions.cpp │ ├── MultiIndex.cpp │ ├── ParameterizedFunctionBase.cpp │ ├── Serialization.cpp │ ├── SummarizedMap.cpp │ ├── TrainMap.cpp │ ├── TrainMapAdaptive.cpp │ ├── TriangularMap.cpp │ └── Wrapper.cpp │ └── tests │ ├── test_AffineFunction.py │ ├── test_AffineMap.py │ ├── test_ComposedMap.py │ ├── test_ComposedMap_moveCoeffs.py │ ├── test_ConditionalMapBase.py │ ├── test_IdentityMap.py │ ├── test_MapFactory.py │ ├── test_MultiIndex.py │ ├── test_MultiIndexSet.py │ ├── test_Serialization.py │ ├── test_SummarizedMap.py │ ├── test_TorchWrapper.py │ ├── test_TrainMap.py │ ├── test_TrainMapAdaptive.py │ ├── test_TriangularMap.py │ └── test_TriangularMap_moveCoeffs.py ├── cmake ├── BuildDocs.cmake ├── FindJulia.cmake ├── FindSphinx.cmake └── SetInstallPaths.cmake ├── docs ├── Makefile ├── _static │ └── pics │ │ ├── Density.png │ │ ├── Regression.png │ │ ├── Samples.png │ │ └── Transformation2d.png ├── conf.py ├── index.rst ├── make.bat ├── mpart.doxyfile.in └── source │ ├── api │ ├── composedmap.rst │ ├── concepts │ │ ├── cachedparameterization.rst │ │ └── parameterizedfunction.rst │ ├── conditionalmapbase.rst │ ├── index.rst │ ├── mapfactory.rst │ ├── maptraining.rst │ ├── maptraining │ │ ├── trainmap.rst │ │ └── trainmapadaptive.rst │ ├── monotonecomponent.rst │ ├── multiindex.rst │ ├── multiindices │ │ ├── fixedmultiindexset.rst │ │ ├── multiindex.rst │ │ ├── multiindexlimiter.rst │ │ ├── multiindexneighborhood.rst │ │ └── multiindexset.rst │ ├── multivariateexpansion.rst │ ├── multivariateexpansionworker.rst │ ├── parameterizedfunctionbase.rst │ ├── quadrature.rst │ ├── quadrature │ │ ├── adaptivesimpson.rst │ │ ├── clenshawcurtis.rst │ │ └── recursivequadrature.rst │ ├── templateconcepts.rst │ ├── tensorproductfunction.rst │ ├── triangularmap.rst │ └── utilities │ │ ├── initialization.rst │ │ ├── kokkoswrappers.rst │ │ ├── linearalgebra.rst │ │ └── serialization.rst │ ├── development │ └── index.rst │ ├── getting_started.rst │ ├── installation.rst │ ├── mathematics.rst │ └── tutorials │ └── index.rst ├── joss ├── paper.bib ├── paper.md └── performance_comparison.png ├── pyproject.toml ├── setup.py ├── src ├── AffineFunction.cpp ├── AffineMap.cpp ├── CMakeLists.txt ├── ComposedMap.cpp ├── ConditionalMapBase.cpp ├── Distributions │ ├── DensityBase.cpp │ ├── GaussianSamplerDensity.cpp │ └── PullbackDensity.cpp ├── IdentityMap.cpp ├── Initialization.cpp ├── MapFactory.cpp ├── MapFactoryImpl1.cpp ├── MapFactoryImpl10.cpp ├── MapFactoryImpl11.cpp ├── MapFactoryImpl12.cpp ├── MapFactoryImpl13.cpp ├── MapFactoryImpl14.cpp ├── MapFactoryImpl15.cpp ├── MapFactoryImpl16.cpp ├── MapFactoryImpl17.cpp ├── MapFactoryImpl18.cpp ├── MapFactoryImpl2.cpp ├── MapFactoryImpl3.cpp ├── MapFactoryImpl4.cpp ├── MapFactoryImpl5.cpp ├── MapFactoryImpl6.cpp ├── MapFactoryImpl7.cpp ├── MapFactoryImpl8.cpp ├── MapFactoryImpl9.cpp ├── MapObjective.cpp ├── MultiIndices │ ├── FixedMultiIndexSet.cpp │ ├── MultiIndex.cpp │ ├── MultiIndexLimiter.cpp │ ├── MultiIndexNeighborhood.cpp │ └── MultiIndexSet.cpp ├── ParameterizedFunctionBase.cpp ├── SummarizedMap.cpp ├── TrainMap.cpp ├── TrainMapAdaptive.cpp ├── TriangularMap.cpp └── Utilities │ ├── LinearAlgebra.cpp │ └── Miscellaneous.cpp └── tests ├── CMakeLists.txt ├── Distributions ├── Test_DensityBase.cpp ├── Test_Distribution.cpp ├── Test_Distributions_Common.cpp ├── Test_Distributions_Common.h ├── Test_GaussianDistribution.cpp ├── Test_SampleGenerator.cpp ├── Test_TransportDensity.cpp ├── Test_TransportDistributionFactory.cpp └── Test_TransportSampler.cpp ├── KokkosInfo.cpp ├── MultiIndices ├── Test_MultiIndex.cpp └── Test_MultiIndexSet.cpp ├── RunTests.cpp ├── Test_AffineFunction.cpp ├── Test_AffineMap.cpp ├── Test_ArrayConversions.cpp ├── Test_ComposedMap.cpp ├── Test_ConditionalMapBase.cpp ├── Test_HermiteFunctions.cpp ├── Test_IdentityMap.cpp ├── Test_LinearAlgebra.cpp ├── Test_LinearizedBasis.cpp ├── Test_MapFactory.cpp ├── Test_MapObjective.cpp ├── Test_MonotoneComponent.cpp ├── Test_MultivariateExpansion.cpp ├── Test_MultivariateExpansionWorker.cpp ├── Test_OrthogonalPolynomials.cpp ├── Test_PositiveBijectors.cpp ├── Test_Quadrature.cpp ├── Test_RootFinding.cpp ├── Test_Serialization.cpp ├── Test_Sigmoid.cpp ├── Test_SummarizedMap.cpp ├── Test_TensorProductFunction.cpp ├── Test_TrainMap.cpp ├── Test_TrainMapAdaptive.cpp └── Test_TriangularMap.cpp /.docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM continuumio/miniconda3 2 | 3 | COPY . MParT_ 4 | 5 | RUN --mount=type=cache,target=/opt/conda/pkgs conda env create -f MParT_/.docker/environment.yml && \ 6 | conda clean -afy 7 | 8 | SHELL ["conda", "run", "-n", "mpart", "/bin/bash", "-c"] 9 | 10 | RUN git clone --depth=1 --branch 3.7.02 https://github.com/kokkos/kokkos.git && \ 11 | mkdir kokkos/build && \ 12 | cd kokkos/build && \ 13 | cmake \ 14 | -DKokkos_ENABLE_SERIAL=ON \ 15 | -DKokkos_ENABLE_OPENMP=ON \ 16 | -DBUILD_SHARED_LIBS=ON \ 17 | -DCMAKE_CXX_STANDARD=17 \ 18 | ../ && \ 19 | make -j$(nproc) && \ 20 | make install && \ 21 | cd / && \ 22 | rm -rf kokkos 23 | 24 | RUN cd MParT_ && \ 25 | mkdir build && \ 26 | cd build && \ 27 | cmake -DMPART_BUILD_TESTS=OFF -DPYTHON_EXECUTABLE=`which python` -DMPART_FETCH_DEPS=OFF ../ && \ 28 | make -j$(nproc) && \ 29 | make install && \ 30 | cd / && \ 31 | rm -rf MParT_ 32 | 33 | ENV NB_USER=bayes \ 34 | NB_UID=1000 35 | 36 | RUN useradd -m -s /bin/bash -N -u $NB_UID $NB_USER 37 | 38 | WORKDIR /home/${NB_USER} 39 | USER $NB_USER 40 | 41 | SHELL ["/bin/bash","-c"] 42 | RUN conda init && \ 43 | echo 'conda activate mpart' >> ~/.bashrc 44 | 45 | RUN echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib' >> ~/.bashrc && \ 46 | echo 'export PYTHONPATH=$PYTHONPATH:/usr/local/python' >> ~/.bashrc && \ 47 | echo 'export OMP_PROC_BIND=spread' >> ~/.bashrc && \ 48 | echo 'export OMP_PLACES=threads' >> ~/.bashrc && \ 49 | echo 'export KOKKOS_NUM_THREADS=`nproc`' >> ~/.bashrc 50 | -------------------------------------------------------------------------------- /.docker/environment.yml: -------------------------------------------------------------------------------- 1 | name: mpart 2 | channels: 3 | - conda-forge 4 | - defaults 5 | dependencies: 6 | - eigen 7 | - pybind11 8 | - catch2 9 | - nlopt 10 | - cereal 11 | - cmake 12 | - gcc 13 | - gxx 14 | - make 15 | - dill 16 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | .gitignore 3 | .docker/Dockerfile 4 | build 5 | external 6 | docs 7 | -------------------------------------------------------------------------------- /.github/environment.yml: -------------------------------------------------------------------------------- 1 | name: my-env 2 | 3 | channels: 4 | - conda-forge 5 | 6 | dependencies: 7 | - python >=3.8 8 | - catch2 >= 3.1.1 9 | - pytest 10 | - numpy 11 | - eigen >=3.3.9 12 | - pybind11 >=2.10 13 | - cereal >= 1.3 14 | - nlopt >= 2.7 15 | - pytorch 16 | - dill 17 | -------------------------------------------------------------------------------- /.github/install-doxygen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -xe 2 | 3 | # install doxygen 4 | # $1 is the version of Doxygen 5 | 6 | mkdir tmp-docs && cd tmp-docs 7 | wget https://www.doxygen.nl/files/doxygen-$1.linux.bin.tar.gz 8 | tar -xzf doxygen-$1.linux.bin.tar.gz 9 | cd doxygen-$1 10 | sudo make install 11 | cd ../.. 12 | sudo apt install libclang1-9 13 | sudo apt install libclang-cpp9 -------------------------------------------------------------------------------- /.github/workflows/build-doc.yml: -------------------------------------------------------------------------------- 1 | name: docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - release 8 | 9 | jobs: 10 | build-docs: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Use Conda 14 | uses: conda-incubator/setup-miniconda@v2 15 | with: 16 | auto-update-conda: true 17 | python-version: "3.8" 18 | activate-environment: "test" 19 | 20 | - name: Checkout MParT 21 | uses: actions/checkout@v1 22 | 23 | - uses: shrink/actions-docker-extract@v1 24 | id: extract 25 | with: 26 | image: quay.io/measuretransport/mpart_examples:latest 27 | path: /home/bayes/examples/python/. 28 | 29 | - name: Move notebooks into documentation 30 | run: | 31 | mkdir ${{ github.workspace }}/docs/source/tutorials/python 32 | cp ${{ steps.extract.outputs.destination }}/*.nbconvert.ipynb ${{ github.workspace }}/docs/source/tutorials/python/ 33 | for file in ${{ github.workspace }}/docs/source/tutorials/python/*.nbconvert.ipynb; do mv "${file}" "${file/nbconvert./}"; done 34 | 35 | - name: Install sphinx extensions 36 | shell: bash -l {0} 37 | run: conda install -c conda-forge doxygen pygments sphinx sphinx-design breathe pydata-sphinx-theme nbsphinx jupytext pandoc ipykernel nbconvert 38 | 39 | - name: Run CMake 40 | shell: bash -l {0} 41 | run: | 42 | cd ${{ github.workspace }} 43 | mkdir build && cd build 44 | cmake -DKokkos_ENABLE_THREADS=ON -DKokkos_ENABLE_SERIAL=ON -DPYTHON_EXECUTABLE=`which python` -DMPART_BUILD_EXAMPLES=OFF ../ 45 | 46 | - name: Build Docs 47 | shell: bash -l {0} 48 | run: | 49 | cd ${{ github.workspace }} && cd build 50 | make sphinx 51 | 52 | - name: Push to gh-pages 53 | uses: peaceiris/actions-gh-pages@v3.6.1 54 | with: 55 | github_token: ${{ secrets.GITHUB_TOKEN }} 56 | publish_dir: build/docs/sphinx/ 57 | -------------------------------------------------------------------------------- /.github/workflows/build-push-docker.yml: -------------------------------------------------------------------------------- 1 | name: build-and-push-docker 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - release 8 | 9 | jobs: 10 | docker: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Check out the repo 14 | uses: actions/checkout@v3 15 | - 16 | name: Set up Docker Buildx 17 | uses: docker/setup-buildx-action@v2 18 | - 19 | name: Login to Quay.io 20 | uses: docker/login-action@v2 21 | with: 22 | registry: quay.io 23 | username: ${{ secrets.QUAY_USERNAME }} 24 | password: ${{ secrets.QUAY_PASSWORD }} 25 | - 26 | name: Build and push 27 | uses: docker/build-push-action@v3 28 | with: 29 | context: . 30 | file: ./.docker/Dockerfile 31 | push: true 32 | tags: quay.io/measuretransport/mpart_base:latest 33 | -------------------------------------------------------------------------------- /.github/workflows/build-tests.yml: -------------------------------------------------------------------------------- 1 | name: tests 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - release 8 | pull_request: {} 9 | 10 | jobs: 11 | build-tests: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v1 16 | 17 | - name: Run CMake 18 | run: | 19 | cd ${{ github.workspace }} 20 | mkdir build 21 | cd build 22 | cmake -DKokkos_ENABLE_THREADS=ON -DKokkos_ENABLE_SERIAL=ON ../ 23 | 24 | - name: Build 25 | run: cd build; make -j2 26 | 27 | - name: Run Tests 28 | run: cd build; ./RunTests --kokkos-threads=2 --reporter junit -o test-results.xml 29 | 30 | - name: Publish Unit Test Results 31 | uses: EnricoMi/publish-unit-test-result-action@v1 32 | if: always() 33 | with: 34 | check_name: "Test Results" 35 | files: build/test-results.xml 36 | 37 | 38 | -------------------------------------------------------------------------------- /.github/workflows/pypi-deploy.yml: -------------------------------------------------------------------------------- 1 | name: Build and upload to PyPI 2 | 3 | # Build on every branch push, tag push, and pull request change: 4 | on: [push, pull_request] 5 | # Alternatively, to publish when a (published) GitHub Release is created, use the following: 6 | # on: 7 | # push: 8 | # pull_request: 9 | # release: 10 | # types: 11 | # - published 12 | 13 | jobs: 14 | # build_wheels: 15 | # name: Build wheels on ${{ matrix.os }} 16 | # runs-on: ${{ matrix.os }} 17 | # strategy: 18 | # matrix: 19 | # os: [ubuntu-20.04, macos-11, macos-12] 20 | 21 | # steps: 22 | # - uses: actions/checkout@v3 23 | 24 | # - name: Build wheels 25 | # uses: pypa/cibuildwheel@v2.12.0 26 | 27 | # - uses: actions/upload-artifact@v3 28 | # with: 29 | # path: ./wheelhouse/*.whl 30 | 31 | build_sdist: 32 | name: Build source distribution 33 | runs-on: ubuntu-latest 34 | steps: 35 | - uses: actions/checkout@v3 36 | 37 | - name: Build sdist 38 | run: pipx run build --sdist 39 | 40 | - uses: actions/upload-artifact@v3 41 | with: 42 | path: dist/*.tar.gz 43 | 44 | upload_pypi: 45 | needs: [build_sdist] 46 | runs-on: ubuntu-latest 47 | # upload to PyPI on every tag starting with 'v' 48 | if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') 49 | steps: 50 | - uses: actions/download-artifact@v3 51 | with: 52 | # unpacks default artifact into dist/ 53 | # if `name: artifact` is omitted, the action will create extra parent dir 54 | name: artifact 55 | path: dist 56 | 57 | - uses: pypa/gh-action-pypi-publish@release/v1 58 | with: 59 | password: ${{ secrets.pypi_password }} 60 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | *.egg-info* 3 | .vscode 4 | docs/_build 5 | bin 6 | lib 7 | /python 8 | bindings/python/tests/__pycache__/ 9 | .DS_Store 10 | MANIFEST.in 11 | _skbuild 12 | dist 13 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | # This CITATION.cff file was generated with cffinit. 2 | # Visit https://bit.ly/cffinit to generate yours today! 3 | 4 | cff-version: 1.2.0 5 | title: Monotone Parameterization Toolkit (MParT) 6 | message: 'If you use MParT, please cite it as below.' 7 | type: software 8 | version: 2.2.1 9 | authors: 10 | - given-names: Matthew 11 | family-names: Parno 12 | email: parnomd@gmail.com 13 | orcid: https://orcid.org/0000-0002-9419-2693 14 | - given-names: Daniel 15 | family-names: Sharp 16 | email: dannys4@vt.edu 17 | orcid: https://orcid.org/0000-0002-0439-5084 18 | - given-names: Paul-Baptiste 19 | family-names: Rubio 20 | email: rubiop@mit.edu 21 | orcid: https://orcid.org/0000-0002-9765-1162 22 | - given-names: Michael 23 | family-names: Brennan 24 | email: mcbrenn@mit.edu 25 | orcid: https://orcid.org/0000-0001-7812-9347 26 | - given-names: Henning 27 | family-names: Bonart 28 | email: hbonart@mit.edu 29 | orcid: https://orcid.org/0000-0002-5026-4499 30 | - given-names: Ricardo 31 | family-names: Baptista 32 | email: rsb@mit.edu 33 | orcid: https://orcid.org/0000-0002-0421-890X 34 | - given-names: Youssef 35 | family-names: Marzouk 36 | email: ymarz@mit.edu 37 | orcid: https://orcid.org/0000-0001-8242-3290 38 | 39 | -------------------------------------------------------------------------------- /Config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | include(CMakeFindDependencyMacro) 4 | find_dependency(Kokkos REQUIRED) 5 | find_dependency(Eigen3 REQUIRED) 6 | 7 | include ( "${CMAKE_CURRENT_LIST_DIR}/MParTTargets.cmake" ) 8 | 9 | 10 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2022, Massachusetts Institute of Technology 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 11 | 12 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /MParT/AffineFunction.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_AFFINEFUNCTION_H 2 | #define MPART_AFFINEFUNCTION_H 3 | 4 | #include 5 | 6 | #include "MParT/ParameterizedFunctionBase.h" 7 | 8 | #include 9 | #include 10 | 11 | 12 | namespace mpart{ 13 | 14 | /** @brief Defines functions of the form \f$Ax+b\f$ for an arbitrary rectangular matrix \f$A\f$ and vector offset \f$b\f$. 15 | */ 16 | template 17 | class AffineFunction : public ParameterizedFunctionBase 18 | { 19 | public: 20 | /** Construct a function that simply shifts the input. 21 | \f[ y = x + b \f] 22 | */ 23 | AffineFunction(StridedVector b); 24 | 25 | /** Constructs a linear function that only scales the input. 26 | \f[ y = Ax\f] 27 | */ 28 | AffineFunction(StridedMatrix A); 29 | 30 | /** Constructs an affine function that scales and shifts the input. 31 | \f[ y = Ax + b \f] 32 | */ 33 | AffineFunction(StridedMatrix A, StridedVector b); 34 | 35 | virtual ~AffineFunction() = default; 36 | 37 | void EvaluateImpl(StridedMatrix const& pts, 38 | StridedMatrix output) override; 39 | 40 | void CoeffGradImpl(StridedMatrix const& pts, 41 | StridedMatrix const& sens, 42 | StridedMatrix output) override; 43 | 44 | void GradientImpl(StridedMatrix const& pts, 45 | StridedMatrix const& sens, 46 | StridedMatrix output) override; 47 | 48 | 49 | // void print_Aij(int i, int j) { std::cout << "A(" << i << "," << j << ") = " << A_(i,j) << std::endl; } 50 | // void print_ptr_A() { std::cout << "ptr A = " << A_.data() << std::endl; } 51 | 52 | 53 | protected: 54 | 55 | Kokkos::View A_; 56 | Kokkos::View b_; 57 | 58 | int ldA; 59 | 60 | }; 61 | 62 | } 63 | #endif -------------------------------------------------------------------------------- /MParT/DerivativeFlags.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_DERIVATIVEFLAGS_H 2 | #define MPART_DERIVATIVEFLAGS_H 3 | 4 | namespace mpart{ 5 | namespace DerivativeFlags{ 6 | 7 | enum DerivativeType { 8 | None, //<- No derivatives 9 | Parameters, //<- Deriv wrt coeffs 10 | Diagonal, //<- first derivative wrt diagonal 11 | Diagonal2, //<- second derivative wrt diagonal 12 | Mixed, //<- gradient wrt coeffs of first derivative wrt x_d 13 | Input, //<- gradient wrt map input 14 | MixedInput //<- gradient of diagonal wrt map input 15 | }; 16 | 17 | } 18 | } 19 | #endif // #ifndef MPART_DERIVATIVEFLAGS_H -------------------------------------------------------------------------------- /MParT/Distributions/PullbackSampler.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_PULLBACKSAMPLER_H 2 | #define MPART_PULLBACKSAMPLER_H 3 | 4 | #include "MParT/Distributions/SampleGenerator.h" 5 | #include "MParT/ConditionalMapBase.h" 6 | 7 | namespace mpart { 8 | 9 | /** 10 | * @brief A class to sample from the pullback distribution of a transport map given the map and a sampler. 11 | * If \f$X\sim\mu\f$, and \f$T\f$ satisfies \f$T(X)\sim\nu\f$, then this class allows you to sample from 12 | * \f$\mu\f$ given a sampler for \f$\nu\f$ and the map \f$T\f$. 13 | * 14 | * @tparam MemorySpace Space where data is stored for computation 15 | */ 16 | template 17 | class PullbackSampler: public SampleGenerator { 18 | 19 | public: 20 | PullbackSampler() = delete; 21 | /** 22 | * @brief Construct a new Pullback Sampler object from the transport map and object to sample from \f$\nu\f$ 23 | * 24 | * @param map transport map with pushforward \f$\nu\f$ 25 | * @param sampler sampler of \f$\nu\f$ 26 | */ 27 | PullbackSampler(std::shared_ptr> map, std::shared_ptr> sampler): 28 | SampleGenerator(sampler->Dim()), map_(map), sampler_(sampler) { 29 | if (map_->outputDim != sampler_->Dim()) { 30 | throw std::invalid_argument("PullbackSampler: map output dimension does not match sampler sampler dimension"); 31 | } 32 | if (map_->inputDim != map_->outputDim) { 33 | throw std::invalid_argument("PullbackSampler: map input dimension does not match map output dimension"); 34 | } 35 | } 36 | 37 | /** 38 | * @brief Sample from \f$\mu\f$ using the pullback distribution 39 | * 40 | * @param output (MxN) matrix, where M is the dimension of \f$\mu\f$ and N is the number of samples 41 | */ 42 | void SampleImpl(StridedMatrix output) override { 43 | unsigned int N = output.extent(1); 44 | StridedMatrix pts = sampler_->Sample(N); 45 | Kokkos::View prefix_null("prefix_null", 0, pts.extent(1)); 46 | map_->InverseImpl(prefix_null, pts, output); 47 | }; 48 | 49 | /** 50 | * @brief Set the Seed for the random Pool of the sampler for reproducibility 51 | * 52 | * @param seed new seed to use 53 | */ 54 | void SetSeed(unsigned int seed) override { 55 | SampleGenerator::SetSeed(seed); 56 | sampler_->SetSeed(seed); 57 | } 58 | 59 | private: 60 | /** 61 | * @brief Transport map \f$T:\mu\to\nu\f$ 62 | * 63 | */ 64 | std::shared_ptr> map_; 65 | /** 66 | * @brief Object to sample from measure \f$\nu\f$ 67 | * 68 | */ 69 | std::shared_ptr> sampler_; 70 | }; 71 | 72 | } // namespace mpart 73 | 74 | #endif // MPART_PULLBACKSAMPLER_H -------------------------------------------------------------------------------- /MParT/Distributions/PushforwardSampler.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_PUSHFORWARDSAMPLER_H 2 | #define MPART_PUSHFORWARDSAMPLER_H 3 | 4 | #include "MParT/Distributions/SampleGenerator.h" 5 | #include "MParT/ConditionalMapBase.h" 6 | 7 | namespace mpart { 8 | 9 | /** 10 | * @brief A class to sample from the pushforward distribution of a transport map given the map and a sampler. 11 | * If \f$X\sim\mu\f$, and \f$T\f$ satisfies \f$T(X)\sim\nu\f$, then this class allows you to sample from 12 | * \f$\nu\f$ given a sampler for \f$\mu\f$ and the map \f$T\f$. 13 | * 14 | * @tparam MemorySpace Space where data is stored for computation 15 | */ 16 | template 17 | class PushforwardSampler: public SampleGenerator { 18 | 19 | public: 20 | PushforwardSampler() = delete; 21 | 22 | /** 23 | * @brief Construct a new Pushforward Sampler object from map \f$T\f$ and sampler of \f$\mu\f$ 24 | * 25 | * @param map Transport map \f$T:\mu\to\nu\f$ 26 | * @param sampler Object to sample according to measure \f$\mu\f$ 27 | */ 28 | PushforwardSampler(std::shared_ptr> map, std::shared_ptr> sampler): 29 | SampleGenerator(sampler->Dim()), map_(map), sampler_(sampler) { 30 | if (map_->outputDim != sampler_->Dim()) { 31 | throw std::invalid_argument("PushforwardSampler: map output dimension does not match sampler dimension"); 32 | } 33 | if (map_->inputDim != map_->outputDim) { 34 | throw std::invalid_argument("PushforwardSampler: map input dimension does not match map output dimension"); 35 | } 36 | } 37 | 38 | /** 39 | * @brief Sample from \f$\nu\f$ using the pushforward distribution 40 | * 41 | * @param output (MxN) matrix, where M is the dimension of \f$\nu\f$ and N is the number of samples 42 | */ 43 | void SampleImpl(StridedMatrix output) override { 44 | unsigned int N = output.extent(1); 45 | StridedMatrix pts = sampler_->Sample(N); 46 | map_->EvaluateImpl(pts, output); 47 | }; 48 | 49 | /** 50 | * @brief Set the Seed for the random Pool of the sampler for reproducibility 51 | * 52 | * @param seed new seed to use 53 | */ 54 | void SetSeed(unsigned int seed) override { 55 | SampleGenerator::SetSeed(seed); 56 | sampler_->SetSeed(seed); 57 | } 58 | 59 | private: 60 | /** 61 | * @brief Transport map \f$T:\mu\to\nu\f$ 62 | * 63 | */ 64 | std::shared_ptr> map_; 65 | /** 66 | * @brief Object to sample from measure \f$\nu\f$ 67 | * 68 | */ 69 | std::shared_ptr> sampler_; 70 | }; 71 | 72 | } // namespace mpart 73 | 74 | #endif // MPART_PUSHFORWARDSAMPLER_H -------------------------------------------------------------------------------- /MParT/Distributions/SampleGenerator.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_SampleGenerator_H 2 | #define MPART_SampleGenerator_H 3 | 4 | #include 5 | #include 6 | 7 | #include "MParT/Utilities/EigenTypes.h" 8 | #include "MParT/Utilities/KokkosSpaceMappings.h" 9 | #include "MParT/Utilities/ArrayConversions.h" 10 | 11 | namespace mpart { 12 | 13 | /** 14 | * @brief A base class to generate samples from a distribution 15 | * 16 | * @tparam MemorySpace where the samples will be stored 17 | */ 18 | template 19 | class SampleGenerator { 20 | public: 21 | 22 | /** 23 | * @brief Construct a new Sample Generator base object with a dimension and a seed for the random pool 24 | * 25 | * @param dim dimension of the distribution 26 | * @param seed what seed to initialize the random pool with 27 | */ 28 | SampleGenerator(unsigned int dim, unsigned int seed = time(NULL)) : dim_(dim), rand_pool(seed) {}; 29 | 30 | virtual ~SampleGenerator() = default; 31 | 32 | /** 33 | * @brief Generates a sample from the generator. 34 | * @param output The matrix where we want to store the samples. 35 | */ 36 | virtual void SampleImpl(StridedMatrix output) = 0; 37 | 38 | /** 39 | * @brief Generates a samples from the generator. 40 | * 41 | * @param N The number of Samples from this generator 42 | * @return StridedMatrix The samples from this generator 43 | */ 44 | Kokkos::View Sample(unsigned int N) { 45 | Kokkos::View output("output", dim_, N); 46 | SampleImpl(output); 47 | return output; 48 | }; 49 | 50 | /** 51 | * @brief Set the Seed for the random pool, reinitializing it to ensure sampling has reproducible behavior 52 | * 53 | * @param seed new seed to set for the pool 54 | */ 55 | virtual void SetSeed(unsigned int seed) { 56 | rand_pool = PoolType(seed); 57 | } 58 | 59 | /** Sample function with conversion from Kokkos to Eigen (and possibly copy to/from device). */ 60 | // Eigen::RowMatrixXd SampleEigen(unsigned int N); 61 | using PoolType = typename Kokkos::Random_XorShift64_Pool::Space>; 62 | 63 | /** 64 | * @brief Retrieve the dimension of the distribution we sample from 65 | * 66 | * @return unsigned int dimension of the samples 67 | */ 68 | virtual unsigned int Dim() const { return dim_; } 69 | 70 | protected: 71 | /** 72 | * @brief Dimension of the distribution 73 | * 74 | */ 75 | const unsigned int dim_; 76 | 77 | /** 78 | * @brief Pool containing RNGs for internal random sampling 79 | * 80 | */ 81 | PoolType rand_pool; 82 | }; 83 | 84 | } // namespace mpart 85 | #endif //MPART_SampleGenerator_H -------------------------------------------------------------------------------- /MParT/Distributions/TransportDistributionFactory.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_TRANSPORTDISTRIBUTIONFACTORY_H 2 | #define MPART_TRANSPORTDISTRIBUTIONFACTORY_H 3 | 4 | #include "Distribution.h" 5 | #include "PullbackDensity.h" 6 | #include "PushforwardDensity.h" 7 | #include "PullbackSampler.h" 8 | #include "PushforwardSampler.h" 9 | 10 | namespace mpart { 11 | 12 | template 13 | using PullbackDistribution = Distribution, PullbackSampler>; 14 | template 15 | using PushforwardDistribution = Distribution, PushforwardSampler>; 16 | 17 | template 18 | std::shared_ptr> CreatePullback(std::shared_ptr> map, std::shared_ptr> reference) { 19 | auto sampler = std::make_shared>(map, reference->GetSampler()); 20 | auto density = std::make_shared>(map, reference->GetDensity()); 21 | return std::make_shared>(sampler, density); 22 | }; 23 | 24 | template 25 | std::shared_ptr> CreatePushforward(std::shared_ptr> map, std::shared_ptr> reference) { 26 | auto sampler = std::make_shared>(map, reference->GetSampler()); 27 | auto density = std::make_shared>(map, reference->GetDensity()); 28 | return std::make_shared>(sampler, density); 29 | }; 30 | 31 | }; 32 | 33 | #endif // MPART_TRANSPORTDISTRIBUTIONFACTORY_H -------------------------------------------------------------------------------- /MParT/IdentityMap.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_IDENTITYMAP_H 2 | #define MPART_IDENTITYMAP_H 3 | 4 | #include "MParT/ConditionalMapBase.h" 5 | #include "MParT/Utilities/Miscellaneous.h" 6 | 7 | #include 8 | 9 | #include 10 | 11 | 12 | namespace mpart{ 13 | 14 | /** 15 | @brief Provides a definition of the identity map. 16 | @details 17 | This class defines the identity map \f$I:\mathbb{R}^N\rightarrow \mathbb{R}^M\f$, i.e., a map such that \f$I(x_{1:N-M},x_{N-M:N}) = x_{N-M:N}\f$ 18 | 19 | 20 | */ 21 | template 22 | class IdentityMap : public ConditionalMapBase 23 | { 24 | public: 25 | 26 | /** @brief Construct an map that acts as the identify. 27 | 28 | @param inDim The dimension \f$N\f$ of the input to this map. 29 | @param outDim The dimension \f$M\f$ of the output from this map. 30 | */ 31 | IdentityMap(unsigned int inDim, unsigned int outDim); 32 | 33 | 34 | void EvaluateImpl(StridedMatrix const& pts, 35 | StridedMatrix output) override; 36 | 37 | void InverseImpl(StridedMatrix const& x1, 38 | StridedMatrix const& r, 39 | StridedMatrix output) override; 40 | 41 | 42 | void LogDeterminantImpl(StridedMatrix const& pts, 43 | StridedVector output) override; 44 | 45 | void CoeffGradImpl(StridedMatrix const& pts, 46 | StridedMatrix const& sens, 47 | StridedMatrix output) override; 48 | 49 | void GradientImpl(StridedMatrix const& pts, 50 | StridedMatrix const& sens, 51 | StridedMatrix output) override; 52 | 53 | 54 | void LogDeterminantCoeffGradImpl(StridedMatrix const& pts, 55 | StridedMatrix output) override; 56 | 57 | void LogDeterminantInputGradImpl(StridedMatrix const& pts, 58 | StridedMatrix output) override; 59 | 60 | }; // class IdentityMap 61 | 62 | } 63 | 64 | #endif -------------------------------------------------------------------------------- /MParT/MultiIndices/MultiIndexNeighborhood.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_MULTIINDEXNEIGHBORHOOD_H 2 | #define MPART_MULTIINDEXNEIGHBORHOOD_H 3 | 4 | #include 5 | 6 | #include "MParT/MultiIndices/MultiIndex.h" 7 | 8 | namespace mpart{ 9 | 10 | /** 11 | @brief Abstract base class for MultiIndexSet graph connectivity definitions. 12 | */ 13 | class MultiIndexNeighborhood{ 14 | public: 15 | virtual ~MultiIndexNeighborhood() = default; 16 | 17 | virtual std::vector ForwardNeighbors(MultiIndex const& multi) = 0; 18 | 19 | virtual std::vector BackwardNeighbors(MultiIndex const& multi) = 0; 20 | 21 | virtual bool IsForward(MultiIndex const& base, MultiIndex const& next) = 0; 22 | virtual bool IsBackward(MultiIndex const& base, MultiIndex const& next) = 0; 23 | 24 | 25 | }; 26 | 27 | /** 28 | @brief Defines the standard graph connectivity for a MultiIndexSet. 29 | A multiindex \f$\mathbf{\alpha}\f$ is a **forward** neighbor of \f$\mathbf{\beta}\f$ if 30 | \f$\|\mathbf{\alpha}-\mathbf{\beta}|_1==1\f$ and \f$\mathbf{\alpha}_i \geq \mathbf{\alpha}_i\f$ for all \f$i\f$. 31 | 32 | A multiindex \f$\mathbf{\alpha}\f$ is a **backward** neighbor of \f$\mathbf{\beta}\f$ if 33 | \f$\|\mathbf{\alpha}-\mathbf{\beta}|_1==1\f$ and \f$\mathbf{\alpha}_i \leq \mathbf{\alpha}_i\f$ for all \f$i\f$. 34 | */ 35 | class DefaultNeighborhood : public MultiIndexNeighborhood{ 36 | public: 37 | 38 | virtual ~DefaultNeighborhood() = default; 39 | 40 | virtual std::vector ForwardNeighbors(MultiIndex const& multi) override; 41 | 42 | virtual std::vector BackwardNeighbors(MultiIndex const& multi) override; 43 | 44 | virtual bool IsForward(MultiIndex const& base, 45 | MultiIndex const& next) override; 46 | 47 | virtual bool IsBackward(MultiIndex const& base, 48 | MultiIndex const& prev) override; 49 | }; 50 | 51 | } 52 | 53 | 54 | #endif -------------------------------------------------------------------------------- /MParT/PositiveBijectors.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_POSITIVEBIJECTORS_H 2 | #define MPART_POSITIVEBIJECTORS_H 3 | 4 | #include 5 | #include 6 | 7 | namespace mpart{ 8 | 9 | /** 10 | * @brief Defines the softplus function \f$g(x) = \log(1+\exp(x))\f$. 11 | */ 12 | class SoftPlus{ 13 | public: 14 | 15 | KOKKOS_INLINE_FUNCTION static double Evaluate(double x){ 16 | //stable implementation of std::log(1.0 + std::exp(x)) for large values 17 | return std::log(1.0 + std::exp(-1.0 * std::abs(x))) + std::fmax(x,0.0); 18 | } 19 | 20 | KOKKOS_INLINE_FUNCTION static double Derivative(double x){ 21 | return 1.0 / (1.0 + std::exp(-1.0 * x)); 22 | } 23 | 24 | KOKKOS_INLINE_FUNCTION static double SecondDerivative(double x){ 25 | return 1.0 / (2.0 + std::exp(-1.0 * x) + std::exp(x)); 26 | } 27 | 28 | KOKKOS_INLINE_FUNCTION static double Inverse(double x){ 29 | return std::fmin(std::log(std::exp(x) - 1.0), x); 30 | } 31 | 32 | }; 33 | 34 | /** 35 | * @brief Defines the exponential function \f$g(x) = \exp(x)\f$. 36 | */ 37 | class Exp{ 38 | public: 39 | 40 | KOKKOS_INLINE_FUNCTION static double Evaluate(double x){ 41 | return std::exp(x); 42 | } 43 | 44 | KOKKOS_INLINE_FUNCTION static double Derivative(double x){ 45 | return std::exp(x); 46 | } 47 | 48 | KOKKOS_INLINE_FUNCTION static double SecondDerivative(double x){ 49 | return std::exp(x); 50 | } 51 | 52 | KOKKOS_INLINE_FUNCTION static double Inverse(double x){ 53 | return std::log(x); 54 | } 55 | 56 | }; 57 | 58 | } // namespace mpart 59 | 60 | #endif -------------------------------------------------------------------------------- /MParT/TrainMap.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_TRAINMAP_H 2 | #define MPART_TRAINMAP_H 3 | 4 | #include 5 | #include 6 | #include "ConditionalMapBase.h" 7 | #include "MapObjective.h" 8 | 9 | namespace mpart { 10 | 11 | /** 12 | * @brief TrainOptions adds options for training your map, 13 | * with fields largely based on NLopt settings. For documentation 14 | * of such fields, see NLOpt. 15 | * 16 | */ 17 | struct TrainOptions { 18 | /** NLOpt: Optimization Algorithm to use */ 19 | std::string opt_alg = "LD_SLSQP"; 20 | /** NLOpt: Lower bound on optimizer */ 21 | double opt_stopval = -std::numeric_limits::infinity(); 22 | /** NLOpt: Relative tolerance on function value change */ 23 | double opt_ftol_rel = 1e-3; 24 | /** NLOpt: Absolute tolerance of function value change */ 25 | double opt_ftol_abs = 1e-3; 26 | /** NLOpt: Relative tolerance of minimizer value change */ 27 | double opt_xtol_rel = 1e-4; 28 | /** NLOpt: Absolute tolerance of minimizer value change */ 29 | double opt_xtol_abs = 1e-4; 30 | /** NLOpt: Maximum number of evaluations of function to optimize */ 31 | int opt_maxeval = 1000; 32 | /** NLOpt: Maximum amount of time to spend optimizing */ 33 | double opt_maxtime = std::numeric_limits::infinity(); 34 | /** Verbosity of map training (1: verbose, 2: debug) */ 35 | int verbose = 0; 36 | 37 | /** 38 | * @brief Create a string representation of these training options (helpful for bindings) 39 | * 40 | * @return std::string Every option value in this struct 41 | */ 42 | std::string String() { 43 | std::stringstream ss; 44 | ss << "opt_alg = " << opt_alg << "\n"; 45 | ss << "opt_stopval = " << opt_stopval << "\n"; 46 | ss << "opt_ftol_rel = " << opt_ftol_rel << "\n"; 47 | ss << "opt_ftol_abs = " << opt_ftol_abs << "\n"; 48 | ss << "opt_xtol_rel = " << opt_xtol_rel << "\n"; 49 | ss << "opt_xtol_abs = " << opt_xtol_abs << "\n"; 50 | ss << "opt_maxeval = " << opt_maxeval << "\n"; 51 | ss << "opt_maxtime = " << opt_maxtime << "\n"; 52 | ss << "verbose = " << verbose; 53 | return ss.str(); 54 | } 55 | }; 56 | 57 | /** 58 | * @brief Function to train a map inplace given an objective and optimization options 59 | * 60 | * @param map Map to optimize (inplace) 61 | * @param objective MapObjective to optimize over 62 | * @param options Options for optimizing the map 63 | */ 64 | template 65 | double TrainMap(std::shared_ptr> map, std::shared_ptr> objective, TrainOptions options); 66 | 67 | } // namespace mpart 68 | 69 | #endif // MPART_TRAINMAP_H -------------------------------------------------------------------------------- /MParT/TrainMapAdaptive.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_TRAINMAPADAPTIVE_H 2 | #define MPART_TRAINMAPADAPTIVE_H 3 | 4 | #include 5 | #include "Utilities/ArrayConversions.h" 6 | #include "MultiIndices/MultiIndexSet.h" 7 | #include "MapOptions.h" 8 | #include "TriangularMap.h" 9 | #include "MapFactory.h" 10 | #include "MapObjective.h" 11 | #include "TrainMap.h" 12 | 13 | namespace mpart { 14 | 15 | /** 16 | * @brief Both map and training options combined with special ATM options. 17 | * 18 | */ 19 | struct ATMOptions: public MapOptions, public TrainOptions { 20 | /** Maximum number of iterations that do not improve error */ 21 | unsigned int maxPatience = 10; 22 | /** Maximum number of coefficients in final expansion (including ALL dimensions of map) */ 23 | unsigned int maxSize = std::numeric_limits::max(); // <- use this instead of infinity because python doesn't have infinite ints 24 | /** Multiindex representing the maximum degree in each input dimension */ 25 | MultiIndex maxDegrees; 26 | 27 | /** 28 | * @brief Create a string representation of these options. 29 | * 30 | * @return std::string 31 | */ 32 | std::string String() override { 33 | std::string md_str = maxDegrees.String(); 34 | std::stringstream ss; 35 | ss << MapOptions::String() << "\n" << TrainOptions::String() << "\n"; 36 | ss << "maxPatience = " << maxPatience << "\n"; 37 | ss << "maxSize = " << maxSize << "\n"; 38 | ss << "maxDegrees = " << maxDegrees.String(); 39 | 40 | return ss.str(); 41 | } 42 | }; 43 | 44 | /** 45 | * @brief Adaptively discover new terms in coefficient basis to add to map using the ATM algorithm of Baptista, et al. 2022. 46 | * 47 | * @tparam MemorySpace Device or host space to work in 48 | * @param mset0 vector storing initial (minimal) guess of multiindex sets, corresponding to each dimension. Is changed in-place. 49 | * @param objective What this map should be adapted to fits 50 | * @return std::shared_ptr> New map according to specifications. 51 | */ 52 | template 53 | std::shared_ptr> TrainMapAdaptive(std::vector &mset0, 54 | std::shared_ptr> objective, 55 | ATMOptions options); 56 | 57 | // template 58 | // std::shared_ptr> TrainMapAdaptive(StridedMatrix train_x, StridedMatrix test_x, ATMOptions options = ATMOptions()) { 59 | // unsigned int dim = train_x.extent(0); 60 | // MultiIndexSet mset0 = MultiIndexSet::CreateTotalOrder(dim, 0); 61 | // return TrainMapAdaptive(mset0, train_x, test_x, options); 62 | // } 63 | 64 | } 65 | 66 | 67 | #endif // MPART_TRAINMAPADAPTIVE_H -------------------------------------------------------------------------------- /MParT/Utilities/EigenTypes.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_EIGENTYPES_H 2 | #define MPART_EIGENTYPES_H 3 | 4 | #include 5 | 6 | namespace Eigen{ 7 | using RowMatrixXd = Eigen::Matrix; 8 | } 9 | 10 | 11 | #endif -------------------------------------------------------------------------------- /MParT/Utilities/GPUtils.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace mpart{ 4 | #if defined(MPART_ENABLE_GPU) 5 | 6 | // Only enable DeviceSpace if the DefaultExecutionSpace is a GPU space. 7 | using DeviceSpace = std::enable_if< 8 | !std::is_same::value, Kokkos::DefaultExecutionSpace::memory_space>::type; 11 | 12 | #endif 13 | } // namespace mpart -------------------------------------------------------------------------------- /MParT/Utilities/KokkosHelpers.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_KOKKOSHELPERS_H 2 | #define MPART_KOKKOSHELPERS_H 3 | 4 | #include 5 | 6 | namespace mpart{ 7 | 8 | /** Sets up a team policy for iterating over a range where each thread requires the same amount of cache memory. Uses kokkos functions to figure out the recommended team size. 9 | @tparam ExecutionSpace The kokkos execution space where the parallel for loop will be executed. 10 | @tparam FunctorType The type of functor that will be evaluated. 11 | @param numPts The number of iterations in the for loop. 12 | @param cacheBytes The amount of memory, in bytes, required by each thread. 13 | @param functor The for loop work. 14 | @return A policy with allocated cache that can be used to iterate over the range. 15 | */ 16 | template 17 | Kokkos::TeamPolicy GetCachedRangePolicy(unsigned int numPts, unsigned int cacheBytes, FunctorType const& functor) 18 | { 19 | Kokkos::TeamPolicy policy; 20 | policy.set_scratch_size(1,Kokkos::PerTeam(0), Kokkos::PerThread(cacheBytes)); 21 | 22 | const unsigned int threadsPerTeam = std::min(numPts, policy.team_size_recommended(functor, Kokkos::ParallelForTag())); 23 | const unsigned int numTeams = std::ceil( double(numPts) / threadsPerTeam ); 24 | 25 | policy = Kokkos::TeamPolicy(numTeams, threadsPerTeam).set_scratch_size(1,Kokkos::PerTeam(0), Kokkos::PerThread(cacheBytes)); 26 | 27 | return policy; 28 | }; 29 | 30 | } // namespace mpart 31 | 32 | 33 | #endif -------------------------------------------------------------------------------- /MParT/Utilities/KokkosSpaceMappings.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_KOKKOSSPACEMAPPINGS_H 2 | #define MPART_KOKKOSSPACEMAPPINGS_H 3 | 4 | #include 5 | 6 | namespace mpart{ 7 | 8 | /** Used to convert Kokkos memory space type (e.g., Kokkos::CudaSpace) to an execution space that can access that memory. 9 | Note that mapping from memory space to device space is not unique. This metaprogramming technique is only guaranteed 10 | to return one of the possible execution spaces. 11 | */ 12 | template 13 | struct MemoryToExecution{}; 14 | 15 | template<> struct MemoryToExecution{using Space = Kokkos::DefaultHostExecutionSpace;}; 16 | 17 | #if defined(MPART_ENABLE_GPU) 18 | template<> struct MemoryToExecution{using Space = Kokkos::Cuda;}; 19 | #endif 20 | 21 | } 22 | 23 | #endif -------------------------------------------------------------------------------- /MParT/Utilities/MathFunctions.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_MATHFUNCTIONS_H 2 | #define MPART_MATHFUNCTIONS_H 3 | 4 | #include 5 | #include "ArrayConversions.h" 6 | 7 | namespace mpart{ 8 | 9 | /** Computes the factorial d! */ 10 | KOKKOS_INLINE_FUNCTION unsigned int Factorial(unsigned int d) 11 | { 12 | unsigned int out = 1; 13 | for(unsigned int i=2; i<=d; ++i) 14 | out *= i; 15 | return out; 16 | } 17 | 18 | } 19 | 20 | #endif -------------------------------------------------------------------------------- /MParT/Utilities/Miscellaneous.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_UTILITIES_MISCELLANEOUS_H 2 | #define MPART_UTILITIES_MISCELLANEOUS_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace mpart{ 9 | 10 | template 11 | KOKKOS_INLINE_FUNCTION void simple_swap(T& t1, T& t2) { 12 | T temp(t1); 13 | t1 = t2; 14 | t2 = temp; 15 | } 16 | 17 | /** Tries to read an options from a std::map. If the key does not exist, the specified default value is returned. */ 18 | std::string GetOption(std::unordered_map const& map, 19 | std::string const& key, 20 | std::string const& defaultValue); 21 | 22 | /** Provides a mechanism for raising exceptions in CPU code where recovery is possible 23 | and assertions in GPU code where exceptions aren't alllowed. 24 | */ 25 | template 26 | struct ProcAgnosticError { 27 | static void error(const char*) { 28 | assert(false); 29 | } 30 | }; 31 | 32 | template 33 | struct ProcAgnosticError { 34 | static void error(const char* message) { 35 | throw ErrorType(message); 36 | } 37 | }; 38 | } 39 | 40 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![](https://github.com/MeasureTransport/MParT/actions/workflows/build-doc.yml/badge.svg)](https://measuretransport.github.io/MParT/) 2 | [![](https://github.com/MeasureTransport/MParT/actions/workflows/build-tests.yml/badge.svg)](https://github.com/MeasureTransport/MParT/actions/workflows/build-tests.yml) 3 | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/MeasureTransport/MParT-examples/HEAD) 4 | [![DOI](https://joss.theoj.org/papers/10.21105/joss.04843/status.svg)](https://doi.org/10.21105/joss.04843) 5 | 6 | # MParT: A Monotone Parameterization Toolkit 7 | A CPU/GPU performance-portable library for parameterizing and constructing monotone functions in the context of measure transport and regression. 8 | 9 | ## Documentation 10 | See [measuretransport.github.io/MParT/](https://measuretransport.github.io/MParT/) for more extensive documentation. 11 | 12 | -------------------------------------------------------------------------------- /bindings/common/include/CommonUtilities.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "MParT/Utilities/ArrayConversions.h" 5 | 6 | namespace mpart{ 7 | namespace binding{ 8 | 9 | /** Define a wrapper around Kokkos::Initialize that accepts a vector of strings instead of argc and argv. */ 10 | void Initialize(std::vector args); 11 | 12 | } // namespace mpart 13 | } // namespace binding -------------------------------------------------------------------------------- /bindings/common/src/CommonUtilities.cpp: -------------------------------------------------------------------------------- 1 | #include "CommonUtilities.h" 2 | 3 | #include 4 | #include "MParT/Initialization.h" 5 | 6 | // Define a wrapper around Kokkos::Initialize that accepts a vector of strings instead of argc and argv. 7 | void mpart::binding::Initialize(std::vector args) { 8 | 9 | std::vector cstrs; 10 | cstrs.reserve(args.size()); 11 | for (auto &s : args) cstrs.push_back(const_cast(s.c_str())); 12 | 13 | int size = cstrs.size(); 14 | mpart::Initialize(size, cstrs.data()); 15 | }; -------------------------------------------------------------------------------- /bindings/julia/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(JULIA_BINDING_SOURCES 2 | src/CommonJuliaUtilities.cpp 3 | src/ConditionalMapBase.cpp 4 | src/JlArrayConversions.cpp 5 | src/MapFactory.cpp 6 | src/MapOptions.cpp 7 | src/MultiIndex.cpp 8 | src/ParameterizedFunctionBase.cpp 9 | src/TriangularMap.cpp 10 | src/Wrapper.cpp 11 | src/AffineMap.cpp 12 | src/ComposedMap.cpp 13 | ../common/src/CommonUtilities.cpp 14 | ) 15 | 16 | if(MPART_OPT) 17 | set(JULIA_BINDING_SOURCES ${JULIA_BINDING_SOURCES} 18 | src/MapObjective.cpp 19 | src/TrainMap.cpp 20 | src/TrainMapAdaptive.cpp 21 | ) 22 | endif() 23 | 24 | include_directories(./include ../common/include) 25 | add_library(mpartjl SHARED ${JULIA_BINDING_SOURCES}) 26 | target_link_libraries(mpartjl PRIVATE mpart JlCxx::cxxwrap_julia JlCxx::cxxwrap_julia_stl Kokkos::kokkos Eigen3::Eigen ${EXT_LIBRARIES}) 27 | 28 | # Add an installation target for the julia bindings 29 | install(TARGETS mpartjl DESTINATION "${JULIA_INSTALL_PREFIX}") -------------------------------------------------------------------------------- /bindings/julia/src/AffineMap.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/AffineMap.h" 2 | #include "MParT/AffineFunction.h" 3 | #include "MParT/ParameterizedFunctionBase.h" 4 | #include "MParT/ConditionalMapBase.h" 5 | 6 | #include "CommonJuliaUtilities.h" 7 | #include "JlArrayConversions.h" 8 | 9 | namespace jlcxx { 10 | // Tell CxxWrap.jl the supertype structure for ConditionalMapBase 11 | template<> struct SuperType> {typedef mpart::ConditionalMapBase type;}; 12 | template<> struct SuperType>{typedef mpart::ParameterizedFunctionBase type;}; 13 | } 14 | 15 | using namespace mpart; 16 | 17 | void mpart::binding::AffineMapWrapper(jlcxx::Module &mod) 18 | { 19 | mod.add_type>("AffineMap", jlcxx::julia_base_type>()); 20 | mod.method("AffineMap", [](jlcxx::ArrayRef b){ 21 | return std::make_shared>(JuliaToKokkos(b)); 22 | }); 23 | mod.method("AffineMap", [](jlcxx::ArrayRef A, jlcxx::ArrayRef b){ 24 | return std::make_shared>(JuliaToKokkos(A), JuliaToKokkos(b)); 25 | }); 26 | mod.method("AffineMap", [](jlcxx::ArrayRef A){ 27 | return std::make_shared>(JuliaToKokkos(A)); 28 | }); 29 | } 30 | 31 | 32 | void mpart::binding::AffineFunctionWrapper(jlcxx::Module &mod) 33 | { 34 | mod.add_type>("AffineFunction", jlcxx::julia_base_type>()); 35 | mod.method("AffineFunction", [](jlcxx::ArrayRef b){ 36 | return std::make_shared>(JuliaToKokkos(b)); 37 | }); 38 | mod.method("AffineFunction", [](jlcxx::ArrayRef A, jlcxx::ArrayRef b){ 39 | return std::make_shared>(JuliaToKokkos(A), JuliaToKokkos(b)); 40 | }); 41 | mod.method("AffineFunction", [](jlcxx::ArrayRef A){ 42 | return std::make_shared>(JuliaToKokkos(A)); 43 | }); 44 | } 45 | -------------------------------------------------------------------------------- /bindings/julia/src/CommonJuliaUtilities.cpp: -------------------------------------------------------------------------------- 1 | #include "CommonJuliaUtilities.h" 2 | 3 | #include 4 | 5 | using namespace mpart::binding; 6 | 7 | namespace mpart{ 8 | namespace binding{ 9 | std::vector makeInitArguments(std::vector opts) { 10 | std::vector args; 11 | 12 | for(int i = 0; i < opts.size(); i+=2){ 13 | auto key = opts[i]; 14 | auto val = opts[i+1]; 15 | std::string opt = "--" + key + "=" + val; 16 | args.push_back(opt); 17 | } 18 | return args; 19 | } 20 | } 21 | } 22 | 23 | void mpart::binding::CommonUtilitiesWrapper(jlcxx::Module &mod) 24 | { 25 | mod.method("Initialize", [](){mpart::binding::Initialize(std::vector {});}); 26 | mod.method("Initialize", [](std::vector v){mpart::binding::Initialize(makeInitArguments(v));}); 27 | mod.method("Concurrency", &Kokkos::DefaultExecutionSpace::concurrency); 28 | mod.add_type("HostSpace"); 29 | mod.add_type("LayoutStride"); 30 | } 31 | -------------------------------------------------------------------------------- /bindings/julia/src/ComposedMap.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/ComposedMap.h" 2 | #include "MParT/ConditionalMapBase.h" 3 | 4 | #include "CommonJuliaUtilities.h" 5 | #include "JlArrayConversions.h" 6 | 7 | namespace jlcxx { 8 | // Tell CxxWrap.jl the supertype structure for ConditionalMapBase 9 | template<> struct SuperType> {typedef mpart::ConditionalMapBase type;}; 10 | } 11 | 12 | using namespace mpart; 13 | 14 | void mpart::binding::ComposedMapWrapper(jlcxx::Module &mod) 15 | { 16 | mod.add_type>("ComposedMap", jlcxx::julia_base_type>()); 17 | mod.method("ComposedMap", [](std::vector>> const& maps){ 18 | std::shared_ptr> ret = std::make_shared>(maps); 19 | return ret; 20 | }) 21 | ; 22 | } -------------------------------------------------------------------------------- /bindings/julia/src/ConditionalMapBase.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/ConditionalMapBase.h" 2 | 3 | #include "CommonJuliaUtilities.h" 4 | #include "JlArrayConversions.h" 5 | 6 | namespace jlcxx { 7 | // Tell CxxWrap.jl the supertype structure for ConditionalMapBase 8 | template<> struct SuperType> {typedef mpart::ParameterizedFunctionBase type;}; 9 | } 10 | 11 | void mpart::binding::ConditionalMapBaseWrapper(jlcxx::Module &mod) { 12 | // ConditionalMapBase 13 | mod.add_type>("ConditionalMapBase", jlcxx::julia_base_type>()) 14 | .method("GetBaseFunction", &ConditionalMapBase::GetBaseFunction) 15 | .method("LogDeterminant", [](ConditionalMapBase &map, jlcxx::ArrayRef pts){ 16 | unsigned int numPts = size(pts,1); 17 | jlcxx::ArrayRef output = jlMalloc(numPts); 18 | map.LogDeterminantImpl(JuliaToKokkos(pts), JuliaToKokkos(output)); 19 | return output; 20 | }) 21 | .method("LogDeterminantCoeffGrad", [](ConditionalMapBase& map, jlcxx::ArrayRef pts){ 22 | unsigned int numPts = size(pts,1); 23 | unsigned int numCoeffs = map.numCoeffs; 24 | jlcxx::ArrayRef output = jlMalloc(numCoeffs, numPts); 25 | map.LogDeterminantCoeffGradImpl(JuliaToKokkos(pts), JuliaToKokkos(output)); 26 | return output; 27 | }) 28 | .method("LogDeterminantInputGrad", [](ConditionalMapBase& map, jlcxx::ArrayRef pts){ 29 | unsigned int numPts = size(pts,1); 30 | unsigned int numInputs = map.inputDim; 31 | jlcxx::ArrayRef output = jlMalloc(numInputs, numPts); 32 | map.LogDeterminantInputGradImpl(JuliaToKokkos(pts), JuliaToKokkos(output)); 33 | return output; 34 | }) 35 | .method("Inverse", [](ConditionalMapBase &map, jlcxx::ArrayRef x1, jlcxx::ArrayRef r) { 36 | unsigned int numPts = size(r,1); 37 | unsigned int outputDim = map.outputDim; 38 | jlcxx::ArrayRef output = jlMalloc(outputDim, numPts); 39 | map.InverseImpl(JuliaToKokkos(x1), JuliaToKokkos(r), JuliaToKokkos(output)); 40 | return output; 41 | }) 42 | ; 43 | jlcxx::stl::apply_stl*>(mod); 44 | } -------------------------------------------------------------------------------- /bindings/julia/src/JlArrayConversions.cpp: -------------------------------------------------------------------------------- 1 | #include "JlArrayConversions.h" 2 | 3 | namespace mpart { 4 | namespace binding { 5 | /** 6 | * @brief Wrap a Julia vector in a Kokkos View 7 | * 8 | * @param vec Julia vector to take view of 9 | * @return mpart::StridedVector Same memory, but now a Kokkos View 10 | */ 11 | StridedVector JuliaToKokkos(jlcxx::ArrayRef &vec) 12 | { 13 | double* vptr = vec.data(); 14 | unsigned int vsize = vec.size(); 15 | return ToKokkos(vptr, vsize); 16 | } 17 | 18 | /** 19 | * @brief Wrap a Julia matrix in a Kokkos View 20 | * 21 | * @param mat Julia matrix to take view of 22 | * @return mpart::StridedMatrix Same memory, but now a Kokkos View 23 | */ 24 | StridedMatrix JuliaToKokkos(jlcxx::ArrayRef &mat) 25 | { 26 | double* mptr = mat.data(); 27 | unsigned int rows = size(mat,0); 28 | unsigned int cols = size(mat,1); 29 | 30 | return ToKokkos(mptr, rows, cols); 31 | } 32 | 33 | /** 34 | * @brief Wrap a Julia matrix in an Eigen Map 35 | * 36 | * @param mat Reference to the Julia matrix to wrap 37 | * @return auto an Eigen Map to the same memory as the Julia matrix 38 | */ 39 | Eigen::Map,0,Eigen::OuterStride<>> JuliaToEigenMat(jlcxx::ArrayRef mat) { 40 | int* mptr = mat.data(); 41 | unsigned int rows = size(mat,0); 42 | unsigned int cols = size(mat,1); 43 | return Eigen::Map,0,Eigen::OuterStride<>>(mptr, rows, cols, Eigen::OuterStride<>(rows)); 44 | } 45 | 46 | /** 47 | * @brief Wrap a 1D Kokkos View in a Julia vector 48 | * 49 | * @param view View to access in Julia 50 | * @return jlcxx::ArrayRef Same memory, but now a Julia array 51 | */ 52 | jlcxx::ArrayRef KokkosToJulia(StridedVector view) { 53 | double* vptr = view.data(); 54 | unsigned int sz = view.extent(0); 55 | return jlcxx::make_julia_array(vptr, sz); 56 | } 57 | 58 | /** 59 | * @brief Wrap a 2D Kokkos View in a Julia matrix 60 | * 61 | * @param view View to access in Julia 62 | * @return jlcxx::ArrayRef Same memory, but now a Julia array 63 | */ 64 | jlcxx::ArrayRef KokkosToJulia(StridedMatrix view) { 65 | double* vptr = view.data(); 66 | unsigned int rows = view.extent(0); 67 | unsigned int cols = view.extent(1); 68 | return jlcxx::make_julia_array(vptr, rows, cols); 69 | } 70 | } // namespace binding 71 | } // namespace mpart -------------------------------------------------------------------------------- /bindings/julia/src/MapFactory.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/MapFactory.h" 2 | #include "CommonJuliaUtilities.h" 3 | 4 | void mpart::binding::MapFactoryWrapper(jlcxx::Module &mod) { 5 | // CreateComponent 6 | mod.method("CreateComponent", &MapFactory::CreateComponent); 7 | 8 | // CreateTriangular 9 | mod.method("CreateTriangular", &MapFactory::CreateTriangular); 10 | } -------------------------------------------------------------------------------- /bindings/julia/src/MapObjective.cpp: -------------------------------------------------------------------------------- 1 | #include "CommonJuliaUtilities.h" 2 | #include "MParT/Distributions/GaussianSamplerDensity.h" 3 | #include "MParT/MapObjective.h" 4 | 5 | #include 6 | #include "JlArrayConversions.h" 7 | 8 | using namespace mpart; 9 | using namespace mpart::binding; 10 | 11 | namespace jlcxx { 12 | // Tell CxxWrap.jl the supertype structure for TriangularMap 13 | template<> struct SuperType> {typedef mpart::MapObjective type;}; 14 | } 15 | 16 | 17 | void mpart::binding::MapObjectiveWrapper(jlcxx::Module &mod) { 18 | using MemorySpace = Kokkos::HostSpace; 19 | std::string tName = "KLObjective"; 20 | std::string mName = "CreateGaussian"+tName; 21 | 22 | mod.add_type>("MapObjective") 23 | .method("TrainError", &MapObjective::TrainError) 24 | .method("TestError", &MapObjective::TestError) 25 | ; 26 | 27 | mod.add_type>(tName,jlcxx::julia_base_type>()); 28 | mod.method(mName, [](jlcxx::ArrayRef train, unsigned int dim) { 29 | StridedMatrix trainView = JuliaToKokkos(train); 30 | Kokkos::View storeTrain ("Training data", trainView.extent(0), trainView.extent(1)); 31 | Kokkos::deep_copy(storeTrain, trainView); 32 | trainView = storeTrain; 33 | return ObjectiveFactory::CreateGaussianKLObjective(trainView, dim); 34 | }); 35 | mod.method(mName, [](jlcxx::ArrayRef train, jlcxx::ArrayRef test, unsigned int dim) { 36 | StridedMatrix trainView = JuliaToKokkos(train); 37 | StridedMatrix testView = JuliaToKokkos(test); 38 | Kokkos::View storeTrain ("Training data", trainView.extent(0), trainView.extent(1)); 39 | Kokkos::View storeTest ("Testing data", testView.extent(0), testView.extent(1)); 40 | Kokkos::deep_copy(storeTrain, trainView); 41 | Kokkos::deep_copy(storeTest, testView); 42 | trainView = storeTrain; 43 | testView = storeTest; 44 | return ObjectiveFactory::CreateGaussianKLObjective(trainView, testView, dim); 45 | }); 46 | } 47 | 48 | -------------------------------------------------------------------------------- /bindings/julia/src/TrainMap.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/TrainMap.h" 2 | #include "CommonJuliaUtilities.h" 3 | 4 | void mpart::binding::TrainMapWrapper(jlcxx::Module &mod) { 5 | mod.add_type("__TrainOptions") 6 | .method("__opt_alg!", [](TrainOptions &opts, std::string alg){opts.opt_alg = alg;}) 7 | .method("__opt_ftol_rel!", [](TrainOptions &opts, double tol){opts.opt_ftol_rel = tol;}) 8 | .method("__opt_ftol_abs!", [](TrainOptions &opts, double tol){opts.opt_ftol_abs = tol;}) 9 | .method("__opt_xtol_rel!", [](TrainOptions &opts, double tol){opts.opt_xtol_rel = tol;}) 10 | .method("__opt_xtol_abs!", [](TrainOptions &opts, double tol){opts.opt_xtol_abs = tol;}) 11 | .method("__opt_maxeval!", [](TrainOptions &opts, int eval){opts.opt_maxeval = eval;}) 12 | .method("__verbose!", [](TrainOptions &opts, int verbose){opts.verbose = verbose;}) 13 | ; 14 | 15 | mod.set_override_module(jl_base_module); 16 | mod.method("string", [](TrainOptions opts){return opts.String();}); 17 | mod.unset_override_module(); 18 | 19 | // TrainMap 20 | mod.method("TrainMap", &mpart::TrainMap); 21 | } -------------------------------------------------------------------------------- /bindings/julia/src/TrainMapAdaptive.cpp: -------------------------------------------------------------------------------- 1 | #include "CommonJuliaUtilities.h" 2 | #include "MParT/MapOptions.h" 3 | #include "MParT/MapObjective.h" 4 | #include "MParT/TrainMap.h" 5 | #include "MParT/TrainMapAdaptive.h" 6 | 7 | #include 8 | 9 | using namespace mpart; 10 | 11 | namespace jlcxx { 12 | // Tell CxxWrap.jl the supertype structure for ConditionalMapBase 13 | template<> struct SuperType {typedef mpart::MapOptions type;}; 14 | } 15 | 16 | void mpart::binding::TrainMapAdaptiveWrapper(jlcxx::Module &mod) { 17 | // Can only do single inheritence, so I arbitrarily picked inheritence from MapOptions 18 | // If you need to convert to TrainOptions, I allow a conversion 19 | mod.add_type("__ATMOptions", jlcxx::julia_base_type()) 20 | .method("__opt_alg!", [](ATMOptions &opts, std::string alg){opts.opt_alg = alg;}) 21 | .method("__opt_ftol_rel!", [](ATMOptions &opts, double tol){opts.opt_ftol_rel = tol;}) 22 | .method("__opt_ftol_abs!", [](ATMOptions &opts, double tol){opts.opt_ftol_abs = tol;}) 23 | .method("__opt_xtol_rel!", [](ATMOptions &opts, double tol){opts.opt_xtol_rel = tol;}) 24 | .method("__opt_xtol_abs!", [](ATMOptions &opts, double tol){opts.opt_xtol_abs = tol;}) 25 | .method("__opt_maxeval!", [](ATMOptions &opts, int eval){opts.opt_maxeval = eval;}) 26 | .method("__verbose!", [](ATMOptions &opts, int verbose){opts.verbose = verbose;}) 27 | .method("__maxPatience!", [](ATMOptions &opts, int maxPatience){opts.maxPatience = maxPatience;}) 28 | .method("__maxSize!", [](ATMOptions &opts, int maxSize){opts.maxSize = maxSize;}) 29 | .method("__maxDegrees!", [](ATMOptions &opts, MultiIndex &maxDegrees){opts.maxDegrees = maxDegrees;}) 30 | .method("TrainOptions", [](ATMOptions &opts){ return static_cast(opts);}) 31 | ; 32 | 33 | 34 | mod.method("TrainMapAdaptive", [](jlcxx::ArrayRef arr, std::shared_ptr> objective, ATMOptions options) { 35 | std::vector vec (arr.begin(), arr.end()); 36 | auto map = TrainMapAdaptive(vec, objective, options); 37 | for(int i = 0; i < vec.size(); i++) arr[i] = vec[i]; 38 | return map; 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /bindings/julia/src/TriangularMap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "MParT/TriangularMap.h" 3 | 4 | #include "CommonJuliaUtilities.h" 5 | #include "JlArrayConversions.h" 6 | 7 | namespace jlcxx { 8 | // Tell CxxWrap.jl the supertype structure for TriangularMap 9 | template<> struct SuperType> {typedef mpart::ConditionalMapBase type;}; 10 | } 11 | 12 | void mpart::binding::TriangularMapWrapper(jlcxx::Module &mod) { 13 | mod.add_type>("TriangularMap", jlcxx::julia_base_type>()) 14 | .method("InverseInplace", [](TriangularMap &map, jlcxx::ArrayRef x, jlcxx::ArrayRef r){ 15 | map.InverseInplace(JuliaToKokkos(x), JuliaToKokkos(r)); 16 | }) 17 | .method("GetComponent", &TriangularMap::GetComponent) 18 | ; 19 | 20 | mod.method("TriangularMap", [](std::vector>> vec){ 21 | return std::static_pointer_cast>(std::make_shared>(vec)); 22 | }); 23 | 24 | } -------------------------------------------------------------------------------- /bindings/julia/src/Wrapper.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "MParT/MapFactory.h" 4 | 5 | #include "CommonJuliaUtilities.h" 6 | #include "CommonUtilities.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "CommonJuliaUtilities.h" 14 | #include "JlArrayConversions.h" 15 | 16 | using namespace mpart; 17 | 18 | JLCXX_MODULE MParT_julia_module(jlcxx::Module& mod) 19 | { 20 | binding::CommonUtilitiesWrapper(mod); 21 | binding::MultiIndexWrapper(mod); 22 | binding::MapOptionsWrapper(mod); 23 | binding::ParameterizedFunctionBaseWrapper(mod); 24 | binding::ConditionalMapBaseWrapper(mod); 25 | binding::TriangularMapWrapper(mod); 26 | binding::ComposedMapWrapper(mod); 27 | binding::AffineMapWrapper(mod); 28 | binding::AffineFunctionWrapper(mod); 29 | binding::MapFactoryWrapper(mod); 30 | #if defined(MPART_HAS_NLOPT) 31 | binding::MapObjectiveWrapper(mod); 32 | binding::TrainMapWrapper(mod); 33 | binding::TrainMapAdaptiveWrapper(mod); 34 | #endif // MPART_HAS_NLOPT 35 | } -------------------------------------------------------------------------------- /bindings/matlab/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | include_directories(include) 4 | include_directories(external) 5 | include_directories(external/mexplus) 6 | 7 | set(MEX_SOURCE 8 | src/KokkosUtilities_mex.cpp 9 | src/ConditionalMap_mex.cpp 10 | src/MultiIndexSet_mex.cpp 11 | src/MultiIndex_mex.cpp 12 | src/FixedMultiIndexSet_mex.cpp 13 | src/ParameterizedFunctionBase_mex.cpp 14 | src/MexArrayConversions.cpp 15 | src/MexOptionsConversions.cpp 16 | ) 17 | 18 | if(MPART_OPT) 19 | set(MEX_SOURCE ${MEX_SOURCE} 20 | src/MapObjective_mex.cpp 21 | ) 22 | endif() 23 | 24 | matlab_add_mex(NAME MParT_ SRC ${MEX_SOURCE} LINK_TO mpart Kokkos::kokkos Eigen3::Eigen ${EXT_LIBRARIES}) 25 | 26 | # Add an installation target for the matlab bindings 27 | install(TARGETS MParT_ DESTINATION matlab) 28 | install(DIRECTORY mat/ DESTINATION matlab) -------------------------------------------------------------------------------- /bindings/matlab/external/mexplus/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Kota Yamaguchi 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. The name of the author may not be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /bindings/matlab/external/mexplus/mexplus.h: -------------------------------------------------------------------------------- 1 | /** MEXPLUS: C++ Matlab MEX development kit. 2 | * 3 | * Copyright 2014 Kota Yamaguchi. 4 | */ 5 | 6 | #ifndef INCLUDE_MEXPLUS_H_ 7 | #define INCLUDE_MEXPLUS_H_ 8 | 9 | #include "mexplus/arguments.h" 10 | #include "mexplus/dispatch.h" 11 | 12 | #endif // INCLUDE_MEXPLUS_H_ 13 | -------------------------------------------------------------------------------- /bindings/matlab/include/MexArrayConversions.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_MEXARRAYCONVERSIONS_H 2 | #define MPART_MEXARRAYCONVERSIONS_H 3 | 4 | #include 5 | #include 6 | 7 | namespace mpart{ 8 | 9 | /** Converts a real-valued matlab vector to a Kokkos::View. The memory in matlab vector is not copied for performance 10 | reasons. However, this means that the user is responsible for ensuring the vector is not freed before the view. 11 | */ 12 | Kokkos::View MexToKokkos1d(const mxArray *mx); 13 | 14 | /** Converts a real-valued matlab matrix to a Kokkos view. The memory in matlab matrix is not copied for performance 15 | reasons. However, this means that the user is responsible for ensuring the matrix is not freed before the view.*/ 16 | Kokkos::View MexToKokkos2d(const mxArray *mx); 17 | } 18 | 19 | 20 | #endif -------------------------------------------------------------------------------- /bindings/matlab/include/MexOptionsConversions.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_MEXOPTIONSCONVERSIONS_H 2 | #define MPART_MEXOPTIONSCONVERSIONS_H 3 | 4 | #include 5 | #include 6 | #include "MParT/MapOptions.h" 7 | #if defined(MPART_HAS_NLOPT) 8 | #include "MParT/TrainMapAdaptive.h" 9 | #endif // defined(MPART_HAS_NLOPT) 10 | 11 | namespace mpart{ 12 | namespace binding{ 13 | 14 | MapOptions MapOptionsFromMatlab(std::string basisType, std::string posFuncType, 15 | std::string quadType, double quadAbsTol, 16 | double quadRelTol, unsigned int quadMaxSub, 17 | unsigned int quadMinSub,unsigned int quadPts, 18 | bool contDeriv, double basisLB, double basisUB, 19 | bool basisNorm, double nugget); 20 | 21 | void MapOptionsToMatlab(MapOptions opts, mexplus::OutputArguments &output, int start = 0); 22 | #if defined(MPART_HAS_NLOPT) 23 | TrainOptions TrainOptionsFromMatlab(mexplus::InputArguments &input, unsigned int start); 24 | ATMOptions ATMOptionsFromMatlab(mexplus::InputArguments &input, unsigned int start); 25 | ATMOptions ATMOptionsFromMatlab(std::string basisType, std::string posFuncType, 26 | std::string quadType, double quadAbsTol, 27 | double quadRelTol, unsigned int quadMaxSub, 28 | unsigned int quadMinSub,unsigned int quadPts, 29 | bool contDeriv, double basisLB, double basisUB, bool basisNorm, 30 | std::string opt_alg, double opt_stopval, 31 | double opt_ftol_rel, double opt_ftol_abs, 32 | double opt_xtol_rel, double opt_xtol_abs, 33 | int opt_maxeval, double opt_maxtime, int verbose, 34 | unsigned int maxPatience, unsigned int maxSize, MultiIndex& maxDegrees); 35 | #endif // defined(MPART_HAS_NLOPT) 36 | } 37 | } 38 | 39 | 40 | #endif -------------------------------------------------------------------------------- /bindings/matlab/include/MexWrapperTypes.h: -------------------------------------------------------------------------------- 1 | #ifndef MPART_MEXWRAPPERTYPES_H 2 | #define MPART_MEXWRAPPERTYPES_H 3 | 4 | #include 5 | #include 6 | #include "MParT/ConditionalMapBase.h" 7 | #include "MParT/TriangularMap.h" 8 | #include "MParT/ComposedMap.h" 9 | #include "MParT/AffineMap.h" 10 | #include "MParT/MapObjective.h" 11 | 12 | 13 | using namespace mpart; 14 | using namespace mexplus; 15 | using MemorySpace = Kokkos::HostSpace; 16 | 17 | class ConditionalMapMex { // The class 18 | public: 19 | std::shared_ptr> map_ptr; 20 | 21 | ConditionalMapMex(FixedMultiIndexSet const& mset, 22 | MapOptions opts){ 23 | map_ptr = MapFactory::CreateComponent(mset,opts); 24 | } 25 | 26 | ConditionalMapMex(std::shared_ptr> init_ptr){ 27 | map_ptr = init_ptr; 28 | } 29 | 30 | ConditionalMapMex(std::vector>> blocks){ 31 | map_ptr = std::make_shared>(blocks); 32 | } 33 | 34 | ConditionalMapMex(unsigned int inputDim, unsigned int outputDim, unsigned int totalOrder, MapOptions opts){ 35 | map_ptr = MapFactory::CreateTriangular(inputDim,outputDim,totalOrder,opts); 36 | } 37 | 38 | ConditionalMapMex(std::vector>> triMaps,std::string typeMap){ 39 | map_ptr = std::make_shared>(triMaps); 40 | } 41 | 42 | ConditionalMapMex(StridedMatrix A, StridedVector b){ 43 | map_ptr = std::make_shared>(A,b); 44 | } 45 | 46 | ConditionalMapMex(StridedMatrix A){ 47 | map_ptr = std::make_shared>(A); 48 | } 49 | 50 | ConditionalMapMex(StridedVector b){ 51 | map_ptr = std::make_shared>(b); 52 | } 53 | 54 | }; //end class 55 | 56 | class ParameterizedFunctionMex { // The class 57 | public: 58 | std::shared_ptr> fun_ptr; 59 | 60 | ParameterizedFunctionMex(unsigned int outputDim, FixedMultiIndexSet const& mset, 61 | MapOptions opts){ 62 | fun_ptr = MapFactory::CreateExpansion(outputDim,mset,opts); 63 | } 64 | 65 | ParameterizedFunctionMex(std::shared_ptr> init_ptr){ 66 | fun_ptr = init_ptr; 67 | } 68 | }; //end class 69 | 70 | class MapObjectiveMex { // The class 71 | public: 72 | std::shared_ptr> obj_ptr; 73 | 74 | MapObjectiveMex(std::shared_ptr> init_ptr): obj_ptr(init_ptr) {}; 75 | }; 76 | 77 | // Instance manager for ConditionalMap. 78 | template class mexplus::Session; 79 | template class mexplus::Session; 80 | template class mexplus::Session; 81 | 82 | 83 | #endif // MPART_MEXWRAPPERTYPES_H -------------------------------------------------------------------------------- /bindings/matlab/mat/ATMOptions.m: -------------------------------------------------------------------------------- 1 | classdef ATMOptions < TrainOptions & MapOptions 2 | properties (Access = public) 3 | maxPatience = 10; 4 | maxSize = 10; 5 | maxDegrees = MultiIndex(0); 6 | end 7 | methods 8 | function obj = set.maxPatience(obj,value) 9 | obj.maxPatience = value; 10 | end 11 | function obj = set.maxSize(obj,value) 12 | obj.maxSize = value; 13 | end 14 | function obj = set.maxDegrees(obj,value) 15 | obj.maxDegrees = value; 16 | end 17 | function optionsArray = getMexOptions(obj) 18 | optionsArray{1} = char(obj.basisType); 19 | optionsArray{2} = char(obj.posFuncType); 20 | optionsArray{3} = char(obj.quadType); 21 | optionsArray{4} = obj.quadAbsTol; 22 | optionsArray{5} = obj.quadRelTol; 23 | optionsArray{6} = obj.quadMaxSub; 24 | optionsArray{7} = obj.quadMinSub; 25 | optionsArray{8} = obj.quadPts; 26 | optionsArray{9} = obj.contDeriv; 27 | optionsArray{10} = obj.basisLB; 28 | optionsArray{11} = obj.basisUB; 29 | optionsArray{12} = obj.basisNorm; 30 | optionsArray{12+1} = char(obj.opt_alg); 31 | optionsArray{12+2} = obj.opt_stopval; 32 | optionsArray{12+3} = obj.opt_ftol_rel; 33 | optionsArray{12+4} = obj.opt_ftol_abs; 34 | optionsArray{12+5} = obj.opt_xtol_rel; 35 | optionsArray{12+6} = obj.opt_xtol_abs; 36 | optionsArray{12+7} = obj.opt_maxeval; 37 | optionsArray{12+8} = obj.opt_maxtime; 38 | optionsArray{12+9} = obj.verbose; 39 | optionsArray{12+9+1} = obj.maxPatience; 40 | optionsArray{12+9+2} = obj.maxSize; 41 | optionsArray{12+9+3} = obj.maxDegrees.get_id(); 42 | end 43 | end 44 | end -------------------------------------------------------------------------------- /bindings/matlab/mat/AdaptiveTransportMap.m: -------------------------------------------------------------------------------- 1 | function map = TrainMapAdaptive(mset0, objective, atm_options) 2 | mexOptions = atm_options.getMexOptions; 3 | mset_ids = arrayfun(@(mset) mset.get_id(), mset0); 4 | input_str=['map_ptr = MParT_(',char(39),'ConditionalMap_TrainMapAdaptive',char(39),',mset_ids,objective.get_id()']; 5 | for o=1:length(mexOptions) 6 | input_o=[',mexOptions{',num2str(o),'}']; 7 | input_str=[input_str,input_o]; 8 | end 9 | input_str=[input_str,');']; 10 | eval(input_str); 11 | map = ConditionalMap(map_ptr,"id"); 12 | end -------------------------------------------------------------------------------- /bindings/matlab/mat/AffineMap.m: -------------------------------------------------------------------------------- 1 | function map = AffineMap(varargin) 2 | if(nargin == 1) 3 | % this not very safe (matlab vector is a matrix and vectors can be vertical or horizontal) 4 | if isvector(varargin{1}) 5 | map = ConditionalMap(varargin{1},"b"); 6 | else 7 | map = ConditionalMap(varargin{1},"A"); 8 | end 9 | elseif(nargin == 2) 10 | map = ConditionalMap(varargin{1},varargin{2},"Ab"); 11 | else 12 | error("Wrong number of input arguments"); 13 | end 14 | 15 | end -------------------------------------------------------------------------------- /bindings/matlab/mat/ComposedMap.m: -------------------------------------------------------------------------------- 1 | function map = ComposedMap(listTriMaps) 2 | listTriMaps_ids =[]; 3 | for i=1:length(listTriMaps) 4 | listTriMaps_ids=[listTriMaps_ids,listTriMaps(i).get_id()]; 5 | end 6 | map = ConditionalMap(listTriMaps_ids,"compose"); 7 | end -------------------------------------------------------------------------------- /bindings/matlab/mat/CreateComponent.m: -------------------------------------------------------------------------------- 1 | function map = CreateComponent(mset, options) 2 | map = ConditionalMap(mset,options); 3 | end -------------------------------------------------------------------------------- /bindings/matlab/mat/CreateTriangular.m: -------------------------------------------------------------------------------- 1 | function map = CreateTriangular(inDim, outDim, order, opts) 2 | map = ConditionalMap(inDim, outDim, order, opts); 3 | end -------------------------------------------------------------------------------- /bindings/matlab/mat/DeserializeMap.m: -------------------------------------------------------------------------------- 1 | function [inputDim,outputDim,coeffs] = DeserializeMap(filename) 2 | [inputDim,outputDim,coeffs] = MParT_('ParameterizedFunction_DeserializeMap', filename); 3 | end -------------------------------------------------------------------------------- /bindings/matlab/mat/FixedMultiIndexSet.m: -------------------------------------------------------------------------------- 1 | classdef FixedMultiIndexSet < handle 2 | 3 | properties (Access = private) 4 | id_ 5 | end 6 | 7 | methods 8 | function this = FixedMultiIndexSet(varargin) 9 | if(nargin==1) 10 | this.id_ = MParT_('FixedMultiIndexSet_fromMultiIndexSet', varargin{1}.get_id()); 11 | else 12 | this.id_ = MParT_('FixedMultiIndexSet_newTotalOrder',varargin{1},varargin{2}); 13 | end 14 | end 15 | 16 | function delete(this) 17 | %DELETE Destructor. 18 | MParT_('FixedMultiIndexSet_delete', this.id_); 19 | end 20 | 21 | function result = MaxDegrees(this) 22 | result = MParT_('FixedMultiIndexSet_MaxDegrees', this.id_); 23 | end 24 | 25 | function Print(this) 26 | MParT_('FixedMultiIndexSet_Print', this.id_); 27 | end 28 | 29 | function size = Size(this) 30 | size = MParT_('FixedMultiIndexSet_Size', this.id_); 31 | end 32 | 33 | function ind = MultiToIndex(this, multi) 34 | ind = MParT_('FixedMultiIndexSet_MultiToIndex', this.id_, multi); 35 | ind = ind + 1; 36 | end 37 | 38 | function multi = IndexToMulti(this, index) 39 | multi = MParT_('FixedMultiIndexSet_IndexToMulti', this.id_, index-1); 40 | end 41 | 42 | function dim = Length(this) 43 | dim = MParT_('FixedMultiIndexSet_Length', this.id_); 44 | end 45 | 46 | function result = get_id(this) 47 | result = this.id_; 48 | end 49 | 50 | function Serialize(this,filename) 51 | MParT_('FixedMultiIndexSet_Serialize', this.id_, filename); 52 | end 53 | 54 | function Deserialize(this,filename) 55 | MParT_('FixedMultiIndexSet_Deserialize', this.id_, filename); 56 | end 57 | 58 | end 59 | 60 | end 61 | -------------------------------------------------------------------------------- /bindings/matlab/mat/GaussianKLObjective.m: -------------------------------------------------------------------------------- 1 | classdef GaussianKLObjective < handle 2 | 3 | properties (Access = private) 4 | id_ 5 | end 6 | 7 | methods 8 | function this = GaussianKLObjective(train, test, dim) 9 | if(nargin==1) 10 | this.id_ = MParT_('GaussianKLObjective_newTrain',train,0); 11 | elseif(isinteger(test)) 12 | this.id_ = MParT_('GaussianKLObjective_newTrain',train,test); 13 | elseif(nargin==2) 14 | this.id_ = MParT_('GaussianKLObjective_newTrainTest',train,test,0); 15 | else 16 | this.id_ = MParT_('GaussianKLObjective_newTrainTest',train,test,dim); 17 | end 18 | end 19 | 20 | function delete(this) 21 | MParT_('MapObjective_delete',this.id_); 22 | end 23 | 24 | function result = TestError(this, map) 25 | result = MParT_('GaussianKLObjective_TestError',this.id_,map.get_id()); 26 | end 27 | 28 | function result = TrainError(this, map) 29 | result = MParT_('GaussianKLObjective_TrainError',this.id_,map.get_id()); 30 | end 31 | 32 | function result = TrainCoeffGrad(this, map) 33 | result = zeros(map.numCoeffs,1); 34 | MParT_('GaussianKLObjective_TrainCoeffGrad', this.id_, map.get_id(),result); 35 | end 36 | 37 | function result = get_id(this) 38 | result = this.id_; 39 | end 40 | 41 | end 42 | end -------------------------------------------------------------------------------- /bindings/matlab/mat/KokkosInitialize.m: -------------------------------------------------------------------------------- 1 | function KokkosInitialize(num_threads) 2 | MParT_('Kokkos_Initialize', num_threads); 3 | end -------------------------------------------------------------------------------- /bindings/matlab/mat/MapOptions/BasisTypes.m: -------------------------------------------------------------------------------- 1 | classdef BasisTypes 2 | enumeration 3 | ProbabilistHermite, PhysicistHermite,HermiteFunctions 4 | end 5 | end -------------------------------------------------------------------------------- /bindings/matlab/mat/MapOptions/PosFuncTypes.m: -------------------------------------------------------------------------------- 1 | classdef PosFuncTypes 2 | enumeration 3 | Exp,SoftPlus 4 | end 5 | end -------------------------------------------------------------------------------- /bindings/matlab/mat/MapOptions/QuadTypes.m: -------------------------------------------------------------------------------- 1 | classdef QuadTypes 2 | enumeration 3 | ClenshawCurtis,AdaptiveSimpson,AdaptiveClenshawCurtis 4 | end 5 | end -------------------------------------------------------------------------------- /bindings/matlab/mat/TrainMap.m: -------------------------------------------------------------------------------- 1 | function TrainMap(map, objective, train_options) 2 | mexOptions = train_options.getMexOptions; 3 | input_str=['MParT_(',char(39),'ConditionalMap_TrainMap',char(39),',map.get_id(),objective.get_id()']; 4 | for o=1:length(mexOptions) 5 | input_o=[',mexOptions{',num2str(o),'}']; 6 | input_str=[input_str,input_o]; 7 | end 8 | input_str=[input_str,')']; 9 | eval(input_str); 10 | end -------------------------------------------------------------------------------- /bindings/matlab/mat/TrainOptions.m: -------------------------------------------------------------------------------- 1 | classdef TrainOptions 2 | properties (Access = public) 3 | opt_alg = "LD_SLSQP" 4 | opt_stopval = log(0) 5 | opt_ftol_rel = 1e-3 6 | opt_ftol_abs = 1e-3 7 | opt_xtol_rel = 1e-4 8 | opt_xtol_abs = 1e-4 9 | opt_maxeval = 30 10 | opt_maxtime = 1e2 11 | verbose = 0 12 | end 13 | 14 | methods 15 | function obj = set.opt_alg(obj,value) 16 | obj.opt_alg = value; 17 | end 18 | function obj = set.opt_stopval(obj,value) 19 | obj.opt_stopval = value; 20 | end 21 | function obj = set.opt_ftol_rel(obj,value) 22 | obj.opt_ftol_rel = value; 23 | end 24 | function obj = set.opt_ftol_abs(obj,value) 25 | obj.opt_ftol_abs = value; 26 | end 27 | function obj = set.opt_xtol_rel(obj,value) 28 | obj.opt_xtol_rel = value; 29 | end 30 | function obj = set.opt_xtol_abs(obj,value) 31 | obj.opt_xtol_abs = value; 32 | end 33 | function obj = set.opt_maxeval(obj,value) 34 | obj.opt_maxeval = value; 35 | end 36 | function obj = set.opt_maxtime(obj,value) 37 | obj.opt_maxtime = value; 38 | end 39 | function obj = set.verbose(obj,value) 40 | obj.verbose = value; 41 | end 42 | function optionsArray = getMexOptions(obj) 43 | optionsArray{1} = char(obj.opt_alg); 44 | optionsArray{2} = obj.opt_stopval; 45 | optionsArray{3} = obj.opt_ftol_rel; 46 | optionsArray{4} = obj.opt_ftol_abs; 47 | optionsArray{5} = obj.opt_xtol_rel; 48 | optionsArray{6} = obj.opt_xtol_abs; 49 | optionsArray{7} = obj.opt_maxeval; 50 | optionsArray{8} = obj.opt_maxtime; 51 | optionsArray{9} = obj.verbose; 52 | end 53 | end 54 | end -------------------------------------------------------------------------------- /bindings/matlab/mat/TriangularMap.m: -------------------------------------------------------------------------------- 1 | function map = TriangularMap(listCondMaps) 2 | listCondMap_ids =[]; 3 | for i=1:length(listCondMaps) 4 | listCondMap_ids=[listCondMap_ids,listCondMaps(i).get_id()]; 5 | end 6 | map = ConditionalMap(listCondMap_ids); 7 | end -------------------------------------------------------------------------------- /bindings/matlab/src/KokkosUtilities_mex.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | using namespace mexplus; 8 | 9 | namespace { 10 | 11 | // Defines MEX API for new. 12 | MEX_DEFINE(Kokkos_Initialize) (int nlhs, mxArray* plhs[], 13 | int nrhs, const mxArray* prhs[]) { 14 | InputArguments input(nrhs, prhs, 1); 15 | OutputArguments output(nlhs, plhs, 0); 16 | mpart::Initialize(Kokkos::InitializationSettings() 17 | .set_num_threads(input.get(0))); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /bindings/matlab/src/MapObjective_mex.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/Utilities/ArrayConversions.h" 2 | #include "MParT/MultiIndices/FixedMultiIndexSet.h" 3 | #include "MParT/MapOptions.h" 4 | #include "MParT/MapFactory.h" 5 | #include "MParT/Distributions/GaussianSamplerDensity.h" 6 | #include "MParT/MapObjective.h" 7 | #include "MParT/TrainMap.h" 8 | 9 | #include "MexWrapperTypes.h" 10 | #include "MexArrayConversions.h" 11 | #include "mexplus_eigen.h" 12 | 13 | using namespace mpart; 14 | using namespace mexplus; 15 | using MemorySpace = Kokkos::HostSpace; 16 | 17 | namespace { 18 | // Defines MEX API for new. 19 | MEX_DEFINE(GaussianKLObjective_newTrain) (int nlhs, mxArray* plhs[], 20 | int nrhs, const mxArray* prhs[]) { 21 | 22 | InputArguments input(nrhs, prhs, 2); 23 | OutputArguments output(nlhs, plhs, 1); 24 | StridedMatrix train = MexToKokkos2d(prhs[0]); 25 | unsigned int dim = input.get(1); 26 | std::shared_ptr> objective = ObjectiveFactory::CreateGaussianKLObjective(train, dim); 27 | output.set(0, Session::create(new MapObjectiveMex(objective))); 28 | } 29 | 30 | // Defines MEX API for new. 31 | MEX_DEFINE(GaussianKLObjective_newTrainTest) (int nlhs, mxArray* plhs[], 32 | int nrhs, const mxArray* prhs[]) { 33 | 34 | InputArguments input(nrhs, prhs, 3); 35 | OutputArguments output(nlhs, plhs, 1); 36 | StridedMatrix train = MexToKokkos2d(prhs[0]); 37 | StridedMatrix test = MexToKokkos2d(prhs[1]); 38 | unsigned int dim = input.get(2); 39 | std::shared_ptr> objective = ObjectiveFactory::CreateGaussianKLObjective(train, test, dim); 40 | output.set(0, Session::create(new MapObjectiveMex(objective))); 41 | } 42 | 43 | // Defines MEX API for delete. 44 | MEX_DEFINE(MapObjective_delete) (int nlhs, mxArray* plhs[], 45 | int nrhs, const mxArray* prhs[]) { 46 | InputArguments input(nrhs, prhs, 1); 47 | OutputArguments output(nlhs, plhs, 0); 48 | Session::destroy(input.get(0)); 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /bindings/matlab/src/MexArrayConversions.cpp: -------------------------------------------------------------------------------- 1 | #include "MexArrayConversions.h" 2 | 3 | #include 4 | 5 | using namespace mpart; 6 | 7 | Kokkos::View mpart::MexToKokkos1d(const mxArray *mx) 8 | { 9 | size_t rows = mxGetN(mx); 10 | size_t cols = mxGetM(mx); 11 | 12 | // if(mxIsComplex(mx)){ 13 | // std::stringstream msg; 14 | // msg << "In mpart::MexToKokkos2d. The input matrix is complex, not real."; 15 | // throw std::invalid_argument(msg.str()); 16 | // } 17 | 18 | // if(! mxIsDouble(mx)){ 19 | // std::stringstream msg; 20 | // msg << "In mpart::MexToKokkos2d. The input matrix is not double precision."; 21 | // throw std::invalid_argument(msg.str()); 22 | // } 23 | 24 | // if((rows!=1)&&(cols!=1)){ 25 | // std::stringstream msg; 26 | // msg << "In mpart::MexToKokkos1d. The size of the input array is not 1d! Did you mean to call MexToKokkos2d?"; 27 | // throw std::invalid_argument(msg.str()); 28 | // } 29 | 30 | unsigned int length = std::max(rows,cols); 31 | double *data = (double *) mxGetData(mx); 32 | 33 | return Kokkos::View>(data, length); 34 | } 35 | 36 | 37 | Kokkos::View mpart::MexToKokkos2d(const mxArray *mx) 38 | { 39 | size_t cols = mxGetN(mx); 40 | size_t rows = mxGetM(mx); 41 | 42 | if(mxIsComplex(mx)){ 43 | std::stringstream msg; 44 | msg << "In mpart::MexToKokkos2d. The input matrix is complex, not real."; 45 | throw std::invalid_argument(msg.str()); 46 | } 47 | 48 | if(! mxIsDouble(mx)){ 49 | std::stringstream msg; 50 | msg << "In mpart::MexToKokkos2d. The input matrix is not double precision."; 51 | throw std::invalid_argument(msg.str()); 52 | } 53 | 54 | double *data = (double *) mxGetData(mx); 55 | 56 | return Kokkos::View>(data, rows, cols); 57 | } -------------------------------------------------------------------------------- /bindings/matlab/tests/FixedMultiIndexSetTest.m: -------------------------------------------------------------------------------- 1 | classdef FixedMultiIndexSetTest < matlab.unittest.TestCase 2 | % Copyright 2014 - 2016 The MathWorks, Inc. 3 | 4 | methods ( Test ) 5 | 6 | function size( testCase ) 7 | dim = 2; 8 | maxOrder = 3; 9 | mset = FixedMultiIndexSet(dim,maxOrder); 10 | testCase.verifyEqual( double(mset.Size()), ((maxOrder+1)*(maxOrder+2)/2) ); 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /bindings/matlab/tests/Test_AffineMap.m: -------------------------------------------------------------------------------- 1 | clear 2 | 3 | addpath(genpath('~/Installations/MParT/')); 4 | 5 | KokkosInitialize(8); 6 | 7 | A = 2.*eye(2); 8 | b = [-0.3;0.5]; 9 | 10 | T1 = AffineMap(A); 11 | T2 = AffineMap(b); 12 | T3 = AffineMap(A,b); 13 | 14 | x = [linspace(-4,4,11);linspace(-4,4,11)]; 15 | 16 | y1 = T1.Evaluate(x); 17 | y2 = T2.Evaluate(x); 18 | y3 = T3.Evaluate(x); 19 | 20 | -------------------------------------------------------------------------------- /bindings/matlab/tests/Test_ComposedMap.m: -------------------------------------------------------------------------------- 1 | clear 2 | 3 | addpath(genpath('~/Installations/MParT/')); 4 | 5 | KokkosInitialize(8); 6 | 7 | opts = MapOptions(); %Setting options to default 8 | 9 | T1 = CreateTriangular(2,2,2,opts); 10 | T2 = CreateTriangular(2,2,2,opts); 11 | 12 | T = ComposedMap([T1 T2]); 13 | 14 | Y=T.Evaluate(randn(2,10)); 15 | -------------------------------------------------------------------------------- /bindings/matlab/tests/Test_MultiIndex.m: -------------------------------------------------------------------------------- 1 | clear; 2 | addpath(genpath('.')); 3 | 4 | KokkosInitialize(8); 5 | 6 | a=[2,3,4]; 7 | multi=MultiIndex(a); 8 | multi.String() 9 | 10 | multi2=MultiIndex(6,1); 11 | multi2.String() 12 | 13 | multi3=MultiIndex([0,1,2,3]); %Not sure we want to keep this 14 | multi3.String() 15 | 16 | multi3.Set(1,9); 17 | multi3.Vector(); 18 | 19 | disp(multi2==multi3); 20 | disp(multi2~=multi2); 21 | 22 | disp(multi2>multi3) 23 | 24 | disp(multi2>=multi3) 25 | disp(multi2<=multi2) 26 | disp(multi3 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "../../common/include/CommonUtilities.h" 11 | 12 | namespace mpart{ 13 | namespace binding{ 14 | 15 | /** Define a wrapper around Kokkos::Initialize that accepts a python dictionary instead of argc and argv. */ 16 | void Initialize(pybind11::dict opts); 17 | 18 | /** 19 | @brief Adds the pybind11 bindings to the existing module pybind11 module m. 20 | @param m pybind11 module 21 | */ 22 | void CommonUtilitiesWrapper(pybind11::module &m); 23 | 24 | void MapOptionsWrapper(pybind11::module &m); 25 | 26 | void MultiIndexWrapper(pybind11::module &m); 27 | 28 | template 29 | void ConditionalMapBaseWrapper(pybind11::module &m); 30 | 31 | template 32 | void ParameterizedFunctionBaseWrapper(pybind11::module &m); 33 | 34 | template 35 | void TriangularMapWrapper(pybind11::module &m); 36 | 37 | template 38 | void ComposedMapWrapper(pybind11::module &m); 39 | 40 | template 41 | void SummarizedMapWrapper(pybind11::module &m); 42 | 43 | template 44 | void IdentityMapWrapper(pybind11::module &m); 45 | 46 | // template 47 | // void DebugMapWrapper(pybind11::module &m); 48 | 49 | #if defined(MPART_HAS_NLOPT) 50 | void TrainOptionsWrapper(pybind11::module &m); 51 | 52 | template 53 | void MapObjectiveWrapper(pybind11::module &m); 54 | 55 | template 56 | void MapFactoryWrapper(pybind11::module &m); 57 | 58 | template 59 | void TrainMapWrapper(pybind11::module &m); 60 | 61 | void ATMOptionsWrapper(pybind11::module &m); 62 | 63 | template 64 | void TrainMapAdaptiveWrapper(pybind11::module &m); 65 | #endif 66 | 67 | 68 | #if defined(MPART_HAS_CEREAL) 69 | template 70 | void DeserializeWrapper(pybind11::module &m); 71 | #endif // MPART_HAS_CEREAL 72 | 73 | void AffineMapWrapperHost(pybind11::module &m); 74 | void AffineMapWrapperDevice(pybind11::module &m); 75 | void AffineFunctionWrapperHost(pybind11::module &m); 76 | void AffineFunctionWrapperDevice(pybind11::module &m); 77 | 78 | } // namespace binding 79 | } // namespace mpart 80 | 81 | 82 | 83 | 84 | #endif -------------------------------------------------------------------------------- /bindings/python/package/__init__.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from .pympart import * 3 | 4 | kokkos_init = Initialize(dict()) 5 | sys.modules[__name__] = sys.modules['mpart'] 6 | 7 | try: 8 | from .torch import * 9 | mpart_has_torch = True 10 | except ImportError: 11 | mpart_has_torch = False 12 | 13 | -------------------------------------------------------------------------------- /bindings/python/src/CommonPybindUtilities.cpp: -------------------------------------------------------------------------------- 1 | #include "CommonPybindUtilities.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "MParT/Initialization.h" 7 | #include 8 | 9 | #include 10 | 11 | namespace py = pybind11; 12 | using namespace mpart::binding; 13 | 14 | // Define a wrapper around Kokkos::Initialize that accepts a python dictionary instead of argc and argv. 15 | void mpart::binding::Initialize(py::dict opts) { 16 | 17 | std::vector args; 18 | 19 | pybind11::object keys = pybind11::list(opts.attr("keys")()); 20 | std::vector keysCpp = keys.cast>(); 21 | 22 | for(auto& key : keysCpp){ 23 | args.push_back("--" + key + "=" + py::cast(opts.attr("get")(key))); 24 | } 25 | 26 | mpart::binding::Initialize(args); 27 | }; 28 | 29 | void mpart::binding::CommonUtilitiesWrapper(py::module &m) 30 | { 31 | m.def("Initialize", py::overload_cast( &mpart::binding::Initialize )); 32 | m.def("Concurrency", &Kokkos::DefaultExecutionSpace::concurrency); 33 | } 34 | -------------------------------------------------------------------------------- /bindings/python/src/ComposedMap.cpp: -------------------------------------------------------------------------------- 1 | #include "CommonPybindUtilities.h" 2 | #include "MParT/ComposedMap.h" 3 | #include "MParT/ConditionalMapBase.h" 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace py = pybind11; 11 | using namespace mpart::binding; 12 | 13 | template 14 | void mpart::binding::ComposedMapWrapper(py::module &m) 15 | { 16 | std::string tName = "ComposedMap"; 17 | if(!std::is_same::value) tName = "d" + tName; 18 | 19 | // ComposedMap 20 | py::class_, ConditionalMapBase, std::shared_ptr>>(m, tName.c_str()) 21 | .def(py::init>>,bool,int>(), py::arg("maps"), py::arg("moveCoeffs") = false, py::arg("maxChecks")=-1) 22 | ; 23 | 24 | } 25 | 26 | template void mpart::binding::ComposedMapWrapper(py::module&); 27 | #if defined(MPART_ENABLE_GPU) 28 | template void mpart::binding::ComposedMapWrapper(py::module&); 29 | #endif // MPART_ENABLE_GPU -------------------------------------------------------------------------------- /bindings/python/src/IdentityMap.cpp: -------------------------------------------------------------------------------- 1 | #include "CommonPybindUtilities.h" 2 | #include "MParT/IdentityMap.h" 3 | #include "MParT/ConditionalMapBase.h" 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace py = pybind11; 11 | using namespace mpart::binding; 12 | 13 | template 14 | void mpart::binding::IdentityMapWrapper(py::module &m) 15 | { 16 | std::string tName = "IdentityMap"; 17 | if(!std::is_same::value) tName = "d" + tName; 18 | 19 | // IdentityMap 20 | py::class_, ConditionalMapBase, std::shared_ptr>>(m, tName.c_str()) 21 | .def(py::init()) 22 | ; 23 | 24 | } 25 | 26 | template void mpart::binding::IdentityMapWrapper(py::module&); 27 | #if defined(MPART_ENABLE_GPU) 28 | template void mpart::binding::IdentityMapWrapper(py::module&); 29 | #endif // MPART_ENABLE_GPU -------------------------------------------------------------------------------- /bindings/python/src/MapFactory.cpp: -------------------------------------------------------------------------------- 1 | #include "CommonPybindUtilities.h" 2 | #include "MParT/MapFactory.h" 3 | #include "MParT/ConditionalMapBase.h" 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace py = pybind11; 11 | using namespace mpart::binding; 12 | 13 | template 14 | void mpart::binding::MapFactoryWrapper(py::module &m) 15 | { 16 | bool isDevice = !std::is_same::value; 17 | // CreateComponent 18 | m.def(isDevice? "dCreateComponent" : "CreateComponent", &MapFactory::CreateComponent); 19 | 20 | // CreateTriangular 21 | m.def(isDevice? "dCreateTriangular" : "CreateTriangular", &MapFactory::CreateTriangular); 22 | 23 | // CreateSingleEntryMap 24 | m.def(isDevice? "dCreateSingleEntryMap" : "CreateSingleEntryMap", &MapFactory::CreateSingleEntryMap); 25 | } 26 | template void mpart::binding::MapFactoryWrapper(py::module&); 27 | #if defined(MPART_ENABLE_GPU) 28 | template void mpart::binding::MapFactoryWrapper(py::module&); 29 | #endif // MPART_ENABLE_GPU -------------------------------------------------------------------------------- /bindings/python/src/MapObjective.cpp: -------------------------------------------------------------------------------- 1 | #include "CommonPybindUtilities.h" 2 | #include "MParT/Distributions/GaussianSamplerDensity.h" 3 | #include "MParT/MapObjective.h" 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace py = pybind11; 11 | using namespace py::literals; 12 | using namespace mpart; 13 | using namespace mpart::binding; 14 | 15 | template 16 | void mpart::binding::MapObjectiveWrapper(py::module &m) { 17 | std::string t1Name= "MapObjective"; 18 | std::string t2Name = "KLObjective"; 19 | std::string mName = "CreateGaussianKLObjective"; 20 | if(!std::is_same::value) { 21 | t1Name = "d" + t1Name; 22 | t2Name = "d" + t2Name; 23 | mName = "d" + mName; 24 | } 25 | 26 | py::class_, std::shared_ptr>>(m, t1Name.c_str()) 27 | .def("TestError", &KLObjective::TestError) 28 | .def("TrainError", &KLObjective::TrainError) 29 | ; 30 | 31 | py::class_, MapObjective, std::shared_ptr>>(m, t2Name.c_str()); 32 | m.def(mName.c_str(), [](Eigen::Ref &train, unsigned int dim){ 33 | StridedMatrix trainView = MatToKokkos(train); 34 | Kokkos::View storeTrain ("Training data store", trainView.extent(0), trainView.extent(1)); 35 | Kokkos::deep_copy(storeTrain, trainView); 36 | trainView = storeTrain; 37 | return ObjectiveFactory::CreateGaussianKLObjective(trainView, dim); 38 | }, "train"_a, "dim"_a = 0) 39 | .def(mName.c_str(), [](Eigen::Ref &trainEig, Eigen::Ref &testEig, unsigned int dim){ 40 | StridedMatrix trainView = MatToKokkos(trainEig); 41 | StridedMatrix testView = MatToKokkos(testEig); 42 | Kokkos::View storeTrain ("Training data store", trainView.extent(0), trainView.extent(1)); 43 | Kokkos::View storeTest ("Testing data store", testView.extent(0), testView.extent(1)); 44 | Kokkos::deep_copy(storeTrain, trainView); 45 | Kokkos::deep_copy(storeTest, testView); 46 | trainView = storeTrain; 47 | testView = storeTest; 48 | return ObjectiveFactory::CreateGaussianKLObjective(trainView, testView, dim); 49 | }, "train"_a, "test"_a, "dim"_a = 0) 50 | ; 51 | } 52 | 53 | template void mpart::binding::MapObjectiveWrapper(py::module&); 54 | #if defined(MPART_ENABLE_GPU) 55 | template void mpart::binding::MapObjectiveWrapper(py::module&); 56 | #endif // MPART_ENABLE_GPU 57 | -------------------------------------------------------------------------------- /bindings/python/src/MapOptions.cpp: -------------------------------------------------------------------------------- 1 | #include "CommonPybindUtilities.h" 2 | #include "MParT/MapOptions.h" 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #if defined(MPART_HAS_CEREAL) 10 | #include "MParT/Utilities/Serialization.h" 11 | #include 12 | #endif // MPART_HAS_CEREAL 13 | 14 | namespace py = pybind11; 15 | using namespace mpart::binding; 16 | 17 | void mpart::binding::MapOptionsWrapper(py::module &m) 18 | { 19 | 20 | // BasisTypes 21 | py::enum_(m, "BasisTypes") 22 | .value("ProbabilistHermite",BasisTypes::ProbabilistHermite) 23 | .value("PhysicistHermite",BasisTypes::PhysicistHermite) 24 | .value("HermiteFunctions",BasisTypes::HermiteFunctions); 25 | 26 | // PosFuncTypes 27 | py::enum_(m, "PosFuncTypes") 28 | .value("Exp",PosFuncTypes::Exp) 29 | .value("SoftPlus",PosFuncTypes::SoftPlus); 30 | 31 | // QuadTypes 32 | py::enum_(m, "QuadTypes") 33 | .value("ClenshawCurtis",QuadTypes::ClenshawCurtis) 34 | .value("AdaptiveSimpson",QuadTypes::AdaptiveSimpson) 35 | .value("AdaptiveClenshawCurtis",QuadTypes::AdaptiveClenshawCurtis); 36 | 37 | // MapOptions 38 | py::class_>(m, "MapOptions") 39 | .def(py::init<>()) 40 | .def("__eq__", &MapOptions::operator==) 41 | .def("__str__", &MapOptions::String) 42 | .def("__repr__", [](MapOptions opts){return "";}) 43 | .def_readwrite("basisType", &MapOptions::basisType) 44 | .def_readwrite("basisLB", &MapOptions::basisLB) 45 | .def_readwrite("basisUB", &MapOptions::basisUB) 46 | .def_readwrite("basisNorm", &MapOptions::basisNorm) 47 | .def_readwrite("posFuncType", &MapOptions::posFuncType) 48 | .def_readwrite("quadType", &MapOptions::quadType) 49 | .def_readwrite("quadAbsTol", &MapOptions::quadAbsTol) 50 | .def_readwrite("quadRelTol", &MapOptions::quadRelTol) 51 | .def_readwrite("quadMaxSub", &MapOptions::quadMaxSub) 52 | .def_readwrite("quadMinSub", &MapOptions::quadMinSub) 53 | .def_readwrite("quadPts", &MapOptions::quadPts) 54 | .def_readwrite("contDeriv", &MapOptions::contDeriv) 55 | .def_readwrite("nugget", &MapOptions::nugget) 56 | #if defined(MPART_HAS_CEREAL) 57 | .def("Serialize", [](MapOptions const &opts, std::string const &filename){ 58 | std::ofstream os (filename); 59 | cereal::BinaryOutputArchive oarchive(os); 60 | oarchive(opts); 61 | }) 62 | .def("Deserialize", [](MapOptions &opts, std::string const &filename){ 63 | std::ifstream is(filename); 64 | cereal::BinaryInputArchive iarchive(is); 65 | iarchive(opts); 66 | return opts; 67 | }) 68 | #endif // MPART_HAS_CEREAL 69 | ; 70 | 71 | } -------------------------------------------------------------------------------- /bindings/python/src/Serialization.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "CommonPybindUtilities.h" 8 | #include "MParT/MultiIndices/FixedMultiIndexSet.h" 9 | #include "MParT/ParameterizedFunctionBase.h" 10 | #include "MParT/Utilities/Serialization.h" 11 | #include "MParT/Utilities/ArrayConversions.h" 12 | #include "MParT/MapOptions.h" 13 | 14 | 15 | namespace py = pybind11; 16 | using namespace mpart; 17 | using namespace mpart::binding; 18 | 19 | template<> 20 | void mpart::binding::DeserializeWrapper(py::module &m) 21 | { 22 | m.def("DeserializeMap", 23 | [](std::string const &filename) { 24 | std::ifstream is(filename); 25 | cereal::BinaryInputArchive archive(is); 26 | unsigned int inputDim, outputDim, numCoeffs; 27 | archive(inputDim, outputDim, numCoeffs); 28 | Kokkos::View coeffs ("Map coeffs", numCoeffs); 29 | load(archive, coeffs); 30 | return std::make_tuple(inputDim, outputDim, CopyKokkosToVec(coeffs)); 31 | }); 32 | } -------------------------------------------------------------------------------- /bindings/python/src/SummarizedMap.cpp: -------------------------------------------------------------------------------- 1 | #include "CommonPybindUtilities.h" 2 | #include "MParT/SummarizedMap.h" 3 | #include "MParT/ConditionalMapBase.h" 4 | #include "MParT/ParameterizedFunctionBase.h" 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace py = pybind11; 12 | using namespace mpart::binding; 13 | 14 | template 15 | void mpart::binding::SummarizedMapWrapper(py::module &m) 16 | { 17 | std::string tName = "SummarizedMap"; 18 | if(!std::is_same::value) tName = "d" + tName; 19 | 20 | // SummarizedMap 21 | py::class_, ConditionalMapBase, std::shared_ptr>>(m, tName.c_str()) 22 | .def(py::init>, std::shared_ptr>>()) 23 | ; 24 | 25 | } 26 | 27 | template void mpart::binding::SummarizedMapWrapper(py::module&); 28 | #if defined(MPART_ENABLE_GPU) 29 | template void mpart::binding::SummarizedMapWrapper(py::module&); 30 | #endif // MPART_ENABLE_GPU -------------------------------------------------------------------------------- /bindings/python/src/TrainMap.cpp: -------------------------------------------------------------------------------- 1 | #include "CommonPybindUtilities.h" 2 | #include "MParT/TrainMap.h" 3 | #include "MParT/MapObjective.h" 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace py = pybind11; 11 | using namespace mpart::binding; 12 | 13 | void mpart::binding::TrainOptionsWrapper(py::module &m) 14 | { 15 | // TrainOptions 16 | py::class_>(m, "TrainOptions") 17 | .def(py::init<>()) 18 | .def("__str__", &TrainOptions::String) 19 | .def("__repr__", [](TrainOptions opts){return "";}) 20 | .def_readwrite("opt_alg", &TrainOptions::opt_alg) 21 | .def_readwrite("opt_stopval", &TrainOptions::opt_stopval) 22 | .def_readwrite("opt_ftol_rel", &TrainOptions::opt_ftol_rel) 23 | .def_readwrite("opt_ftol_abs", &TrainOptions::opt_ftol_abs) 24 | .def_readwrite("opt_xtol_rel", &TrainOptions::opt_xtol_rel) 25 | .def_readwrite("opt_xtol_abs", &TrainOptions::opt_xtol_abs) 26 | .def_readwrite("opt_maxeval", &TrainOptions::opt_maxeval) 27 | .def_readwrite("opt_maxtime", &TrainOptions::opt_maxtime) 28 | .def_readwrite("verbose", &TrainOptions::verbose) 29 | ; 30 | } 31 | 32 | template 33 | void mpart::binding::TrainMapWrapper(py::module &m) { 34 | 35 | std::string tName = "TrainMap"; 36 | if(!std::is_same::value) tName = "d" + tName; 37 | 38 | m.def(tName.c_str(), &TrainMap) 39 | ; 40 | } 41 | 42 | template void mpart::binding::TrainMapWrapper(py::module&); 43 | #if defined(MPART_ENABLE_GPU) 44 | template void mpart::binding::TrainMapWrapper(py::module&); 45 | #endif // MPART_ENABLE_GPU -------------------------------------------------------------------------------- /bindings/python/src/TrainMapAdaptive.cpp: -------------------------------------------------------------------------------- 1 | #include "CommonPybindUtilities.h" 2 | #include "MParT/MapOptions.h" 3 | #include "MParT/MapObjective.h" 4 | #include "MParT/TrainMap.h" 5 | #include "MParT/TrainMapAdaptive.h" 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | namespace py = pybind11; 13 | using namespace mpart::binding; 14 | using namespace mpart; 15 | 16 | void mpart::binding::ATMOptionsWrapper(py::module &m) 17 | { 18 | // ATMOptions 19 | py::class_>(m, "ATMOptions") 20 | .def(py::init<>()) 21 | .def("__str__", &ATMOptions::String) 22 | .def("__repr__", [](ATMOptions opts){return "";}) 23 | .def_readwrite("maxPatience", &ATMOptions::maxPatience) 24 | .def_readwrite("maxSize", &ATMOptions::maxSize) 25 | .def_readwrite("maxDegrees", &ATMOptions::maxDegrees) 26 | ; 27 | 28 | } 29 | 30 | template 31 | std::shared_ptr> TrainMapAdaptiveSmartPointerPython(std::vector> &mset0, 32 | std::shared_ptr> objective, 33 | ATMOptions options) 34 | { 35 | // Create a version of the mset vector with objects not pointers 36 | std::vector newmset; 37 | for(auto& ptr: mset0) 38 | newmset.push_back(*ptr); 39 | 40 | // Call AdaptiveTrainMap 41 | std::shared_ptr> map = TrainMapAdaptive(newmset, objective, options); 42 | 43 | // Now update the pointers 44 | for(int i=0; i 51 | void mpart::binding::TrainMapAdaptiveWrapper(py::module &m) { 52 | 53 | std::string tName = "TrainMapAdaptive"; 54 | if(!std::is_same::value) tName = "d" + tName; 55 | 56 | m.def(tName.c_str(), &TrainMapAdaptiveSmartPointerPython); 57 | } 58 | 59 | template void mpart::binding::TrainMapAdaptiveWrapper(py::module&); 60 | #if defined(MPART_ENABLE_GPU) 61 | template void mpart::binding::TrainMapAdaptiveWrapper(py::module&); 62 | #endif // MPART_ENABLE_GPU -------------------------------------------------------------------------------- /bindings/python/src/TriangularMap.cpp: -------------------------------------------------------------------------------- 1 | #include "CommonPybindUtilities.h" 2 | #include "MParT/TriangularMap.h" 3 | #include "MParT/ConditionalMapBase.h" 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace py = pybind11; 11 | using namespace mpart::binding; 12 | 13 | template 14 | void mpart::binding::TriangularMapWrapper(py::module &m) 15 | { 16 | std::string tName = "TriangularMap"; 17 | if(!std::is_same::value) tName = "d" + tName; 18 | 19 | // TriangularMap 20 | py::class_, ConditionalMapBase, ParameterizedFunctionBase, std::shared_ptr>>(m, tName.c_str()) 21 | .def(py::init>>, bool>(), py::arg("comps"), py::arg("moveCoeffs") = false) 22 | .def("GetComponent", &TriangularMap::GetComponent) 23 | .def(py::pickle( 24 | [](std::shared_ptr> const& ptr) { // __getstate__ 25 | std::stringstream ss; 26 | ptr->Save(ss); 27 | return py::bytes(ss.str()); 28 | }, 29 | [](py::bytes input) { 30 | 31 | std::stringstream ss; 32 | ss.str(input); 33 | 34 | auto ptr = std::dynamic_pointer_cast>(ParameterizedFunctionBase::Load(ss)); 35 | return ptr; 36 | } 37 | )) 38 | ; 39 | 40 | } 41 | 42 | template void mpart::binding::TriangularMapWrapper(py::module&); 43 | #if defined(MPART_ENABLE_GPU) 44 | template void mpart::binding::TriangularMapWrapper(py::module&); 45 | #endif // MPART_ENABLE_GPU -------------------------------------------------------------------------------- /bindings/python/src/Wrapper.cpp: -------------------------------------------------------------------------------- 1 | #include "CommonPybindUtilities.h" 2 | #include 3 | 4 | using namespace mpart::binding; 5 | 6 | 7 | PYBIND11_MODULE(pympart, m) { 8 | 9 | CommonUtilitiesWrapper(m); 10 | MultiIndexWrapper(m); 11 | MapOptionsWrapper(m); 12 | 13 | ParameterizedFunctionBaseWrapper(m); 14 | ConditionalMapBaseWrapper(m); 15 | AffineMapWrapperHost(m); 16 | AffineFunctionWrapperHost(m); 17 | TriangularMapWrapper(m); 18 | ComposedMapWrapper(m); 19 | SummarizedMapWrapper(m); 20 | IdentityMapWrapper(m); 21 | // DebugMapWrapper(m); 22 | MapFactoryWrapper(m); 23 | MapObjectiveWrapper(m); 24 | 25 | #if defined(MPART_HAS_NLOPT) 26 | TrainOptionsWrapper(m); 27 | ATMOptionsWrapper(m); 28 | TrainMapWrapper(m); 29 | TrainMapAdaptiveWrapper(m); 30 | #endif // MPART_HAS_NLOPT 31 | 32 | #if defined(MPART_HAS_CEREAL) 33 | DeserializeWrapper(m); 34 | #endif // MPART_HAS_CEREAL 35 | 36 | #if defined(MPART_ENABLE_GPU) 37 | ParameterizedFunctionBaseWrapper(m); 38 | ConditionalMapBaseWrapper(m); 39 | TriangularMapWrapper(m); 40 | MapFactoryWrapper(m); 41 | AffineMapWrapperDevice(m); 42 | AffineFunctionWrapperDevice(m); 43 | IdentityMapWrapper(m); 44 | SerializeWrapper(m); 45 | DeserializeWrapper(m); 46 | #endif 47 | } -------------------------------------------------------------------------------- /bindings/python/tests/test_AffineFunction.py: -------------------------------------------------------------------------------- 1 | # MultiIndex test 2 | 3 | import mpart 4 | import numpy as np 5 | 6 | 7 | def test_ShiftOnlyFunction(): 8 | 9 | 10 | b = np.array([1.,2.]).reshape(2,1) 11 | shift = mpart.AffineFunction(b) 12 | del b # checking that AffineFunction deep-copied b; see issue 275 13 | 14 | b_ = np.array([1.,2.]).reshape(2,1) 15 | numPts = 10 16 | pts = np.random.randn(2, numPts) 17 | evals = shift.Evaluate(pts) 18 | 19 | assert np.allclose(evals, pts + b_, atol=1E-8) 20 | 21 | 22 | 23 | def test_SquareLinearOnlyFunction(): 24 | 25 | 26 | A = np.array([[1.,2.],[-3,1.5]]) 27 | 28 | scale = mpart.AffineFunction(np.asfortranarray(A)) 29 | del A # checking that AffineFunction deep-copied b; see issue 275 30 | 31 | A_ = np.array([[1.,2.],[-3,1.5]]) 32 | 33 | numPts = 10 34 | pts = np.random.randn(2, numPts) 35 | evals = scale.Evaluate(pts) 36 | 37 | assert np.allclose(evals, A_@pts, atol=1E-8) 38 | 39 | 40 | def test_RectLinearOnlyFunction(): 41 | A = np.array([[1.,1.,3],[-3,1.5,-3.4]]) 42 | 43 | scale = mpart.AffineFunction(np.asfortranarray(A)) 44 | del A # checking that AffineFunction deep-copied b; see issue 275 45 | 46 | A_ = np.array([[1.,1.,3],[-3,1.5,-3.4]]) 47 | 48 | numPts = 10 49 | pts = np.random.randn(3, numPts) 50 | evals = scale.Evaluate(pts) 51 | 52 | assert np.allclose(evals, A_@pts, atol=1E-8) 53 | 54 | 55 | def test_FullFunction(): 56 | A = np.array([[1.,2.],[-3,1.5]]) 57 | b = np.array([1.,2.]).reshape(2,1) 58 | affine = mpart.AffineFunction(np.asfortranarray(A),b) 59 | 60 | del A, b # checking that AffineFunction deep-copied A and b; see issue 275 61 | 62 | A_ = np.array([[1.,2.],[-3,1.5]]) 63 | b_ = np.array([1.,2.]).reshape(2,1) 64 | 65 | numPts = 10 66 | pts = np.random.randn(2, numPts) 67 | evals = affine.Evaluate(pts) 68 | 69 | assert np.allclose(evals, A_@pts + b_, atol=1E-8) 70 | 71 | 72 | # recreating bug example from issue 275 73 | def test_Issue275(): 74 | 75 | dim = 100 76 | numPts = 10 77 | # lists to hold matrices and functions 78 | mats_ = [] 79 | funs = [] 80 | for idx in range(2, dim): 81 | 82 | # create summary_matrix 83 | A = np.random.randn(idx, idx) 84 | Q, _ = np.linalg.qr(A) 85 | mat = Q[:2,:].copy() 86 | mat_ = Q[:2,:].copy() 87 | mats_.append(mat_) 88 | 89 | # create summary function 90 | fun = mpart.AffineFunction(np.asfortranarray(mat)) 91 | funs.append(fun) 92 | 93 | for mat_,fun in zip(mats_, funs): 94 | 95 | pts = np.random.randn(mat_.shape[1], numPts) 96 | evals = fun.Evaluate(pts) 97 | 98 | assert np.allclose(evals, mat_@pts, atol=1E-8) 99 | -------------------------------------------------------------------------------- /bindings/python/tests/test_AffineMap.py: -------------------------------------------------------------------------------- 1 | # MultiIndex test 2 | 3 | import mpart 4 | import numpy as np 5 | 6 | 7 | def test_ShiftOnlyMap(): 8 | 9 | 10 | b = np.array([1.,2.]).reshape(2,1) 11 | shift = mpart.AffineMap(b) 12 | del b # checking that AffineMap deep-copied b; see issue 275 13 | 14 | b_ = np.array([1.,2.]).reshape(2,1) 15 | numPts = 10 16 | pts = np.random.randn(2, numPts) 17 | 18 | evals = shift.Evaluate(pts) 19 | assert np.allclose(evals, pts + b_, atol=1E-8) 20 | 21 | pts_ = shift.Inverse(pts,evals) 22 | assert np.allclose(pts_, pts, atol=1E-8) 23 | 24 | logdet = shift.LogDeterminant(pts) 25 | assert np.allclose(logdet, 0, atol=1E-8) 26 | 27 | 28 | 29 | def test_SquareLinearOnlyMap(): 30 | 31 | 32 | A = np.array([[1.,2.],[-3,1.5]]) 33 | 34 | scale = mpart.AffineMap(np.asfortranarray(A)) 35 | del A # checking that AffineMap deep-copied b; see issue 275 36 | 37 | A_ = np.array([[1.,2.],[-3,1.5]]) 38 | 39 | numPts = 10 40 | pts = np.random.randn(2, numPts) 41 | 42 | 43 | evals = scale.Evaluate(pts) 44 | assert np.allclose(evals, A_@pts, atol=1E-8) 45 | 46 | pts_ = scale.Inverse(pts,evals) 47 | assert np.allclose(pts_, pts, atol=1E-8) 48 | 49 | logdet = scale.LogDeterminant(pts) 50 | assert np.allclose(logdet, np.log(np.linalg.det(A_)), atol=1E-8) 51 | 52 | 53 | 54 | def test_FullMap(): 55 | A = np.array([[1.,2.],[-3,1.5]]) 56 | b = np.array([1.,2.]).reshape(2,1) 57 | affine = mpart.AffineMap(np.asfortranarray(A),b) 58 | 59 | del A, b # checking that AffineMap deep-copied A and b; see issue 275 60 | 61 | A_ = np.array([[1.,2.],[-3,1.5]]) 62 | b_ = np.array([1.,2.]).reshape(2,1) 63 | 64 | numPts = 10 65 | pts = np.random.randn(2, numPts) 66 | evals = affine.Evaluate(pts) 67 | assert np.allclose(evals, A_@pts + b_, atol=1E-8) 68 | 69 | pts_ = affine.Inverse(pts,evals) 70 | assert np.allclose(pts_, pts, atol=1E-8) 71 | 72 | logdet = affine.LogDeterminant(pts) 73 | assert np.allclose(logdet, np.log(np.linalg.det(A_)), atol=1E-8) 74 | -------------------------------------------------------------------------------- /bindings/python/tests/test_ComposedMap.py: -------------------------------------------------------------------------------- 1 | # Test methods of ComposedMap object 2 | import mpart 3 | import numpy as np 4 | print("made map") 5 | opts = mpart.MapOptions() 6 | 7 | num_maps = 4 8 | dim = 2 9 | maxOrder = 1 10 | 11 | maps = [] 12 | numCoeffs = 0 13 | for i in range(num_maps): 14 | map = mpart.CreateTriangular(dim,dim,maxOrder,opts) 15 | maps.append(map) 16 | numCoeffs += map.numCoeffs 17 | 18 | 19 | composed_map = mpart.ComposedMap(maps, num_maps) 20 | composed_map.SetCoeffs(np.random.randn(composed_map.numCoeffs)) 21 | 22 | num_samples = 100 23 | x = np.random.randn(dim,num_samples) 24 | 25 | 26 | def test_numCoeffs(): 27 | assert composed_map.numCoeffs == numCoeffs 28 | 29 | def test_CoeffsMap(): 30 | 31 | coeffs = np.random.randn(composed_map.numCoeffs) 32 | composed_map.SetCoeffs(coeffs) 33 | assert np.all(composed_map.CoeffMap() == coeffs) 34 | 35 | 36 | def test_Evaluate(): 37 | assert composed_map.Evaluate(x).shape == (dim, num_samples) 38 | x_ = x.copy() 39 | for map_ in maps: 40 | x_ = map_.Evaluate(x_) 41 | assert np.all(composed_map.Evaluate(x) == x_) 42 | 43 | 44 | 45 | def test_LogDeterminant(): 46 | assert composed_map.LogDeterminant(x).shape == (num_samples,) 47 | 48 | def test_Inverse(): 49 | 50 | y = composed_map.Evaluate(x) 51 | x_ = composed_map.Inverse(np.zeros((1,num_samples)),y) 52 | assert np.allclose(x_, x, atol=1E-3) 53 | -------------------------------------------------------------------------------- /bindings/python/tests/test_ComposedMap_moveCoeffs.py: -------------------------------------------------------------------------------- 1 | # Test methods of ComposedMap object 2 | import mpart 3 | import numpy as np 4 | print("made map") 5 | opts = mpart.MapOptions() 6 | 7 | num_maps = 4 8 | dim = 2 9 | maxOrder = 1 10 | 11 | maps = [] 12 | coeffs_ = [] 13 | numCoeffs = 0 14 | for i in range(num_maps): 15 | map = mpart.CreateTriangular(dim,dim,maxOrder,opts) 16 | coeffs = np.random.randn(map.numCoeffs) 17 | map.SetCoeffs(coeffs) 18 | maps.append(map) 19 | coeffs_.append(coeffs) 20 | numCoeffs += map.numCoeffs 21 | 22 | 23 | moveCoeffs = True 24 | composed_map = mpart.ComposedMap(maps, moveCoeffs, num_maps) 25 | all_coeffs = np.hstack(coeffs_).flatten() 26 | 27 | num_samples = 100 28 | x = np.random.randn(dim, num_samples) 29 | 30 | def test_numCoeffs(): 31 | assert composed_map.numCoeffs == numCoeffs 32 | 33 | def test_CoeffsMap(): 34 | assert np.all(composed_map.CoeffMap() == all_coeffs) 35 | 36 | 37 | def test_Evaluate(): 38 | assert composed_map.Evaluate(x).shape == (dim, num_samples) 39 | x_ = x.copy() 40 | for map_ in maps: 41 | x_ = map_.Evaluate(x_) 42 | assert np.all(composed_map.Evaluate(x) == x_) 43 | 44 | 45 | def test_LogDeterminant(): 46 | assert composed_map.LogDeterminant(x).shape == (num_samples,) 47 | 48 | def test_Inverse(): 49 | 50 | y = composed_map.Evaluate(x) 51 | x_ = composed_map.Inverse(np.zeros((1,num_samples)),y) 52 | assert np.allclose(x_, x, atol=1E-3) 53 | -------------------------------------------------------------------------------- /bindings/python/tests/test_ConditionalMapBase.py: -------------------------------------------------------------------------------- 1 | # Test methods of ConditionalMapBase object 2 | import mpart 3 | import numpy as np 4 | 5 | opts = mpart.MapOptions() 6 | 7 | multis = np.array([[0],[1]]) # linear 8 | mset = mpart.MultiIndexSet(multis).fix(True) 9 | 10 | component = mpart.CreateComponent(mset, opts) 11 | num_samples = 100 12 | x = np.random.randn(1,num_samples) 13 | 14 | 15 | def test_numCoeffs(): 16 | assert component.numCoeffs == 2 17 | 18 | 19 | def test_CoeffsMap(): 20 | component.SetCoeffs(np.zeros(component.numCoeffs)) 21 | assert component.CoeffMap().tolist() == [0,0] 22 | 23 | coeffs = np.random.randn(component.numCoeffs) 24 | component.SetCoeffs(coeffs) 25 | assert np.all(component.CoeffMap() == coeffs) 26 | 27 | 28 | def test_Evaluate(): 29 | assert component.Evaluate(x).shape == (1,num_samples) 30 | 31 | 32 | def test_LogDeterminant(): 33 | assert component.LogDeterminant(x).shape == (num_samples,) 34 | 35 | 36 | def test_Inverse(): 37 | coeffs = np.random.randn(component.numCoeffs) 38 | component.SetCoeffs(coeffs) 39 | y = component.Evaluate(x) 40 | x_ = component.Inverse(np.zeros((1,num_samples)),y) 41 | assert np.allclose(x_, x[-1,:], atol=1E-3) 42 | 43 | -------------------------------------------------------------------------------- /bindings/python/tests/test_IdentityMap.py: -------------------------------------------------------------------------------- 1 | # Test methods of TriangularMap object 2 | import mpart 3 | import numpy as np 4 | 5 | 6 | inputdim = 20 7 | outputdim = 15 8 | num_samples = 100 9 | 10 | x = np.random.randn(inputdim,num_samples) 11 | id_map = mpart.IdentityMap(inputdim,outputdim) 12 | 13 | def test_Evaluate(): 14 | y = id_map.Evaluate(x) 15 | assert y.shape == (outputdim,num_samples) 16 | assert np.all(y == x[inputdim-outputdim:,:]) 17 | 18 | def test_LogDeterminant(): 19 | assert id_map.LogDeterminant(x).shape == (num_samples,) 20 | 21 | def test_Inverse(): 22 | 23 | y = id_map.Evaluate(x) 24 | x_ = id_map.Inverse(np.zeros((1,num_samples)),y) 25 | assert np.allclose(x_, x[inputdim-outputdim:,:], atol=1E-3) 26 | -------------------------------------------------------------------------------- /bindings/python/tests/test_MultiIndex.py: -------------------------------------------------------------------------------- 1 | # MultiIndex test 2 | 3 | import mpart 4 | 5 | def test_init_with_length(): 6 | 7 | length = 4 8 | multi = mpart.MultiIndex(length) 9 | assert len(multi) == length 10 | assert multi.count_nonzero() == 0 11 | assert multi[0] == 0 12 | assert multi.max() == 0 13 | assert multi.sum() == 0 14 | 15 | multi[0] = 4 16 | assert multi[0] == 4 17 | assert multi.max() == 4 18 | assert multi.sum() == 4 19 | 20 | multi[1] = 3 21 | assert multi[1] == 3 22 | assert multi.max() == 4 23 | assert multi.sum() == 4 + 3 24 | 25 | def test_init_with_length_and_val(): 26 | 27 | length = 4 28 | val = 2 29 | multi = mpart.MultiIndex(length,val) 30 | assert len(multi) == length 31 | assert multi.count_nonzero() == length 32 | assert multi[0] == val 33 | assert multi.max() == val 34 | assert multi.sum() == length*val 35 | 36 | 37 | def test_init_with_list(): 38 | 39 | idx = [2, 3, 0, 0, 100] 40 | multi = mpart.MultiIndex(idx) 41 | assert len(multi) == len(idx) 42 | assert multi.count_nonzero() == 3 43 | assert multi[0] == idx[0] 44 | assert multi.max() == 100 45 | assert multi.sum() == 105 46 | assert multi.tolist() == idx 47 | -------------------------------------------------------------------------------- /bindings/python/tests/test_MultiIndexSet.py: -------------------------------------------------------------------------------- 1 | # MultiIndex test 2 | 3 | import mpart 4 | import numpy as np 5 | 6 | multis = np.array([[0, 1], [2, 0]]) 7 | msetFromArray = mpart.MultiIndexSet(multis) 8 | 9 | noneLim = mpart.NoneLim() 10 | msetTensorProduct = mpart.MultiIndexSet.CreateTensorProduct(3,4,noneLim) 11 | msetTotalOrder = mpart.MultiIndexSet.CreateTotalOrder(3,4,noneLim) 12 | 13 | def test_create(): 14 | mset_one = mpart.MultiIndexSet([[2]]) 15 | assert mset_one.Size() == 1 16 | assert len(mset_one) == 1 17 | mset_one = mpart.MultiIndexSet(np.array([[2]])) 18 | assert mset_one.Size() == 1 19 | assert len(mset_one) == 1 20 | 21 | def test_max_degrees(): 22 | 23 | assert np.all(msetFromArray.MaxOrders() == [2,1]) 24 | assert np.all(msetTensorProduct.MaxOrders() == [4,4,4]) 25 | assert np.all(msetTotalOrder.MaxOrders() == [4,4,4]) 26 | 27 | 28 | def test_at(): 29 | 30 | assert np.all(msetFromArray[0].tolist() == [0,1]) 31 | assert np.all(msetFromArray[1].tolist() == [2,0]) 32 | 33 | assert np.all(msetTensorProduct[0].tolist() == [0,0,0]) 34 | assert np.all(msetTensorProduct[1].tolist() == [0,0,1]) 35 | last_idx = msetTensorProduct.Size()-1 36 | assert np.all(msetTensorProduct[last_idx].tolist() == [4,4,4]) 37 | 38 | assert np.all(msetTotalOrder[0].tolist() == [0,0,0]) 39 | assert np.all(msetTotalOrder[1].tolist() == [0,0,1]) 40 | last_idx = msetTotalOrder.Size()-1 41 | assert np.all(msetTotalOrder[last_idx].tolist() == [4,0,0]) 42 | 43 | -------------------------------------------------------------------------------- /bindings/python/tests/test_SummarizedMap.py: -------------------------------------------------------------------------------- 1 | # Test methods of TriangularMap object 2 | import mpart 3 | import numpy as np 4 | 5 | 6 | 7 | noneLim = mpart.NoneLim() 8 | opts = mpart.MapOptions() 9 | maxDegree = 2 10 | dim = 7 11 | lrcRank = 2 12 | summary_mat = np.random.randn(lrcRank, dim-1) 13 | 14 | summary_fun = mpart.AffineFunction(np.asfortranarray(summary_mat)) 15 | mset_csemap = mpart.MultiIndexSet.CreateTotalOrder(lrcRank+1, maxDegree, noneLim) 16 | 17 | component = mpart.CreateComponent(mset_csemap.fix(True), opts) 18 | summarized_component = mpart.SummarizedMap(summary_fun, component) 19 | 20 | num_samples = 100 21 | pts = np.random.randn(dim, num_samples) 22 | 23 | coeffs = np.random.randn(summarized_component.numCoeffs) 24 | summarized_component.SetCoeffs(coeffs) 25 | 26 | def test_numCoeffs(): 27 | assert summarized_component.numCoeffs == component.numCoeffs 28 | 29 | 30 | def test_CoeffsMap(): 31 | 32 | coeffs = np.random.randn(summarized_component.numCoeffs) 33 | summarized_component.SetCoeffs(coeffs) 34 | assert np.all(summarized_component.CoeffMap() == coeffs) 35 | 36 | 37 | def test_Evaluate(): 38 | 39 | eval = summarized_component.Evaluate(pts) 40 | summary = summary_fun.Evaluate(pts[:dim-1,:]) 41 | new_pts = np.vstack([summary,pts[dim-1,:]]) 42 | eval_ = component.Evaluate(new_pts) 43 | 44 | assert eval.shape == (1,num_samples) 45 | assert np.allclose(eval_, eval, atol=1E-6) 46 | 47 | 48 | def test_LogDeterminant(): 49 | 50 | logdet = summarized_component.LogDeterminant(pts) 51 | summary = summary_fun.Evaluate(pts[:dim-1,:]) 52 | new_pts = np.vstack([summary,pts[dim-1,:]]) 53 | logdet_ = component.LogDeterminant(new_pts) 54 | 55 | assert logdet.shape == (num_samples,) 56 | assert np.allclose(logdet_, logdet, atol=1E-6) 57 | 58 | 59 | def test_Inverse(): 60 | 61 | y = summarized_component.Evaluate(pts) 62 | pts_ = summarized_component.Inverse(pts[:dim-1,:], y) 63 | assert np.allclose(pts_, pts[-1,:], atol=1E-3) 64 | -------------------------------------------------------------------------------- /bindings/python/tests/test_TrainMap.py: -------------------------------------------------------------------------------- 1 | # Test methods of TriangularMap object 2 | import mpart 3 | import numpy as np 4 | import math 5 | 6 | def KS_statistic(map, test_samples): 7 | pullback_samples = map.Evaluate(test_samples) 8 | print(pullback_samples.shape) 9 | sorted_samps = np.sort(pullback_samples.flatten()) 10 | erf = np.vectorize(math.erf) 11 | samps_cdf = (1 + erf(sorted_samps/np.sqrt(2)))/2 12 | samps_ecdf = (np.arange(pullback_samples.size) + 1)/pullback_samples.size 13 | KS_stat = np.abs(samps_cdf - samps_ecdf).max() 14 | return KS_stat 15 | 16 | # Create samples from banana 17 | dim=2 18 | seed = 43 19 | numPts = 20000 20 | testPts = numPts//5 21 | np.random.seed(seed) 22 | samples = np.random.randn(dim,numPts) 23 | target_samples = np.vstack([samples[0,:], samples[1,:] + samples[0,:]**2]) 24 | 25 | # Separate into testing and training samples 26 | test_samples = target_samples[:,:testPts] 27 | train_samples = target_samples[:,testPts:] 28 | 29 | # Create training objective 30 | obj2 = mpart.CreateGaussianKLObjective(np.asfortranarray(train_samples),np.asfortranarray(test_samples)) 31 | obj1 = mpart.CreateGaussianKLObjective(np.asfortranarray(train_samples),np.asfortranarray(test_samples),1) 32 | 33 | # Create untrained maps 34 | map_options = mpart.MapOptions() 35 | map2 = mpart.CreateTriangular(dim,dim,2,map_options) # Triangular map 36 | map1 = mpart.CreateComponent(mpart.FixedMultiIndexSet(2,2),map_options) # Singular Component 37 | 38 | # Train map 39 | train_options = mpart.TrainOptions() 40 | mpart.TrainMap(map2, obj2, train_options) 41 | mpart.TrainMap(map1, obj1, train_options) 42 | 43 | def test_TestError(): 44 | assert obj1.TestError(map1) < 5. 45 | assert obj2.TestError(map2) < 5. 46 | 47 | def test_Normality(): 48 | print("Testing map1...") 49 | KS_stat1 = KS_statistic(map1, test_samples) 50 | print("Testing map2...") 51 | KS_stat2 = KS_statistic(map2, test_samples) 52 | assert KS_stat1 < 0.1 53 | assert KS_stat2 < 0.1 -------------------------------------------------------------------------------- /bindings/python/tests/test_TrainMapAdaptive.py: -------------------------------------------------------------------------------- 1 | # Test methods of TriangularMap object 2 | import mpart 3 | import numpy as np 4 | import math 5 | 6 | def KS_statistic(map, test_samples): 7 | pullback_samples = map.Evaluate(test_samples) 8 | print(pullback_samples.shape) 9 | sorted_samps = np.sort(pullback_samples.flatten()) 10 | erf = np.vectorize(math.erf) 11 | samps_cdf = (1 + erf(sorted_samps/np.sqrt(2)))/2 12 | samps_ecdf = (np.arange(pullback_samples.size) + 1)/pullback_samples.size 13 | KS_stat = np.abs(samps_cdf - samps_ecdf).max() 14 | return KS_stat 15 | 16 | # Create samples from banana 17 | dim=2 18 | seed = 43 19 | numPts = 5000 20 | testPts = numPts//5 21 | np.random.seed(seed) 22 | samples = np.random.randn(dim,numPts) 23 | target_samples = np.vstack([samples[0,:], samples[1,:] + samples[0,:]**2]) 24 | 25 | # Separate into testing and training samples 26 | test_samples = target_samples[:,:testPts] 27 | train_samples = target_samples[:,testPts:] 28 | 29 | # Create training objective 30 | obj = mpart.CreateGaussianKLObjective(np.asfortranarray(train_samples),np.asfortranarray(test_samples)) 31 | 32 | # Use ATM to build a map 33 | opts = mpart.ATMOptions() 34 | msets = [mpart.MultiIndexSet.CreateTotalOrder(d+1,1) for d in range(2)] 35 | map = mpart.TrainMapAdaptive(msets, obj, opts) 36 | 37 | def test_Msets(): 38 | # Make sure the multiindex set has changed 39 | assert msets[1].Size()>3 40 | 41 | def test_TestError(): 42 | assert obj.TestError(map) < 5. 43 | 44 | def test_Normality(): 45 | print("Testing map1...") 46 | KS_stat = KS_statistic(map, test_samples) 47 | assert KS_stat < 0.1 -------------------------------------------------------------------------------- /bindings/python/tests/test_TriangularMap.py: -------------------------------------------------------------------------------- 1 | # Test methods of TriangularMap object 2 | import mpart 3 | import numpy as np 4 | 5 | opts = mpart.MapOptions() 6 | 7 | multis_1 = np.array([[0],[1]]) # linear 8 | multis_2 = np.array([[0,0],[0,1],[2,0]]) # quadratic in x_1, linear in x_2, matches form of target 9 | 10 | mset_1 = mpart.MultiIndexSet(multis_1).fix(True) 11 | mset_2 = mpart.MultiIndexSet(multis_2).fix(True) 12 | 13 | map_1 = mpart.CreateComponent(mset_1, opts) 14 | map_2 = mpart.CreateComponent(mset_2, opts) 15 | 16 | triangular = mpart.TriangularMap([map_1,map_2]) 17 | num_samples = 100 18 | x = np.random.randn(2,num_samples) 19 | coeffs = np.random.randn(triangular.numCoeffs) 20 | triangular.SetCoeffs(coeffs) 21 | 22 | 23 | def test_numCoeffs(): 24 | assert triangular.numCoeffs == 2 + 3 25 | 26 | 27 | def test_CoeffsMap(): 28 | 29 | assert np.all(triangular.CoeffMap() == coeffs) 30 | 31 | 32 | def test_Evaluate(): 33 | assert triangular.Evaluate(x).shape == (2,num_samples) 34 | 35 | 36 | def test_LogDeterminant(): 37 | assert triangular.LogDeterminant(x).shape == (num_samples,) 38 | 39 | def test_Inverse(): 40 | 41 | y = triangular.Evaluate(x) 42 | x_ = triangular.Inverse(np.zeros((1,num_samples)),y) 43 | assert np.allclose(x_, x, atol=1E-3) 44 | -------------------------------------------------------------------------------- /bindings/python/tests/test_TriangularMap_moveCoeffs.py: -------------------------------------------------------------------------------- 1 | # Test methods of TriangularMap object 2 | import mpart 3 | import numpy as np 4 | 5 | opts = mpart.MapOptions() 6 | 7 | multis_1 = np.array([[0],[1]]) # linear 8 | multis_2 = np.array([[0,0],[0,1],[2,0]]) # quadratic in x_1, linear in x_2, matches form of target 9 | 10 | mset_1 = mpart.MultiIndexSet(multis_1).fix(True) 11 | mset_2 = mpart.MultiIndexSet(multis_2).fix(True) 12 | 13 | map_1 = mpart.CreateComponent(mset_1, opts) 14 | coeffs_1 = np.random.randn(map_1.numCoeffs) 15 | map_1.SetCoeffs(coeffs_1) 16 | 17 | map_2 = mpart.CreateComponent(mset_2, opts) 18 | coeffs_2 = np.random.randn(map_2.numCoeffs) 19 | map_2.SetCoeffs(coeffs_2) 20 | 21 | triangular = mpart.TriangularMap([map_1,map_2], moveCoeffs=True) 22 | num_samples = 100 23 | x = np.random.randn(2,num_samples) 24 | 25 | 26 | def test_numCoeffs(): 27 | assert triangular.numCoeffs == 2 + 3 28 | 29 | 30 | def test_Evaluate(): 31 | assert triangular.Evaluate(x).shape == (2,num_samples) 32 | 33 | 34 | def test_LogDeterminant(): 35 | assert triangular.LogDeterminant(x).shape == (num_samples,) 36 | 37 | def test_Inverse(): 38 | # coeffs = np.random.randn(triangular.numCoeffs) 39 | # triangular.SetCoeffs(coeffs) 40 | y = triangular.Evaluate(x) 41 | x_ = triangular.Inverse(np.zeros((1,num_samples)),y) 42 | assert np.allclose(x_, x, atol=1E-3) 43 | -------------------------------------------------------------------------------- /cmake/FindSphinx.cmake: -------------------------------------------------------------------------------- 1 | #Look for an executable called sphinx-build 2 | find_program(SPHINX_EXECUTABLE 3 | NAMES sphinx-build 4 | DOC "Path to sphinx-build executable") 5 | 6 | include(FindPackageHandleStandardArgs) 7 | 8 | #Handle standard arguments to find_package like REQUIRED and QUIET 9 | find_package_handle_standard_args(Sphinx 10 | "Failed to find sphinx-build executable" 11 | SPHINX_EXECUTABLE) 12 | -------------------------------------------------------------------------------- /cmake/SetInstallPaths.cmake: -------------------------------------------------------------------------------- 1 | 2 | 3 | if(PYTHON_INSTALL_PREFIX) 4 | message(STATUS "PYTHON_INSTALL_PREFIX was set by user to be ${PYTHON_INSTALL_PREFIX}.") 5 | else() 6 | if(NOT PYTHON_INSTALL_SUFFIX) 7 | message(STATUS "PYTHON_INSTALL_SUFFIX not specified. Setting to \"python/mpart\".") 8 | set(PYTHON_INSTALL_SUFFIX python/mpart) 9 | endif() 10 | 11 | message(STATUS "PYTHON_INSTALL_PREFIX was not set by user, defaulting to ${CMAKE_INSTALL_PREFIX}/${PYTHON_INSTALL_SUFFIX}") 12 | set(PYTHON_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}/${PYTHON_INSTALL_SUFFIX}) 13 | endif() 14 | 15 | message(STATUS "Python packages will be installed to ${PYTHON_INSTALL_PREFIX}") 16 | 17 | if(JULIA_INSTALL_PREFIX) 18 | message(STATUS "JULIA_INSTALL_PREFIX was set by user to be ${JULIA_INSTALL_PREFIX}") 19 | else() 20 | message(STATUS "JULIA_INSTALL_PREFIX was not set by user, defaulting to ${CMAKE_INSTALL_PREFIX}/julia.") 21 | set(JULIA_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}/julia) 22 | endif() 23 | 24 | 25 | # if(SKBUILD) 26 | # set(CMAKE_INSTALL_RPATH "\$ORIGIN/../lib:\$ORIGIN/../..") 27 | # endif() -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/_static/pics/Density.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeasureTransport/MParT/1ae526b6c53a3a70d9ee9e9bd636afd4e3fca584/docs/_static/pics/Density.png -------------------------------------------------------------------------------- /docs/_static/pics/Regression.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeasureTransport/MParT/1ae526b6c53a3a70d9ee9e9bd636afd4e3fca584/docs/_static/pics/Regression.png -------------------------------------------------------------------------------- /docs/_static/pics/Samples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeasureTransport/MParT/1ae526b6c53a3a70d9ee9e9bd636afd4e3fca584/docs/_static/pics/Samples.png -------------------------------------------------------------------------------- /docs/_static/pics/Transformation2d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeasureTransport/MParT/1ae526b6c53a3a70d9ee9e9bd636afd4e3fca584/docs/_static/pics/Transformation2d.png -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.https://www.sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/source/api/composedmap.rst: -------------------------------------------------------------------------------- 1 | ============================== 2 | Composed Map 3 | ============================== 4 | 5 | .. doxygenclass:: mpart::ComposedMap 6 | :members: 7 | :undoc-members: -------------------------------------------------------------------------------- /docs/source/api/concepts/parameterizedfunction.rst: -------------------------------------------------------------------------------- 1 | ================================ 2 | Parameterized Function Concept 3 | ================================ 4 | 5 | 6 | 7 | Examples of templated classes satisfying this concept include 8 | 9 | .. toctree:: 10 | :caption: Parameterized Functions 11 | :maxdepth: 1 12 | 13 | ../monotonecomponent -------------------------------------------------------------------------------- /docs/source/api/conditionalmapbase.rst: -------------------------------------------------------------------------------- 1 | ============================== 2 | Conditional Map Base 3 | ============================== 4 | 5 | .. doxygenclass:: mpart::ConditionalMapBase 6 | :members: 7 | :undoc-members: -------------------------------------------------------------------------------- /docs/source/api/index.rst: -------------------------------------------------------------------------------- 1 | .. _api: 2 | 3 | API Reference 4 | ============== 5 | 6 | .. toctree:: 7 | :caption: API 8 | :maxdepth: 2 9 | 10 | mapfactory 11 | conditionalmapbase 12 | triangularmap 13 | composedmap 14 | monotonecomponent 15 | multiindex 16 | quadrature 17 | utilities/linearalgebra 18 | utilities/kokkoswrappers 19 | multivariateexpansionworker 20 | templateconcepts 21 | utilities/initialization 22 | utilities/serialization 23 | maptraining 24 | -------------------------------------------------------------------------------- /docs/source/api/mapfactory.rst: -------------------------------------------------------------------------------- 1 | ============================== 2 | Map Factory 3 | ============================== 4 | 5 | .. doxygennamespace:: mpart::MapFactory 6 | 7 | .. doxygenfunction:: mpart::MapFactory::CreateComponent 8 | 9 | .. doxygenfunction:: mpart::MapFactory::CreateTriangular 10 | 11 | .. doxygenstruct:: mpart::MapOptions 12 | :members: 13 | :undoc-members: 14 | 15 | .. doxygenenum:: mpart::BasisTypes 16 | 17 | .. doxygenenum:: mpart::PosFuncTypes 18 | 19 | .. doxygenenum:: mpart::QuadTypes 20 | -------------------------------------------------------------------------------- /docs/source/api/maptraining.rst: -------------------------------------------------------------------------------- 1 | =================== 2 | Map Training 3 | =================== 4 | 5 | Functions and Classes 6 | ------------------- 7 | 8 | .. toctree:: 9 | 10 | maptraining/trainmap 11 | maptraining/trainmapadaptive 12 | -------------------------------------------------------------------------------- /docs/source/api/maptraining/trainmap.rst: -------------------------------------------------------------------------------- 1 | ============================== 2 | Train Map 3 | ============================== 4 | 5 | .. doxygenfunction:: mpart::TrainMap 6 | 7 | .. doxygenstruct:: mpart::TrainOptions 8 | :members: 9 | :undoc-members: 10 | -------------------------------------------------------------------------------- /docs/source/api/maptraining/trainmapadaptive.rst: -------------------------------------------------------------------------------- 1 | ============================== 2 | Adaptive Map Training 3 | ============================== 4 | 5 | .. doxygenfunction:: mpart::TrainMapAdaptive 6 | 7 | .. doxygenstruct:: mpart::ATMOptions 8 | :members: 9 | :undoc-members: 10 | -------------------------------------------------------------------------------- /docs/source/api/monotonecomponent.rst: -------------------------------------------------------------------------------- 1 | ============================== 2 | Monotone Component 3 | ============================== 4 | 5 | .. doxygenclass:: mpart::MonotoneComponent 6 | :members: 7 | :undoc-members: 8 | -------------------------------------------------------------------------------- /docs/source/api/multiindices/fixedmultiindexset.rst: -------------------------------------------------------------------------------- 1 | =================== 2 | FixedMultiIndexSet 3 | =================== 4 | 5 | .. doxygenclass:: mpart::FixedMultiIndexSet 6 | :members: 7 | :undoc-members: -------------------------------------------------------------------------------- /docs/source/api/multiindices/multiindex.rst: -------------------------------------------------------------------------------- 1 | =================== 2 | MultiIndex 3 | =================== 4 | 5 | .. doxygenclass:: mpart::MultiIndex 6 | :members: 7 | :undoc-members: -------------------------------------------------------------------------------- /docs/source/api/multiindices/multiindexlimiter.rst: -------------------------------------------------------------------------------- 1 | =================== 2 | MultiIndexLimiter 3 | =================== 4 | 5 | .. doxygennamespace:: mpart::MultiIndexLimiter -------------------------------------------------------------------------------- /docs/source/api/multiindices/multiindexneighborhood.rst: -------------------------------------------------------------------------------- 1 | ======================= 2 | MultiIndexNeighborhood 3 | ======================= 4 | 5 | .. doxygenclass:: mpart::MultiIndexNeighborhood 6 | :members: 7 | :undoc-members: 8 | 9 | .. doxygenclass:: mpart::DefaultNeighborhood 10 | :members: 11 | :undoc-members: -------------------------------------------------------------------------------- /docs/source/api/multiindices/multiindexset.rst: -------------------------------------------------------------------------------- 1 | =================== 2 | MultiIndexSet 3 | =================== 4 | 5 | .. doxygenclass:: mpart::MultiIndexSet 6 | :members: 7 | :undoc-members: -------------------------------------------------------------------------------- /docs/source/api/multivariateexpansion.rst: -------------------------------------------------------------------------------- 1 | ============================== 2 | Multivariate Expansion 3 | ============================== 4 | 5 | .. doxygenclass:: mpart::MultivariateExpansion 6 | :members: 7 | :undoc-members: 8 | -------------------------------------------------------------------------------- /docs/source/api/multivariateexpansionworker.rst: -------------------------------------------------------------------------------- 1 | ============================== 2 | Multivariate Expansion Worker 3 | ============================== 4 | 5 | .. doxygenclass:: mpart::MultivariateExpansionWorker 6 | :members: 7 | :undoc-members: 8 | -------------------------------------------------------------------------------- /docs/source/api/parameterizedfunctionbase.rst: -------------------------------------------------------------------------------- 1 | ============================== 2 | Parameterized Function Base 3 | ============================== 4 | 5 | .. doxygenclass:: mpart::ParameterizedFunctionBase 6 | :members: 7 | :undoc-members: 8 | -------------------------------------------------------------------------------- /docs/source/api/quadrature.rst: -------------------------------------------------------------------------------- 1 | =================== 2 | Quadrature 3 | =================== 4 | 5 | C++ Objects 6 | ------------------- 7 | 8 | .. toctree:: 9 | 10 | quadrature/clenshawcurtis 11 | quadrature/adaptivesimpson 12 | quadrature/recursivequadrature 13 | -------------------------------------------------------------------------------- /docs/source/api/quadrature/adaptivesimpson.rst: -------------------------------------------------------------------------------- 1 | ============================= 2 | Adaptive Simpson Integration 3 | ============================= 4 | 5 | .. doxygenclass:: mpart::AdaptiveSimpson 6 | :members: 7 | :undoc-members: -------------------------------------------------------------------------------- /docs/source/api/quadrature/clenshawcurtis.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | Clenshaw Curtis Quadrature 3 | =========================== 4 | 5 | .. doxygenclass:: mpart::ClenshawCurtisQuadrature 6 | :members: 7 | :undoc-members: -------------------------------------------------------------------------------- /docs/source/api/quadrature/recursivequadrature.rst: -------------------------------------------------------------------------------- 1 | ==================================== 2 | Adaptive Clenshaw Curtis Quadrature 3 | ==================================== 4 | 5 | .. doxygenclass:: mpart::AdaptiveClenshawCurtis 6 | :members: 7 | :undoc-members: -------------------------------------------------------------------------------- /docs/source/api/templateconcepts.rst: -------------------------------------------------------------------------------- 1 | ================== 2 | Template Concepts 3 | ================== 4 | 5 | Many of the lower-level classes in MParT are templated to allow for generic implementations. Using templates instead of other programming techniques, like virtual inheritance, makes it simpler to copy these classes to/from a GPU and can sometimes even result in more efficient CPU code. For example, the :code:`MonotoneComponent`` class, which uses a generic function :math:`f(x)` to define a monotone function :math:`T_d(x)`, is templated on the type of the :math:`f` function. It is therefore possible to construct a monotone function from any class defining :math:`f(x)`, as long as the class contains the functions (i.e., the interface) expected by :code:`MonotoneComponent`. In the language of generic programming, the necessary interface is a specific `concept `_. 6 | 7 | .. topic:: Concept 8 | 9 | A concept is a set of requirements defining the interface expected by a templated function or class. 10 | 11 | 12 | Specific concepts used throughout MParT can be found on the following pages. 13 | 14 | .. toctree:: 15 | 16 | concepts/cachedparameterization 17 | concepts/parameterizedfunction 18 | -------------------------------------------------------------------------------- /docs/source/api/tensorproductfunction.rst: -------------------------------------------------------------------------------- 1 | ============================== 2 | Tensor Product Function 3 | ============================== 4 | 5 | .. doxygenclass:: mpart::TensorProductFunction 6 | :members: 7 | :undoc-members: 8 | -------------------------------------------------------------------------------- /docs/source/api/triangularmap.rst: -------------------------------------------------------------------------------- 1 | ============================== 2 | Triangular Map 3 | ============================== 4 | 5 | .. doxygenclass:: mpart::TriangularMap 6 | :members: 7 | :undoc-members: -------------------------------------------------------------------------------- /docs/source/api/utilities/initialization.rst: -------------------------------------------------------------------------------- 1 | ============================= 2 | Initialization Helpers 3 | ============================= 4 | 5 | .. doxygengroup:: InitializationHelpers 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/source/api/utilities/kokkoswrappers.rst: -------------------------------------------------------------------------------- 1 | ============================= 2 | Kokkos Array Conversions 3 | ============================= 4 | 5 | .. doxygengroup:: ArrayUtilities 6 | -------------------------------------------------------------------------------- /docs/source/tutorials/index.rst: -------------------------------------------------------------------------------- 1 | .. _tutorials: 2 | 3 | Tutorials 4 | =========== 5 | The :code:`MParT-examples` repository provides several tutorials demonstrating how to use MParT in c++, python, Julia, and Matlab. Below are a gallery of these examples linking to python notebooks. For other languages, please go to the example repository. 6 | 7 | .. card:: 8 | View examples from all languages on Github 9 | 10 | .. button-link:: https://github.com/MeasureTransport/MParT-examples 11 | :color: info 12 | :shadow: 13 | :expand: 14 | 15 | MeasureTransport/MParT-examples 16 | 17 | Gallery (Python) 18 | ----------------- 19 | 20 | .. grid:: 1 2 2 3 21 | :gutter: 3 22 | 23 | .. grid-item-card:: Map from Density 24 | :link: python/FromDensity2D_banana.ipynb 25 | 26 | Construct a transport map from a two dimension probability density function. 27 | 28 | .. grid-item-card:: Map from Samples 29 | :link: python/FromSamples2D_banana.ipynb 30 | 31 | Construct a transport map from two dimensional samples. 32 | 33 | .. grid-item-card:: Monotone Least Squares 34 | :link: python/MonotoneLeastSquares.ipynb 35 | 36 | Use a one dimensional monotone parameterization for regression constrained to the space of strictly increasing functions. 37 | 38 | .. grid-item-card:: Bayesian Inference 39 | :link: python/BayesianInference_BOD.ipynb 40 | 41 | Use a transport map to characterize a Bayesian posterior distribution arising in biochemical oxygen demand. 42 | 43 | .. grid-item-card:: Stochastic Volatility 44 | :link: python/SparseDensityEstimation_SV.ipynb 45 | 46 | Use known conditional independence structure for map-based density estimation in high dimensions. 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /joss/performance_comparison.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeasureTransport/MParT/1ae526b6c53a3a70d9ee9e9bd636afd4e3fca584/joss/performance_comparison.png -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "setuptools", 4 | "scikit-build>=0.13", 5 | "cmake", 6 | "ninja", 7 | ] 8 | build-backend = "setuptools.build_meta" 9 | 10 | [project] 11 | name = "MParT" 12 | authors = [ 13 | {name = "Matthew Parno"}, 14 | ] 15 | license={file="LICENSE.txt"} 16 | readme="README.md" 17 | requires-python = ">=3.7" 18 | description="A Monotone Parameterization Toolkit" 19 | version="2.2.2" 20 | keywords=["Measure Transport", "Monotone", "Transport Map", "Isotonic Regression", "Triangular", "Knothe-Rosenblatt"] 21 | 22 | [project.urls] 23 | Documentation = "https://measuretransport.github.io/MParT/" 24 | Source = "https://github.com/MeasureTransport/MParT" 25 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from skbuild import setup 2 | 3 | import os, sys, site 4 | import warnings 5 | 6 | def get_install_locations(): 7 | """Return the installation directory, or '' if no directory could be found 8 | 9 | Adapted from stack overflow post https://stackoverflow.com/a/36205159 10 | """ 11 | 12 | if '--user' in sys.argv: 13 | paths = (site.getusersitepackages(),) 14 | else: 15 | py_version = f'{sys.version_info[0]}.{sys.version_info[1]}' 16 | paths = [ 17 | sys.prefix + f'/lib/python{py_version}/dist-packages/', 18 | sys.prefix + f'/lib/python{py_version}/site-packages/', 19 | sys.prefix + f'/local/lib/python{py_version}/dist-packages/', 20 | sys.prefix + f'/local/lib/python{py_version}/site-packages/', 21 | f'/Library/Frameworks/Python.framework/Versions/{py_version}/lib/python{py_version}/site-packages/' 22 | ] 23 | 24 | for path in paths: 25 | if os.path.exists(path): 26 | parts = path.split('/') 27 | lib_indices = [index for index, item in enumerate(parts) if item == 'lib'] 28 | return path, '/'.join(parts[0:(lib_indices[-1]+1)]) 29 | 30 | return '' 31 | 32 | site_folder, lib_folder = get_install_locations() 33 | 34 | 35 | setup( 36 | packages=['mpart'], 37 | package_dir={'mpart': 'bindings/python/package'}, 38 | package_data={'mpart':['**/*pympart*']}, 39 | include_package_data=True, 40 | cmake_args=['-DKokkos_ENABLE_THREADS:BOOL=ON', '-DKokkos_ENABLE_THREADS=ON', f'-DSKBUILD_LIB_RPATH={lib_folder}', f'-DSKBUILD_SITE_PATH={site_folder}', '-DPYTHON_INSTALL_SUFFIX=bindings/python/package/', '-DMPART_JULIA:BOOL=OFF', '-DMPART_MATLAB:BOOL=OFF', '-DMPART_BUILD_TESTS:BOOL=OFF', '-DMPART_PYTHON:BOOL=ON', '-DPYTHON_INSTALL_PREFIX='] 41 | ) -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | if (MPART_OPT) 3 | set(MPART_OPT_FILES 4 | MapObjective.cpp 5 | TrainMap.cpp 6 | TrainMapAdaptive.cpp 7 | ) 8 | else() 9 | set(MPART_OPT_FILES "") 10 | endif () 11 | 12 | target_sources(mpart 13 | PRIVATE 14 | MultiIndices/MultiIndex.cpp 15 | MultiIndices/MultiIndexLimiter.cpp 16 | MultiIndices/MultiIndexSet.cpp 17 | MultiIndices/FixedMultiIndexSet.cpp 18 | MultiIndices/MultiIndexNeighborhood.cpp 19 | 20 | Utilities/Miscellaneous.cpp 21 | Utilities/LinearAlgebra.cpp 22 | 23 | Distributions/DensityBase.cpp 24 | Distributions/GaussianSamplerDensity.cpp 25 | Distributions/PullbackDensity.cpp 26 | 27 | ParameterizedFunctionBase.cpp 28 | ConditionalMapBase.cpp 29 | TriangularMap.cpp 30 | IdentityMap.cpp 31 | ComposedMap.cpp 32 | SummarizedMap.cpp 33 | # DebugMap.cpp 34 | AffineMap.cpp 35 | AffineFunction.cpp 36 | MapFactory.cpp 37 | 38 | MapFactoryImpl1.cpp 39 | MapFactoryImpl2.cpp 40 | MapFactoryImpl3.cpp 41 | MapFactoryImpl4.cpp 42 | MapFactoryImpl5.cpp 43 | MapFactoryImpl6.cpp 44 | MapFactoryImpl7.cpp 45 | MapFactoryImpl8.cpp 46 | MapFactoryImpl9.cpp 47 | MapFactoryImpl10.cpp 48 | MapFactoryImpl11.cpp 49 | MapFactoryImpl12.cpp 50 | MapFactoryImpl13.cpp 51 | MapFactoryImpl14.cpp 52 | MapFactoryImpl15.cpp 53 | MapFactoryImpl16.cpp 54 | MapFactoryImpl17.cpp 55 | MapFactoryImpl18.cpp 56 | 57 | ${MPART_OPT_FILES} 58 | Initialization.cpp 59 | ) -------------------------------------------------------------------------------- /src/Distributions/DensityBase.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/Distributions/DensityBase.h" 2 | 3 | using namespace mpart; 4 | 5 | template<> 6 | Eigen::VectorXd DensityBase::LogDensity(Eigen::Ref const &pts) { 7 | // Allocate output 8 | Eigen::VectorXd output(pts.cols()); 9 | StridedMatrix ptsView = ConstRowMatToKokkos(pts); 10 | StridedVector outView = VecToKokkos(output); 11 | // Call the LogDensity function 12 | LogDensityImpl(ptsView, outView); 13 | 14 | return output; 15 | } 16 | 17 | template<> 18 | Eigen::RowMatrixXd DensityBase::LogDensityInputGrad(Eigen::Ref const &pts) { 19 | // Allocate output 20 | Eigen::RowMatrixXd output(pts.rows(), pts.cols()); 21 | StridedMatrix ptsView = ConstRowMatToKokkos(pts); 22 | StridedMatrix outView = MatToKokkos(output); 23 | // Call the LogDensity function 24 | LogDensityInputGradImpl(ptsView, outView); 25 | 26 | return output; 27 | } 28 | 29 | template<> 30 | template<> 31 | StridedVector DensityBase::LogDensity(StridedMatrix const &X) { 32 | // Allocate output 33 | Kokkos::View output("output", X.extent(1)); 34 | // Call the LogDensity function 35 | LogDensityImpl(X, output); 36 | 37 | return output; 38 | } 39 | 40 | template<> 41 | template<> 42 | StridedMatrix DensityBase::LogDensityInputGrad(StridedMatrix const &X) { 43 | // Allocate output 44 | Kokkos::View output("output", X.extent(0), X.extent(1)); 45 | // Call the LogDensity function 46 | LogDensityInputGradImpl(X, output); 47 | 48 | return output; 49 | } -------------------------------------------------------------------------------- /src/Initialization.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/Initialization.h" 2 | 3 | using namespace mpart; 4 | 5 | 6 | void mpart::Finalize() 7 | { 8 | #if defined(MPART_ENABLE_GPU) 9 | cublasDestroy(GetInitializeStatusObject().GetCublasHandle()); 10 | cusolverDnDestroy(GetInitializeStatusObject().GetCusolverHandle()); 11 | #endif 12 | 13 | Kokkos::finalize(); 14 | } 15 | 16 | InitializeStatus& mpart::GetInitializeStatusObject() 17 | { 18 | static InitializeStatus status; 19 | 20 | return status; 21 | } -------------------------------------------------------------------------------- /src/MapFactoryImpl17.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/MapFactory.h" 2 | 3 | #include "MParT/MonotoneComponent.h" 4 | #include "MParT/TriangularMap.h" 5 | #include "MParT/Quadrature.h" 6 | 7 | #include "MParT/HermiteFunction.h" 8 | #include "MParT/MultivariateExpansionWorker.h" 9 | #include "MParT/PositiveBijectors.h" 10 | 11 | #include "MParT/LinearizedBasis.h" 12 | 13 | using namespace mpart; 14 | 15 | template 16 | std::shared_ptr> CreateComponentImpl_LinHF_CC(FixedMultiIndexSet const& mset, MapOptions opts) 17 | { 18 | LinearizedBasis basis1d(HermiteFunction(), opts.basisLB, opts.basisUB); 19 | ClenshawCurtisQuadrature quad(opts.quadPts, 1); 20 | 21 | MultivariateExpansionWorker expansion(mset, basis1d); 22 | std::shared_ptr> output; 23 | 24 | output = std::make_shared>(expansion, quad, opts.contDeriv, opts.nugget); 25 | 26 | output->SetCoeffs(Kokkos::View("Component Coefficients", mset.Size())); 27 | return output; 28 | } 29 | 30 | static auto reg_host_linhf_cc_exp = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::HermiteFunctions, true, PosFuncTypes::Exp, QuadTypes::ClenshawCurtis), CreateComponentImpl_LinHF_CC)); 31 | static auto reg_host_linhf_cc_splus = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::HermiteFunctions, true, PosFuncTypes::SoftPlus, QuadTypes::ClenshawCurtis), CreateComponentImpl_LinHF_CC)); 32 | #if defined(MPART_ENABLE_GPU) 33 | static auto reg_device_linhf_cc_exp = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::HermiteFunctions, true, PosFuncTypes::Exp, QuadTypes::ClenshawCurtis), CreateComponentImpl_LinHF_CC)); 34 | static auto reg_device_linhf_cc_splus = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::HermiteFunctions, true, PosFuncTypes::SoftPlus, QuadTypes::ClenshawCurtis), CreateComponentImpl_LinHF_CC)); 35 | #endif 36 | 37 | #if defined(MPART_HAS_CEREAL) 38 | REGISTER_MONO_COMP(LinearizedBasis, Exp, ClenshawCurtisQuadrature, Kokkos::HostSpace) 39 | REGISTER_MONO_COMP(LinearizedBasis, SoftPlus, ClenshawCurtisQuadrature, Kokkos::HostSpace) 40 | #if defined(MPART_ENABLE_GPU) 41 | REGISTER_MONO_COMP(LinearizedBasis, Exp, ClenshawCurtisQuadrature, mpart::DeviceSpace) 42 | REGISTER_MONO_COMP(LinearizedBasis, Softplus, ClenshawCurtisQuadrature, mpart::DeviceSpace) 43 | #endif 44 | CEREAL_REGISTER_DYNAMIC_INIT(mpartInitMapFactory17) 45 | #endif -------------------------------------------------------------------------------- /src/MapFactoryImpl2.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/MapFactory.h" 2 | 3 | #include "MParT/MonotoneComponent.h" 4 | #include "MParT/TriangularMap.h" 5 | #include "MParT/Quadrature.h" 6 | 7 | #include "MParT/OrthogonalPolynomial.h" 8 | #include "MParT/MultivariateExpansionWorker.h" 9 | #include "MParT/PositiveBijectors.h" 10 | 11 | using namespace mpart; 12 | 13 | 14 | template 15 | std::shared_ptr> CreateComponentImpl_Phys_CC(FixedMultiIndexSet const& mset, MapOptions opts) 16 | { 17 | PhysicistHermite basis1d(opts.basisNorm); 18 | ClenshawCurtisQuadrature quad(opts.quadPts, 1); 19 | 20 | MultivariateExpansionWorker expansion(mset, basis1d); 21 | std::shared_ptr> output; 22 | 23 | output = std::make_shared>(expansion, quad, opts.contDeriv, opts.nugget); 24 | 25 | output->SetCoeffs(Kokkos::View("Component Coefficients", mset.Size())); 26 | return output; 27 | } 28 | 29 | static auto reg_host_phys_cc_exp = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::PhysicistHermite, false, PosFuncTypes::Exp, QuadTypes::ClenshawCurtis), CreateComponentImpl_Phys_CC)); 30 | static auto reg_host_phys_cc_splus = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::PhysicistHermite, false, PosFuncTypes::SoftPlus, QuadTypes::ClenshawCurtis), CreateComponentImpl_Phys_CC)); 31 | #if defined(MPART_ENABLE_GPU) 32 | static auto reg_device_phys_cc_exp = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::PhysicistHermite, false, PosFuncTypes::Exp, QuadTypes::ClenshawCurtis), CreateComponentImpl_Phys_CC)); 33 | static auto reg_device_phys_cc_splus = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::PhysicistHermite, false, PosFuncTypes::SoftPlus, QuadTypes::ClenshawCurtis), CreateComponentImpl_Phys_CC)); 34 | #endif 35 | 36 | #if defined(MPART_HAS_CEREAL) 37 | REGISTER_MONO_COMP(PhysicistHermite, Exp, ClenshawCurtisQuadrature, Kokkos::HostSpace) 38 | REGISTER_MONO_COMP(PhysicistHermite, SoftPlus, ClenshawCurtisQuadrature, Kokkos::HostSpace) 39 | #if defined(MPART_ENABLE_GPU) 40 | REGISTER_MONO_COMP(PhysicistHermite, Exp, ClenshawCurtisQuadrature, mpart::DeviceSpace) 41 | REGISTER_MONO_COMP(PhysicistHermite, Softplus, ClenshawCurtisQuadrature, mpart::DeviceSpace) 42 | #endif 43 | CEREAL_REGISTER_DYNAMIC_INIT(mpartInitMapFactory2) 44 | #endif -------------------------------------------------------------------------------- /src/MapFactoryImpl3.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/MapFactory.h" 2 | 3 | #include "MParT/MonotoneComponent.h" 4 | #include "MParT/TriangularMap.h" 5 | #include "MParT/Quadrature.h" 6 | 7 | #include "MParT/OrthogonalPolynomial.h" 8 | #include "MParT/MultivariateExpansionWorker.h" 9 | #include "MParT/PositiveBijectors.h" 10 | 11 | using namespace mpart; 12 | 13 | template 14 | std::shared_ptr> CreateComponentImpl_Phys_AS(FixedMultiIndexSet const& mset, MapOptions opts) 15 | { 16 | PhysicistHermite basis1d(opts.basisNorm); 17 | AdaptiveSimpson quad(opts.quadMaxSub, 1, nullptr, opts.quadAbsTol, opts.quadRelTol, QuadError::First, opts.quadMinSub); 18 | 19 | MultivariateExpansionWorker expansion(mset, basis1d); 20 | std::shared_ptr> output; 21 | 22 | output = std::make_shared>(expansion, quad, opts.contDeriv, opts.nugget); 23 | 24 | output->SetCoeffs(Kokkos::View("Component Coefficients", mset.Size())); 25 | return output; 26 | } 27 | 28 | static auto reg_host_phys_as_exp = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::PhysicistHermite, false, PosFuncTypes::Exp, QuadTypes::AdaptiveSimpson), CreateComponentImpl_Phys_AS)); 29 | static auto reg_host_phys_as_splus = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::PhysicistHermite, false, PosFuncTypes::SoftPlus, QuadTypes::AdaptiveSimpson), CreateComponentImpl_Phys_AS)); 30 | #if defined(MPART_ENABLE_GPU) 31 | static auto reg_device_phys_as_exp = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::PhysicistHermite, false, PosFuncTypes::Exp, QuadTypes::AdaptiveSimpson), CreateComponentImpl_Phys_AS)); 32 | static auto reg_device_phys_as_splus = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::PhysicistHermite, false, PosFuncTypes::SoftPlus, QuadTypes::AdaptiveSimpson), CreateComponentImpl_Phys_AS)); 33 | #endif 34 | 35 | #if defined(MPART_HAS_CEREAL) 36 | REGISTER_MONO_COMP(PhysicistHermite, Exp, AdaptiveSimpson, Kokkos::HostSpace) 37 | REGISTER_MONO_COMP(PhysicistHermite, SoftPlus, AdaptiveSimpson, Kokkos::HostSpace) 38 | #if defined(MPART_ENABLE_GPU) 39 | REGISTER_MONO_COMP(PhysicistHermite, Exp, AdaptiveSimpson, mpart::DeviceSpace) 40 | REGISTER_MONO_COMP(PhysicistHermite, Softplus, AdaptiveSimpson, mpart::DeviceSpace) 41 | #endif 42 | CEREAL_REGISTER_DYNAMIC_INIT(mpartInitMapFactory3) 43 | #endif -------------------------------------------------------------------------------- /src/MapFactoryImpl5.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/MapFactory.h" 2 | 3 | #include "MParT/MonotoneComponent.h" 4 | #include "MParT/TriangularMap.h" 5 | #include "MParT/Quadrature.h" 6 | 7 | #include "MParT/OrthogonalPolynomial.h" 8 | #include "MParT/MultivariateExpansionWorker.h" 9 | #include "MParT/PositiveBijectors.h" 10 | 11 | using namespace mpart; 12 | 13 | template 14 | std::shared_ptr> CreateComponentImpl_Prob_CC(FixedMultiIndexSet const& mset, MapOptions opts) 15 | { 16 | ProbabilistHermite basis1d(opts.basisNorm); 17 | ClenshawCurtisQuadrature quad(opts.quadPts, 1); 18 | 19 | MultivariateExpansionWorker expansion(mset, basis1d); 20 | std::shared_ptr> output; 21 | 22 | output = std::make_shared>(expansion, quad, opts.contDeriv, opts.nugget); 23 | 24 | output->SetCoeffs(Kokkos::View("Component Coefficients", mset.Size())); 25 | return output; 26 | } 27 | 28 | static auto reg_host_prob_cc_exp = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::ProbabilistHermite, false, PosFuncTypes::Exp, QuadTypes::ClenshawCurtis), CreateComponentImpl_Prob_CC)); 29 | static auto reg_host_prob_cc_splus = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::ProbabilistHermite, false, PosFuncTypes::SoftPlus, QuadTypes::ClenshawCurtis), CreateComponentImpl_Prob_CC)); 30 | #if defined(MPART_ENABLE_GPU) 31 | static auto reg_device_prob_cc_exp = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::ProbabilistHermite, false, PosFuncTypes::Exp, QuadTypes::ClenshawCurtis), CreateComponentImpl_Prob_CC)); 32 | static auto reg_device_prob_cc_splus = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::ProbabilistHermite, false, PosFuncTypes::SoftPlus, QuadTypes::ClenshawCurtis), CreateComponentImpl_Prob_CC)); 33 | #endif 34 | 35 | #if defined(MPART_HAS_CEREAL) 36 | REGISTER_MONO_COMP(ProbabilistHermite, Exp, ClenshawCurtisQuadrature, Kokkos::HostSpace) 37 | REGISTER_MONO_COMP(ProbabilistHermite, SoftPlus, ClenshawCurtisQuadrature, Kokkos::HostSpace) 38 | #if defined(MPART_ENABLE_GPU) 39 | REGISTER_MONO_COMP(ProbabilistHermite, Exp, ClenshawCurtisQuadrature, mpart::DeviceSpace) 40 | REGISTER_MONO_COMP(ProbabilistHermite, Softplus, ClenshawCurtisQuadrature, mpart::DeviceSpace) 41 | #endif 42 | CEREAL_REGISTER_DYNAMIC_INIT(mpartInitMapFactory5) 43 | #endif -------------------------------------------------------------------------------- /src/MapFactoryImpl6.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/MapFactory.h" 2 | 3 | #include "MParT/MonotoneComponent.h" 4 | #include "MParT/TriangularMap.h" 5 | #include "MParT/Quadrature.h" 6 | 7 | #include "MParT/OrthogonalPolynomial.h" 8 | #include "MParT/MultivariateExpansionWorker.h" 9 | #include "MParT/PositiveBijectors.h" 10 | 11 | using namespace mpart; 12 | 13 | template 14 | std::shared_ptr> CreateComponentImpl_Prob_AS(FixedMultiIndexSet const& mset, MapOptions opts) 15 | { 16 | ProbabilistHermite basis1d(opts.basisNorm); 17 | AdaptiveSimpson quad(opts.quadMaxSub, 1, nullptr, opts.quadAbsTol, opts.quadRelTol, QuadError::First, opts.quadMinSub); 18 | 19 | MultivariateExpansionWorker expansion(mset, basis1d); 20 | std::shared_ptr> output; 21 | 22 | output = std::make_shared>(expansion, quad, opts.contDeriv, opts.nugget); 23 | 24 | output->SetCoeffs(Kokkos::View("Component Coefficients", mset.Size())); 25 | return output; 26 | } 27 | 28 | static auto reg_host_prob_as_exp = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::ProbabilistHermite, false, PosFuncTypes::Exp, QuadTypes::AdaptiveSimpson), CreateComponentImpl_Prob_AS)); 29 | static auto reg_host_prob_as_splus = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::ProbabilistHermite, false, PosFuncTypes::SoftPlus, QuadTypes::AdaptiveSimpson), CreateComponentImpl_Prob_AS)); 30 | #if defined(MPART_ENABLE_GPU) 31 | static auto reg_device_prob_as_exp = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::ProbabilistHermite, false, PosFuncTypes::Exp, QuadTypes::AdaptiveSimpson), CreateComponentImpl_Prob_AS)); 32 | static auto reg_device_prob_as_splus = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::ProbabilistHermite, false, PosFuncTypes::SoftPlus, QuadTypes::AdaptiveSimpson), CreateComponentImpl_Prob_AS)); 33 | #endif 34 | 35 | 36 | #if defined(MPART_HAS_CEREAL) 37 | REGISTER_MONO_COMP(ProbabilistHermite, Exp, AdaptiveSimpson, Kokkos::HostSpace) 38 | REGISTER_MONO_COMP(ProbabilistHermite, SoftPlus, AdaptiveSimpson, Kokkos::HostSpace) 39 | #if defined(MPART_ENABLE_GPU) 40 | REGISTER_MONO_COMP(ProbabilistHermite, Exp, AdaptiveSimpson, mpart::DeviceSpace) 41 | REGISTER_MONO_COMP(ProbabilistHermite, Softplus, AdaptiveSimpson, mpart::DeviceSpace) 42 | #endif 43 | CEREAL_REGISTER_DYNAMIC_INIT(mpartInitMapFactory6) 44 | #endif -------------------------------------------------------------------------------- /src/MapFactoryImpl7.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/MapFactory.h" 2 | 3 | #include "MParT/MonotoneComponent.h" 4 | #include "MParT/TriangularMap.h" 5 | #include "MParT/Quadrature.h" 6 | 7 | #include "MParT/HermiteFunction.h" 8 | #include "MParT/MultivariateExpansionWorker.h" 9 | #include "MParT/PositiveBijectors.h" 10 | 11 | using namespace mpart; 12 | 13 | template 14 | std::shared_ptr> CreateComponentImpl_HF_ACC(FixedMultiIndexSet const& mset, MapOptions opts) 15 | { 16 | HermiteFunction basis1d; 17 | 18 | unsigned int level = std::log2(opts.quadPts-2); 19 | AdaptiveClenshawCurtis quad(level, opts.quadMaxSub, 1, nullptr, opts.quadAbsTol, opts.quadRelTol, QuadError::First, opts.quadMinSub); 20 | 21 | MultivariateExpansionWorker expansion(mset, basis1d); 22 | std::shared_ptr> output; 23 | 24 | output = std::make_shared>(expansion, quad, opts.contDeriv, opts.nugget); 25 | 26 | output->SetCoeffs(Kokkos::View("Component Coefficients", mset.Size())); 27 | return output; 28 | } 29 | 30 | static auto reg_host_hf_acc_exp = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::HermiteFunctions, false, PosFuncTypes::Exp, QuadTypes::AdaptiveClenshawCurtis), CreateComponentImpl_HF_ACC)); 31 | static auto reg_host_hf_acc_splus = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::HermiteFunctions, false, PosFuncTypes::SoftPlus, QuadTypes::AdaptiveClenshawCurtis), CreateComponentImpl_HF_ACC)); 32 | #if defined(MPART_ENABLE_GPU) 33 | static auto reg_device_hf_acc_exp = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::HermiteFunctions, false, PosFuncTypes::Exp, QuadTypes::AdaptiveClenshawCurtis), CreateComponentImpl_HF_ACC)); 34 | static auto reg_device_hf_acc_splus = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::HermiteFunctions, false, PosFuncTypes::SoftPlus, QuadTypes::AdaptiveClenshawCurtis), CreateComponentImpl_HF_ACC)); 35 | #endif 36 | 37 | 38 | #if defined(MPART_HAS_CEREAL) 39 | REGISTER_MONO_COMP(HermiteFunction, Exp, AdaptiveClenshawCurtis, Kokkos::HostSpace) 40 | REGISTER_MONO_COMP(HermiteFunction, SoftPlus, AdaptiveClenshawCurtis, Kokkos::HostSpace) 41 | #if defined(MPART_ENABLE_GPU) 42 | REGISTER_MONO_COMP(HermiteFunction, Exp, AdaptiveClenshawCurtis, mpart::DeviceSpace) 43 | REGISTER_MONO_COMP(HermiteFunction, Softplus, AdaptiveClenshawCurtis, mpart::DeviceSpace) 44 | #endif 45 | CEREAL_REGISTER_DYNAMIC_INIT(mpartInitMapFactory7) 46 | #endif -------------------------------------------------------------------------------- /src/MapFactoryImpl8.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/MapFactory.h" 2 | 3 | #include "MParT/MonotoneComponent.h" 4 | #include "MParT/TriangularMap.h" 5 | #include "MParT/Quadrature.h" 6 | 7 | #include "MParT/HermiteFunction.h" 8 | #include "MParT/MultivariateExpansionWorker.h" 9 | #include "MParT/PositiveBijectors.h" 10 | 11 | using namespace mpart; 12 | 13 | template 14 | std::shared_ptr> CreateComponentImpl_HF_CC(FixedMultiIndexSet const& mset, MapOptions opts) 15 | { 16 | HermiteFunction basis1d; 17 | ClenshawCurtisQuadrature quad(opts.quadPts, 1); 18 | 19 | MultivariateExpansionWorker expansion(mset, basis1d); 20 | std::shared_ptr> output; 21 | 22 | output = std::make_shared>(expansion, quad, opts.contDeriv, opts.nugget); 23 | 24 | output->SetCoeffs(Kokkos::View("Component Coefficients", mset.Size())); 25 | return output; 26 | } 27 | 28 | static auto reg_host_hf_cc_exp = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::HermiteFunctions, false, PosFuncTypes::Exp, QuadTypes::ClenshawCurtis), CreateComponentImpl_HF_CC)); 29 | static auto reg_host_hf_cc_splus = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::HermiteFunctions, false, PosFuncTypes::SoftPlus, QuadTypes::ClenshawCurtis), CreateComponentImpl_HF_CC)); 30 | #if defined(MPART_ENABLE_GPU) 31 | static auto reg_device_hf_cc_exp = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::HermiteFunctions, false, PosFuncTypes::Exp, QuadTypes::ClenshawCurtis), CreateComponentImpl_HF_CC)); 32 | static auto reg_device_hf_cc_splus = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::HermiteFunctions, false, PosFuncTypes::SoftPlus, QuadTypes::ClenshawCurtis), CreateComponentImpl_HF_CC)); 33 | #endif 34 | 35 | #if defined(MPART_HAS_CEREAL) 36 | REGISTER_MONO_COMP(HermiteFunction, Exp, ClenshawCurtisQuadrature, Kokkos::HostSpace) 37 | REGISTER_MONO_COMP(HermiteFunction, SoftPlus, ClenshawCurtisQuadrature, Kokkos::HostSpace) 38 | #if defined(MPART_ENABLE_GPU) 39 | REGISTER_MONO_COMP(HermiteFunction, Exp, ClenshawCurtisQuadrature, mpart::DeviceSpace) 40 | REGISTER_MONO_COMP(HermiteFunction, Softplus, ClenshawCurtisQuadrature, mpart::DeviceSpace) 41 | #endif 42 | CEREAL_REGISTER_DYNAMIC_INIT(mpartInitMapFactory8) 43 | #endif -------------------------------------------------------------------------------- /src/MapFactoryImpl9.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/MapFactory.h" 2 | 3 | #include "MParT/MonotoneComponent.h" 4 | #include "MParT/TriangularMap.h" 5 | #include "MParT/Quadrature.h" 6 | 7 | #include "MParT/HermiteFunction.h" 8 | #include "MParT/MultivariateExpansionWorker.h" 9 | #include "MParT/PositiveBijectors.h" 10 | 11 | using namespace mpart; 12 | 13 | template 14 | std::shared_ptr> CreateComponentImpl_HF_AS(FixedMultiIndexSet const& mset, MapOptions opts) 15 | { 16 | HermiteFunction basis1d; 17 | AdaptiveSimpson quad(opts.quadMaxSub, 1, nullptr, opts.quadAbsTol, opts.quadRelTol, QuadError::First, opts.quadMinSub); 18 | 19 | MultivariateExpansionWorker expansion(mset, basis1d); 20 | std::shared_ptr> output; 21 | 22 | output = std::make_shared>(expansion, quad, opts.contDeriv, opts.nugget); 23 | 24 | output->SetCoeffs(Kokkos::View("Component Coefficients", mset.Size())); 25 | return output; 26 | } 27 | 28 | static auto reg_host_hf_as_exp = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::HermiteFunctions, false, PosFuncTypes::Exp, QuadTypes::AdaptiveSimpson), CreateComponentImpl_HF_AS)); 29 | static auto reg_host_hf_as_splus = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::HermiteFunctions, false, PosFuncTypes::SoftPlus, QuadTypes::AdaptiveSimpson), CreateComponentImpl_HF_AS)); 30 | #if defined(MPART_ENABLE_GPU) 31 | static auto reg_device_hf_as_exp = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::HermiteFunctions, false, PosFuncTypes::Exp, QuadTypes::AdaptiveSimpson), CreateComponentImpl_HF_AS)); 32 | static auto reg_device_hf_as_splus = mpart::MapFactory::CompFactoryImpl::GetFactoryMap()->insert(std::make_pair(std::make_tuple(BasisTypes::HermiteFunctions, false, PosFuncTypes::SoftPlus, QuadTypes::AdaptiveSimpson), CreateComponentImpl_HF_AS)); 33 | #endif 34 | 35 | #if defined(MPART_HAS_CEREAL) 36 | REGISTER_MONO_COMP(HermiteFunction, Exp, AdaptiveSimpson, Kokkos::HostSpace) 37 | REGISTER_MONO_COMP(HermiteFunction, SoftPlus, AdaptiveSimpson, Kokkos::HostSpace) 38 | #if defined(MPART_ENABLE_GPU) 39 | REGISTER_MONO_COMP(HermiteFunction, Exp, AdaptiveSimpson, mpart::DeviceSpace) 40 | REGISTER_MONO_COMP(HermiteFunction, Softplus, AdaptiveSimpson, mpart::DeviceSpace) 41 | #endif 42 | CEREAL_REGISTER_DYNAMIC_INIT(mpartInitMapFactory9) 43 | #endif -------------------------------------------------------------------------------- /src/MultiIndices/MultiIndexLimiter.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/MultiIndices/MultiIndexLimiter.h" 2 | 3 | #include 4 | #include 5 | 6 | using namespace mpart; 7 | using namespace mpart::MultiIndexLimiter; 8 | 9 | 10 | bool Dimension::operator()(MultiIndex const& multi) const 11 | { 12 | for(unsigned int i=0; i const& weightsIn, 27 | double epsilonIn) : weights(weightsIn), 28 | epsilon(epsilonIn) 29 | { 30 | // validate weight vector 31 | for(unsigned int i = 0; i < weights.size(); ++i){ 32 | if((weights.at(i) > 1.0) || (weights.at(i) < 0.0)) 33 | throw std::invalid_argument("AnisotropicLimiter requires all weights have to be in [0,1]. Got weight " + std::to_string(weights[i])); 34 | } 35 | 36 | // validate threshold 37 | if ((epsilon >= 1.0) || (epsilon <= 0.0)) 38 | throw std::invalid_argument("AnisotropicLimiter requires epsilon to be in (0,1). Got epsilon = " + std::to_string(epsilon)); 39 | } 40 | 41 | 42 | bool Anisotropic::operator()(MultiIndex const& multi) const 43 | { 44 | 45 | if(multi.Length() != weights.size()) 46 | return false; 47 | 48 | double prod = 1; 49 | for(unsigned int i=0; i= epsilon; 53 | } 54 | 55 | 56 | bool MaxDegree::operator()(MultiIndex const& multi) const 57 | { 58 | if(multi.Length() != maxDegrees.size()) 59 | return false; 60 | 61 | for(unsigned int i=0; imaxDegrees.at(i)) 63 | return false; 64 | } 65 | return true; 66 | } 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/MultiIndices/MultiIndexNeighborhood.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/MultiIndices/MultiIndexNeighborhood.h" 2 | 3 | using namespace mpart; 4 | 5 | 6 | std::vector DefaultNeighborhood::ForwardNeighbors(MultiIndex const& multi) 7 | { 8 | std::vector output; 9 | std::vector vec = multi.Vector(); 10 | 11 | for(unsigned int i=0;i DefaultNeighborhood::BackwardNeighbors(MultiIndex const& multi) 21 | { 22 | std::vector output; 23 | std::vector vec = multi.Vector(); 24 | 25 | for(unsigned int i=0; ibaseNnz+1) || (nextNnz1) 60 | return false; 61 | } 62 | 63 | return (diffSum==1); 64 | } 65 | 66 | bool DefaultNeighborhood::IsBackward(MultiIndex const& base, 67 | MultiIndex const& prev) 68 | { 69 | return IsForward(prev,base); 70 | } 71 | -------------------------------------------------------------------------------- /src/Utilities/Miscellaneous.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/Utilities/Miscellaneous.h" 2 | 3 | using namespace mpart; 4 | 5 | std::string mpart::GetOption(std::unordered_map const& map, 6 | std::string const& key, 7 | std::string const& defaultValue) 8 | { 9 | 10 | // Extract the polynomial type 11 | std::string output; 12 | auto it = map.find(key); 13 | if(it==map.end()){ 14 | output = defaultValue; 15 | }else{ 16 | output = map.at(key); 17 | } 18 | return output; 19 | } -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set (MPART_SERIALIZE_TESTS "") 3 | set (MPART_OPT_TESTS "") 4 | if (MPART_ARCHIVE) 5 | set (MPART_SERIALIZE_TESTS tests/Test_Serialization.cpp) 6 | endif () 7 | if (MPART_OPT) 8 | set (MPART_OPT_TESTS 9 | tests/Test_MapObjective.cpp 10 | tests/Test_TrainMap.cpp 11 | tests/Test_TrainMapAdaptive.cpp 12 | ) 13 | endif () 14 | 15 | set (TEST_SOURCES 16 | tests/RunTests.cpp 17 | 18 | # MultiIndex tests 19 | tests/MultiIndices/Test_MultiIndex.cpp 20 | tests/MultiIndices/Test_MultiIndexSet.cpp 21 | 22 | # Distributions tests 23 | tests/Distributions/Test_Distributions_Common.cpp 24 | tests/Distributions/Test_DensityBase.cpp 25 | tests/Distributions/Test_SampleGenerator.cpp 26 | tests/Distributions/Test_Distribution.cpp 27 | tests/Distributions/Test_GaussianDistribution.cpp 28 | tests/Distributions/Test_TransportDensity.cpp 29 | tests/Distributions/Test_TransportSampler.cpp 30 | 31 | tests/Test_OrthogonalPolynomials.cpp 32 | tests/Test_RootFinding.cpp 33 | tests/Test_HermiteFunctions.cpp 34 | tests/Test_Sigmoid.cpp 35 | tests/Test_PositiveBijectors.cpp 36 | tests/Test_Quadrature.cpp 37 | tests/Test_MonotoneComponent.cpp 38 | tests/Test_MultivariateExpansion.cpp 39 | tests/Test_MultivariateExpansionWorker.cpp 40 | tests/Test_ArrayConversions.cpp 41 | tests/Test_ConditionalMapBase.cpp 42 | tests/Test_TriangularMap.cpp 43 | tests/Test_ComposedMap.cpp 44 | tests/Test_MapFactory.cpp 45 | tests/Test_LinearizedBasis.cpp 46 | tests/Test_AffineMap.cpp 47 | tests/Test_LinearAlgebra.cpp 48 | tests/Test_AffineFunction.cpp 49 | tests/Test_IdentityMap.cpp 50 | tests/Test_SummarizedMap.cpp 51 | #tests/Test_TensorProductFunction.cpp 52 | 53 | ${MPART_SERIALIZE_TESTS} 54 | ${MPART_OPT_TESTS} 55 | PARENT_SCOPE) 56 | -------------------------------------------------------------------------------- /tests/Distributions/Test_Distribution.cpp: -------------------------------------------------------------------------------- 1 | #include "Test_Distributions_Common.h" 2 | 3 | TEST_CASE( "Testing Distribution Class" , "[DistributionClass]") { 4 | auto sampler = std::make_shared>(2); 5 | auto density = std::make_shared>(2); 6 | auto distribution = Distribution(sampler, density); 7 | distribution.SetSeed(42); 8 | unsigned int N_samp = 5000; 9 | unsigned int N_bins = 50; 10 | double hist_tol = 1e-2; 11 | 12 | double bin_inc = std::exp(1.) / N_bins; 13 | double expected_prop = 1. / (N_bins * N_bins); 14 | 15 | // Create a histogram of the samples 16 | std::vector> hist(N_bins, std::vector(N_bins, 0)); 17 | for(int i = 0; i < N_bins; i++) { 18 | for(int j = 0; j < N_bins; j++) { 19 | hist[i][j] = 0; 20 | } 21 | } 22 | 23 | // Ensure the distribution is 2D 24 | REQUIRE(distribution.Dim() == 2); 25 | 26 | // Sample from the distribution and fill the histogram 27 | auto samples = distribution.Sample(N_samp); 28 | for(int i = 0; i < N_samp; i++) { 29 | auto x1 = samples(0, i); 30 | auto x2 = samples(1, i); 31 | hist[std::floor(x1 / bin_inc)][std::floor(x2 / bin_inc)]++; 32 | } 33 | 34 | // Check that the histogram is consistent with the expected distribution 35 | double max_dev = 0.; 36 | for(int i = 0; i < N_bins; i++) { 37 | for(int j = 0; j < N_bins; j++) { 38 | double prop = ((double) hist[i][j]) / ((double) N_samp); 39 | max_dev = std::max(max_dev, std::abs(prop - expected_prop)); 40 | } 41 | } 42 | REQUIRE(max_dev < hist_tol); 43 | 44 | // Check that the density is consistent with the expected distribution 45 | double density_tol = 1e-6; 46 | double exp_log_density = -2.; 47 | double exp_grad_log_density = 0.; 48 | StridedMatrix const_samples = samples; 49 | auto density_samps = distribution.LogDensity(const_samples); 50 | auto grad_density_samps = distribution.LogDensityInputGrad(const_samples); 51 | double max_dev_log_density = 0.; 52 | double max_dev_grad_log_density = 0.; 53 | for(int i = 0; i < N_samp; i++) { 54 | max_dev_log_density = std::max(max_dev_log_density, std::abs(density_samps(i) - exp_log_density)); 55 | max_dev_grad_log_density = std::max(max_dev_grad_log_density, std::abs(grad_density_samps(0, i) - exp_grad_log_density)); 56 | max_dev_grad_log_density = std::max(max_dev_grad_log_density, std::abs(grad_density_samps(1, i) - exp_grad_log_density)); 57 | } 58 | REQUIRE(max_dev_log_density < density_tol); 59 | REQUIRE(max_dev_grad_log_density < density_tol); 60 | } -------------------------------------------------------------------------------- /tests/Distributions/Test_Distributions_Common.cpp: -------------------------------------------------------------------------------- 1 | #include "Test_Distributions_Common.h" 2 | 3 | void TestStandardNormalSamples(StridedMatrix samples) { 4 | unsigned int dim = samples.extent(0); 5 | unsigned int N_samp = samples.extent(1); 6 | double mc_margin = (1/std::sqrt(N_samp))*4.0; 7 | 8 | Kokkos::View mean("mean", dim); 9 | Kokkos::View covar("covar", dim, dim); 10 | std::fill(mean.data(), mean.data()+dim, 0.0); 11 | std::fill(covar.data(), covar.data()+dim*dim, 0.0); 12 | // Calculate sample mean and sample covariance 13 | for(int i = 0; i < N_samp; i++) { 14 | for(int j = 0; j < dim; j++) { 15 | mean(j) += samples(j, i)/N_samp; 16 | for(int k = 0; k < dim; k++) { 17 | covar(j, k) += samples(j, i) * samples(k, i)/(N_samp-1); 18 | } 19 | } 20 | } 21 | 22 | // Check that the mean is zero and the covariance is the identity matrix 23 | for(int i = 0; i < dim; i++) { 24 | REQUIRE(mean(i) == Approx(0.0).margin(mc_margin)); 25 | for(int j = 0; j < dim; j++) { 26 | double diag = (double) (i == j); 27 | REQUIRE(covar(i, j) - mean(i)*mean(j) == Approx(diag).margin(mc_margin)); 28 | } 29 | } 30 | 31 | std::vector in_one_std (dim, 0); 32 | std::vector in_two_std (dim, 0); 33 | std::vector in_three_std (dim, 0); 34 | for(int i = 0; i < N_samp; i++) { 35 | for(int j = 0; j < dim; j++) { 36 | double samp_abs = std::abs(samples(j, i)); 37 | if(samp_abs < 1.0) { 38 | in_one_std[j]++; 39 | } 40 | if(samp_abs < 2.0) { 41 | in_two_std[j]++; 42 | } 43 | if(samp_abs < 3.0) { 44 | in_three_std[j]++; 45 | } 46 | } 47 | } 48 | double emp_one_std = 0.682689492137; 49 | double emp_two_std = 0.954499736104; 50 | double emp_three_std = 0.997300203937; 51 | for(int i = 0; i < dim; i++) { 52 | REQUIRE(in_one_std[i]/(double)N_samp == Approx(emp_one_std).margin(mc_margin)); 53 | REQUIRE(in_two_std[i]/(double)N_samp == Approx(emp_two_std).margin(mc_margin)); 54 | REQUIRE(in_three_std[i]/(double)N_samp == Approx(emp_three_std).margin(mc_margin)); 55 | } 56 | } -------------------------------------------------------------------------------- /tests/Distributions/Test_Distributions_Common.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_DISTRIBUTIONS_COMMON_H 2 | #define TEST_DISTRIBUTIONS_COMMON_H 3 | 4 | #include 5 | #include 6 | #include "MParT/Utilities/ArrayConversions.h" 7 | #include "MParT/Distributions/DensityBase.h" 8 | #include "MParT/Distributions/SampleGenerator.h" 9 | #include "MParT/Distributions/GaussianSamplerDensity.h" 10 | #include "MParT/Distributions/Distribution.h" 11 | 12 | using namespace mpart; 13 | using namespace Catch; 14 | 15 | // Uniform generator on [0,e]^N 16 | // TODO: Test on GPU 17 | template 18 | class UniformSampler: public SampleGenerator { 19 | public: 20 | // Set a given seed for this test 21 | UniformSampler(int dim, double scale = std::exp(1.)): SampleGenerator(dim, seed), scale_(scale) {} 22 | 23 | void SampleImpl(StridedMatrix output) { 24 | Kokkos::MDRangePolicy,typename MemoryToExecution::Space> policy({0, 0}, {output.extent(0), output.extent(1)}); 25 | Kokkos::parallel_for(policy, KOKKOS_LAMBDA(int i, int j) { 26 | auto rgen = this->rand_pool.get_state(); 27 | output(i,j) = scale_*rgen.drand(); 28 | this->rand_pool.free_state(rgen); 29 | }); 30 | } 31 | private: 32 | static const unsigned int seed = 160258; 33 | const double scale_; 34 | }; 35 | 36 | // Uniform density on [0,e]^2 37 | template 38 | class UniformDensity : public DensityBase { 39 | public: 40 | UniformDensity(int dim): DensityBase(dim) {} 41 | void LogDensityImpl(StridedMatrix const &pts, StridedVector output) override { 42 | double euler = std::exp(1.0); 43 | unsigned int N = pts.extent(1); 44 | Kokkos::parallel_for( "uniform log density", N, KOKKOS_LAMBDA (const int& j) { 45 | bool in_bounds1 = (pts(0, j) >= 0.0) && (pts(0, j) <= euler); 46 | bool in_bounds2 = (pts(1, j) >= 0.0) && (pts(1, j) <= euler); 47 | output(j) = in_bounds1 && in_bounds2 ? -2 : -std::numeric_limits::infinity(); 48 | }); 49 | } 50 | 51 | void LogDensityInputGradImpl(StridedMatrix const &pts, StridedMatrix output) override { 52 | unsigned int N = pts.extent(1); 53 | Kokkos::parallel_for( "uniform grad log density", N, KOKKOS_LAMBDA (const int& j) { 54 | output(0,j) = 0.; 55 | output(1,j) = 0.; 56 | }); 57 | } 58 | }; 59 | 60 | // Tests samples that should be transformed to a standard normal distribution 61 | void TestStandardNormalSamples(StridedMatrix samples); 62 | 63 | #endif //MPART_TEST_DISTRIBUTIONS_COMMON_H 64 | -------------------------------------------------------------------------------- /tests/Distributions/Test_SampleGenerator.cpp: -------------------------------------------------------------------------------- 1 | #include "Test_Distributions_Common.h" 2 | 3 | #include 4 | #include 5 | 6 | TEST_CASE( "Testing SampleGenerator", "[SampleGenerator]") { 7 | // Sample 1000 points 8 | // Check empirical CDF against uniform CDF 9 | // assert the difference is less than something 10 | auto generator = std::make_shared>(1); 11 | unsigned int N_pts = 1000; 12 | double eps_N = 1e-3 + 1. /std::sqrt(N_pts); // 1/sqrt(N_pts) + epsilon 13 | SECTION("SampleImpl") { 14 | Kokkos::View output ("output", 1, N_pts); 15 | generator->SampleImpl(output); 16 | std::vector idx (N_pts); 17 | std::iota(idx.begin(), idx.end(), 0); 18 | std::sort(idx.begin(), idx.end(), [&output](int i1, int i2) {return output(0,i1) < output(0,i2);}); 19 | 20 | // Need to take inverse permutation to get correct ordering for exact CDF calculation 21 | std::vector inv_idx (N_pts); 22 | for(unsigned int j = 0; j < N_pts; ++j) { 23 | inv_idx[idx[j]] = j; 24 | } 25 | 26 | // Calculate mean L1 distance between empirical CDF and uniform CDF 27 | double diff = 0.; 28 | double euler = std::exp(1.); 29 | for(unsigned int j = 0; j < N_pts; ++j) { 30 | double ecdf_j = euler*static_cast(inv_idx[j])/static_cast(N_pts); 31 | diff += std::abs(ecdf_j - output(0,j)); 32 | } 33 | diff /= N_pts; 34 | REQUIRE(diff == Approx(0.).epsilon(eps_N).margin(eps_N)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/Distributions/Test_TransportDistributionFactory.cpp: -------------------------------------------------------------------------------- 1 | #include "MParT/Distributions/TransportDistributionFactory.h" 2 | #include "MParT/Distributions/GaussianSamplerDensity.h" 3 | 4 | 5 | using namespace mpart; 6 | using namespace Catch; 7 | 8 | TEST_CASE("Creating Pullback/Pushforward distribution", "[CreatePullbackPushforward]") { 9 | unsigned int dim = 2; 10 | // Form the affine map T(x) = 2*x + [1,1] 11 | double diag_el = 2.0; 12 | double mean = 1.0; 13 | Kokkos::View A("A", dim, dim); 14 | Kokkos::View b("b", dim); 15 | for(int i = 0; i < dim; i++) { 16 | b(i) = mean; 17 | for(int j = 0; j < dim; j++) { 18 | A(i, j) = ((double) i == j)*diag_el; 19 | } 20 | } 21 | 22 | // Create the map and density to use 23 | auto map = std::make_shared>(A, b); 24 | auto reference = CreateDistribution>(dim); 25 | 26 | std::shared_ptr> pullback = CreatePullback(map, reference); 27 | 28 | std::shared_ptr> pushforward = CreatePushforward(map, reference); 29 | } -------------------------------------------------------------------------------- /tests/Distributions/Test_TransportSampler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "MParT/Utilities/ArrayConversions.h" 4 | #include "MParT/Distributions/PullbackSampler.h" 5 | #include "MParT/Distributions/PushforwardSampler.h" 6 | #include "MParT/Distributions/GaussianSamplerDensity.h" 7 | #include "MParT/AffineMap.h" 8 | 9 | #include "Test_Distributions_Common.h" 10 | 11 | using namespace mpart; 12 | using namespace Catch; 13 | 14 | TEST_CASE( "Testing Pullback/Pushforward sampling", "[PullbackPushforwardSampler]") { 15 | unsigned int dim = 2; 16 | unsigned int N_samp = 10000; 17 | unsigned int seed = 162849; 18 | 19 | // Form the affine map T(x) = 2*x + [1,1] 20 | double diag_el = 2.0; 21 | double mean = 1.0; 22 | Kokkos::View A("A", dim, dim); 23 | Kokkos::View b("b", dim); 24 | for(int i = 0; i < dim; i++) { 25 | b(i) = mean; 26 | for(int j = 0; j < dim; j++) { 27 | A(i, j) = ((double) i == j)*diag_el; 28 | } 29 | } 30 | 31 | // Create the map and density to use 32 | auto map = std::make_shared>(A, b); 33 | auto density = std::make_shared>(dim); 34 | 35 | SECTION("PullbackSampler") { 36 | PullbackSampler pullback {map, density}; 37 | 38 | // Set the seed and create samples to test the densities 39 | pullback.SetSeed(seed); 40 | 41 | auto pullbackSamples = pullback.Sample(N_samp); 42 | 43 | // Calculate the pullback and pushforward density error 44 | auto policy = Kokkos::MDRangePolicy>({0, 0}, {N_samp, dim}); 45 | Kokkos::parallel_for("Normalize Pullback Samples", policy, KOKKOS_LAMBDA(const int j, const int i) { 46 | pullbackSamples(i,j) *= diag_el; 47 | pullbackSamples(i,j) += mean; 48 | }); 49 | 50 | TestStandardNormalSamples(pullbackSamples); 51 | } 52 | SECTION("PushforwardSampler") { 53 | // Create the pushforward sampler 54 | PushforwardSampler pushforward {map, density}; 55 | 56 | // Set the seed and create samples 57 | pushforward.SetSeed(seed); 58 | auto pushforwardSamples = pushforward.Sample(N_samp); 59 | 60 | // Calculate the pullback and pushforward density error 61 | auto policy = Kokkos::MDRangePolicy>({0, 0}, {N_samp, dim}); 62 | Kokkos::parallel_for("Normalize Samples", policy, KOKKOS_LAMBDA(const int j, const int i) { 63 | pushforwardSamples(i,j) -= mean; 64 | pushforwardSamples(i,j) /= diag_el; 65 | }); 66 | 67 | TestStandardNormalSamples(pushforwardSamples); 68 | } 69 | } -------------------------------------------------------------------------------- /tests/KokkosInfo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | int main( int argc, char* argv[] ) { 6 | Kokkos::initialize(argc,argv); 7 | 8 | Kokkos::print_configuration(std::cout); 9 | 10 | Kokkos::finalize(); 11 | return 0; 12 | } -------------------------------------------------------------------------------- /tests/RunTests.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "MParT/Initialization.h" 4 | 5 | int main( int argc, char* argv[] ) { 6 | mpart::Initialize(argc,argv); 7 | 8 | Catch::Session session; // There must be exactly one instance 9 | 10 | int cores = 0; // Some user variable you want to be able to set 11 | 12 | // Build a new parser on top of Catch2's 13 | using namespace Catch::Clara; 14 | auto cli 15 | = session.cli() | Opt( cores, "kokkos-thread" ) ["--kokkos-threads"]("Number of cores to use with Kokkos."); 16 | 17 | // Now pass the new composite back to Catch2 so it uses that 18 | session.cli( cli ); 19 | 20 | // Let Catch2 (using Clara) parse the command line 21 | int returnCode = session.applyCommandLine( argc, argv ); 22 | if( returnCode != 0 ) // Indicates a command line error 23 | return returnCode; 24 | 25 | session.run(); 26 | } -------------------------------------------------------------------------------- /tests/Test_PositiveBijectors.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "MParT/PositiveBijectors.h" 6 | #include "MParT/Utilities/ArrayConversions.h" 7 | 8 | using namespace mpart; 9 | using namespace Catch; 10 | 11 | 12 | TEST_CASE( "Testing soft plus function.", "[SofPlus]" ) { 13 | 14 | // Test values near origin 15 | std::vector xs{-1.0, -0.5, 0.0, 0.1, 1.0}; 16 | 17 | for(auto& x : xs){ 18 | double eval = SoftPlus::Evaluate(x); 19 | CHECK( eval == Approx(std::log(1.0+std::exp(x))) ); 20 | CHECK( SoftPlus::Derivative(x) == Approx(std::exp(x) / (std::exp(x) + 1.0)) ); 21 | CHECK( SoftPlus::SecondDerivative(x) == Approx(std::exp(x) / std::pow(std::exp(x) + 1.0, 2.0)) ); 22 | CHECK( SoftPlus::Inverse(eval) == Approx(x) ); 23 | } 24 | 25 | // Test extreme positive values 26 | std::vector xes{50.0, 100.0}; 27 | 28 | for(auto& x : xes){ 29 | double eval = SoftPlus::Evaluate(x); 30 | CHECK( eval == Approx(x) ); 31 | CHECK( SoftPlus::Derivative(x) == Approx(1.0) ); 32 | CHECK( SoftPlus::Inverse(eval) == Approx(x) ); 33 | } 34 | 35 | } 36 | 37 | 38 | #if defined(KOKKOS_ENABLE_CUDA ) || defined(KOKKOS_ENABLE_SYCL) 39 | 40 | TEST_CASE( "Testing soft plus function on device.", "[SofPlusDevice]" ) { 41 | const double floatTol = 1e-15; 42 | 43 | // Test values near origin 44 | Kokkos::View xs_host("host xs", 5); 45 | xs_host(0) = -1.0; 46 | xs_host(1) = -0.5; 47 | xs_host(2) = 0.0; 48 | xs_host(3) = 0.1; 49 | xs_host(4) = 1.0; 50 | 51 | auto xs_device = ToDevice(xs_host); 52 | 53 | Kokkos::View ys_device("ys_device", xs_host.extent(0)); 54 | Kokkos::View deriv_device("deriv_device", xs_host.extent(0)); 55 | 56 | Kokkos::parallel_for(xs_host.size(), KOKKOS_LAMBDA(const size_t ind){ 57 | ys_device(ind) = SoftPlus::Evaluate(xs_device(ind)); 58 | deriv_device(ind) = SoftPlus::Derivative(xs_device(ind)); 59 | }); 60 | 61 | auto ys_host = ToHost(ys_device); 62 | auto deriv_host = ToHost<>(deriv_device); 63 | 64 | for(unsigned int i=0; i