Skip to content

Commit

Permalink
Merge branch 'main' into ExpandAllpy
Browse files Browse the repository at this point in the history
  • Loading branch information
dannys4 authored Apr 18, 2023
2 parents d224206 + 5549746 commit a1a9a95
Show file tree
Hide file tree
Showing 20 changed files with 325 additions and 56 deletions.
9 changes: 5 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13)
project(MParT VERSION 0.0.1)
project(MParT VERSION 2.0.2)

message(STATUS "Will install MParT to ${CMAKE_INSTALL_PREFIX}")

Expand Down Expand Up @@ -53,6 +53,7 @@ option(BUILD_SHARED_LIBS "Build using shared libraries" ON)

# #############################################################
# RPATH settings
# See https://gist.github.com/kprussing/db21614ca5b51cedff07dfb70059f280 for scikit-build example

# use, i.e. don't skip the full RPATH for the build tree
set(CMAKE_SKIP_BUILD_RPATH FALSE)
Expand All @@ -70,9 +71,9 @@ set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
# the RPATH to be used when installing, but only if it's not a system directory
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)

if("${isSystemDir}" STREQUAL "-1")
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
endif("${isSystemDir}" STREQUAL "-1")
# if("${isSystemDir}" STREQUAL "-1")
# set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
# endif("${isSystemDir}" STREQUAL "-1")

# #############################################################
# Dependencies
Expand Down
6 changes: 3 additions & 3 deletions MParT/AffineFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ class AffineFunction : public ParameterizedFunctionBase<MemorySpace>


protected:

StridedMatrix<double,MemorySpace> A_;
StridedVector<double,MemorySpace> b_;
Kokkos::View<double**, Kokkos::LayoutLeft, MemorySpace> A_;
Kokkos::View<double*, Kokkos::LayoutLeft, MemorySpace> b_;

int ldA;

Expand Down
5 changes: 3 additions & 2 deletions MParT/AffineMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
namespace mpart{

/** @brief Defines transformations of the form \f$Ax+b\f$ for an invertible matrix \f$A\f$ and vector offset \f$b\f$.
* Makes a deep copy of any views passed to the constructor.
*/
template<typename MemorySpace>
class AffineMap : public ConditionalMapBase<MemorySpace>
Expand Down Expand Up @@ -64,8 +65,8 @@ class AffineMap : public ConditionalMapBase<MemorySpace>

protected:

StridedMatrix<double,MemorySpace> A_;
StridedVector<double,MemorySpace> b_;
Kokkos::View<double**, Kokkos::LayoutLeft, MemorySpace> A_;
Kokkos::View<double*, Kokkos::LayoutLeft, MemorySpace> b_;

mpart::PartialPivLU<MemorySpace> luSolver_;
double logDet_;
Expand Down
7 changes: 4 additions & 3 deletions MParT/MapObjective.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@ class MapObjective {
*/
double operator()(unsigned int n, const double* x, double* grad, std::shared_ptr<ConditionalMapBase<MemorySpace>> map);

unsigned int Dim(){return train_.extent(0);}
unsigned int NumSamples(){return train_.extent(1);}
unsigned int InputDim() const {return train_.extent(0);}
virtual unsigned int MapOutputDim() const {return train_.extent(0);}
unsigned int NumSamples() const {return train_.extent(1);}

/**
* @brief Shortcut to calculate the error of the map on the training dataset
Expand Down Expand Up @@ -176,7 +177,7 @@ class KLObjective: public MapObjective<MemorySpace> {
double ObjectivePlusCoeffGradImpl(StridedMatrix<const double, MemorySpace> data, StridedVector<double, MemorySpace> grad, std::shared_ptr<ConditionalMapBase<MemorySpace>> map) const override;
double ObjectiveImpl(StridedMatrix<const double, MemorySpace> data, std::shared_ptr<ConditionalMapBase<MemorySpace>> map) const override;
void CoeffGradImpl(StridedMatrix<const double, MemorySpace> data, StridedVector<double, MemorySpace> grad, std::shared_ptr<ConditionalMapBase<MemorySpace>> map) const override;

unsigned int MapOutputDim() const override {return density_->Dim();}
private:
/**
* @brief Density \f$\mu\f$ to calculate the KL with respect to (i.e. \f$D(\cdot||\mu)\f$ )
Expand Down
44 changes: 44 additions & 0 deletions bindings/matlab/tests/TrainMapAdaptiveTest.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
classdef TrainMapTest < matlab.unittest.TestCase
% Copyright 2014 - 2016 The MathWorks, Inc.

methods ( Test )
function train(testCase)
% Create data
dim = 2;
N=20000;
N_test = N/5;
data = randn(dim+1,N);
target = [data(1,:);data(2,:);data(3,:) + data(2,:).^2];
test = target(:,1:N_test);
train = target(:,N_test+1:end);

% Create objective and map
obj1 = GaussianKLObjective(train, test, 1);
obj2 = GaussianKLObjective(train, test);
map_options = ATMOptions();
map_options.maxDegrees = MultiIndex([3,5])
msets2 = [CreateTotalOrder(1,1), CreateTotalOrder(2,1)]
msets1 = [CreateTotalOrder(2,1)]

% Print test error before
map1 = TrainMapAdaptive(msets1, obj1, map_options);
map2 = TrainMapAdaptive(msets2, obj2, map_options);

% Evaluate test samples after training
KS_stat1 = KSStatistic(map1,test);
KS_stat2 = KSStatistic(map2,test);
testCase.verifyTrue(KS_stat1 < 0.1);
testCase.verifyTrue(KS_stat2 < 0.1);
end
end
end


% Perform Kolmogorov-Smirnov test
function KS_stat = KSStatistic(map,samples)
pullback_evals = Evaluate(map,samples);
sorted_samples = sort(pullback_evals(:));
samps_cdf = (1 + erf(sorted_samples/sqrt(2)))/2;
samps_ecdf = (1:numel(sorted_samples))'/numel(sorted_samples);
KS_stat = max(abs(samps_ecdf - samps_cdf));
end
12 changes: 11 additions & 1 deletion bindings/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,14 @@ target_link_libraries(pympart PRIVATE mpart Kokkos::kokkos Eigen3::Eigen ${EXT_L

# Add an installation target for the python bindings
install(TARGETS pympart DESTINATION "${PYTHON_INSTALL_PREFIX}")
install(DIRECTORY package/ DESTINATION "${PYTHON_INSTALL_PREFIX}")
install(DIRECTORY package/ DESTINATION "${PYTHON_INSTALL_PREFIX}")

# See https://gist.github.com/kprussing/db21614ca5b51cedff07dfb70059f280
#set(lib_path "${PYTHON_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
#message(STATUS "LIB_PATH = ${lib_path}")
#list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${lib_path}" is_system)
if(SKBUILD)
if (SKBUILD_LIB_RPATH)
set_target_properties(pympart PROPERTIES INSTALL_RPATH "${SKBUILD_LIB_RPATH}")
endif()
endif()
12 changes: 6 additions & 6 deletions bindings/python/src/AffineMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ using namespace mpart::binding;
void mpart::binding::AffineMapWrapperHost(py::module &m)
{
py::class_<AffineMap<Kokkos::HostSpace>, ConditionalMapBase<Kokkos::HostSpace>, std::shared_ptr<AffineMap<Kokkos::HostSpace>>>(m, "AffineMap")
.def(py::init( [](Eigen::Ref<Eigen::VectorXd> const& b)
.def(py::init( [](py::EigenDRef<Eigen::VectorXd> const& b)
{
return new AffineMap<Kokkos::HostSpace>(VecToKokkos<double, Kokkos::HostSpace>(b));
}))
.def(py::init( [](Eigen::Ref<Eigen::MatrixXd> const& A, Eigen::Ref<Eigen::VectorXd> const& b)
.def(py::init( [](py::EigenDRef<Eigen::MatrixXd> const& A, py::EigenDRef<Eigen::VectorXd> const& b)
{
return new AffineMap<Kokkos::HostSpace>(MatToKokkos<double, Kokkos::HostSpace>(A), VecToKokkos<double, Kokkos::HostSpace>(b));
}))
.def(py::init( [](Eigen::Ref<Eigen::MatrixXd> const& A)
.def(py::init( [](py::EigenDRef<Eigen::MatrixXd> const& A)
{
return new AffineMap<Kokkos::HostSpace>(MatToKokkos<double, Kokkos::HostSpace>(A));
}));
Expand All @@ -31,15 +31,15 @@ void mpart::binding::AffineMapWrapperHost(py::module &m)
void mpart::binding::AffineFunctionWrapperHost(py::module &m)
{
py::class_<AffineFunction<Kokkos::HostSpace>, ParameterizedFunctionBase<Kokkos::HostSpace>, std::shared_ptr<AffineFunction<Kokkos::HostSpace>>>(m, "AffineFunction")
.def(py::init( [](Eigen::Ref<Eigen::VectorXd> const& b)
.def(py::init( [](py::EigenDRef<Eigen::VectorXd> const& b)
{
return new AffineFunction<Kokkos::HostSpace>(VecToKokkos<double, Kokkos::HostSpace>(b));
}))
.def(py::init( [](Eigen::Ref<Eigen::MatrixXd> const& A, Eigen::Ref<Eigen::VectorXd> const& b)
.def(py::init( [](py::EigenDRef<Eigen::MatrixXd> const& A, py::EigenDRef<Eigen::VectorXd> const& b)
{
return new AffineFunction<Kokkos::HostSpace>(MatToKokkos<double, Kokkos::HostSpace>(A), VecToKokkos<double, Kokkos::HostSpace>(b));
}))
.def(py::init( [](Eigen::Ref<Eigen::MatrixXd> const& A)
.def(py::init( [](py::EigenDRef<Eigen::MatrixXd> const& A)
{
return new AffineFunction<Kokkos::HostSpace>(MatToKokkos<double, Kokkos::HostSpace>(A));
}));
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ license={file="LICENSE.txt"}
readme="README.md"
requires-python = ">=3.7"
description="A Monotone Parameterization Toolkit"
version="1.4.4"
version="2.0.2"
keywords=["Measure Transport", "Monotone", "Transport Map", "Isotonic Regression", "Triangular", "Knothe-Rosenblatt"]

[project.urls]
Expand Down
34 changes: 33 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,41 @@
from skbuild import setup

import os, sys, site
import warnings

def get_install_locations():
"""Return the installation directory, or '' if no directory could be found
Adapted from stack overflow post https://stackoverflow.com/a/36205159
"""

if '--user' in sys.argv:
paths = (site.getusersitepackages(),)
else:
py_version = f'{sys.version_info[0]}.{sys.version_info[1]}'
paths = [
sys.prefix + f'/lib/python{py_version}/dist-packages/',
sys.prefix + f'/lib/python{py_version}/site-packages/',
sys.prefix + f'/local/lib/python{py_version}/dist-packages/',
sys.prefix + f'/local/lib/python{py_version}/site-packages/',
f'/Library/Frameworks/Python.framework/Versions/{py_version}/lib/python{py_version}/site-packages/'
]

for path in paths:
if os.path.exists(path):
parts = path.split('/')
lib_indices = [index for index, item in enumerate(parts) if item == 'lib']
return path, '/'.join(parts[0:(lib_indices[-1]+1)])

return ''

site_folder, lib_folder = get_install_locations()


setup(
packages=['mpart'],
package_dir={'mpart': 'bindings/python/package'},
package_data={'mpart':['**/*pympart*']},
include_package_data=True,
cmake_args=['-DKokkos_ENABLE_THREADS:BOOL=ON', '-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=']
cmake_args=['-DKokkos_ENABLE_THREADS:BOOL=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=']
)
23 changes: 15 additions & 8 deletions src/AffineFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ using namespace mpart;

template<typename MemorySpace>
AffineFunction<MemorySpace>::AffineFunction(StridedVector<double,MemorySpace> b) : ParameterizedFunctionBase<MemorySpace>(b.size(),b.size(),0),
b_("b",b.layout())
b_("b",b.extent(0))
{

Kokkos::deep_copy(b_, b);
}

template<typename MemorySpace>
AffineFunction<MemorySpace>::AffineFunction(StridedMatrix<double,MemorySpace> A) : ParameterizedFunctionBase<MemorySpace>(A.extent(1),A.extent(0),0),
A_("A", A.layout())
A_("A", A.extent(0), A.extent(1))
{
Kokkos::deep_copy(A_, A);
assert(A_.extent(0)<=A_.extent(1));
Expand All @@ -29,8 +29,8 @@ AffineFunction<MemorySpace>::AffineFunction(StridedMatrix<double,MemorySpace> A)
template<typename MemorySpace>
AffineFunction<MemorySpace>::AffineFunction(StridedMatrix<double,MemorySpace> A,
StridedVector<double,MemorySpace> b) : ParameterizedFunctionBase<MemorySpace>(A.extent(1),A.extent(0),0),
A_("A", A.layout()),
b_("b",b.layout())
A_("A", A.extent(0), A.extent(1)),
b_("b", b.extent(0))
{
Kokkos::deep_copy(A_, A);
Kokkos::deep_copy(b_, b);
Expand All @@ -43,19 +43,26 @@ template<typename MemorySpace>
void AffineFunction<MemorySpace>::EvaluateImpl(StridedMatrix<const double, MemorySpace> const& pts,
StridedMatrix<double, MemorySpace> output)
{
unsigned int numPts = pts.extent(1);
Kokkos::MDRangePolicy<Kokkos::Rank<2>, typename MemoryToExecution<MemorySpace>::Space> policy({{0, 0}}, {{numPts, this->outputDim}});

// Linear part
if(A_.extent(0)>0){

// Initialize output to zeros
Kokkos::parallel_for(policy, KOKKOS_CLASS_LAMBDA(const int& j, const int& i) {
output(i,j) = 0.0;
});

dgemm<MemorySpace>(1.0, A_, pts, 0.0, output);

}else{
Kokkos::deep_copy(output, pts);
}

// Bias part
if(b_.size()>0){

unsigned int numPts = pts.extent(1);
Kokkos::MDRangePolicy<Kokkos::Rank<2>, typename MemoryToExecution<MemorySpace>::Space> policy({0, 0}, {numPts, this->outputDim});

Kokkos::parallel_for(policy, KOKKOS_CLASS_LAMBDA(const int& j, const int& i) {
output(i,j) += b_(i);
});
Expand Down
31 changes: 15 additions & 16 deletions src/AffineMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ using namespace mpart;

template<typename MemorySpace>
AffineMap<MemorySpace>::AffineMap(StridedVector<double,MemorySpace> b) : ConditionalMapBase<MemorySpace>(b.size(),b.size(),0),
b_("b",b.layout()),
b_("b", b.extent(0)),
logDet_(0.0)
{
Kokkos::deep_copy(b_, b);
}

template<typename MemorySpace>
AffineMap<MemorySpace>::AffineMap(StridedMatrix<double,MemorySpace> A) : ConditionalMapBase<MemorySpace>(A.extent(1),A.extent(0),0),
A_("A", A.layout())
A_("A", A.extent(0), A.extent(1))
{
Kokkos::deep_copy(A_, A);
assert(A_.extent(0)<=A_.extent(1));
Expand All @@ -28,8 +28,8 @@ AffineMap<MemorySpace>::AffineMap(StridedMatrix<double,MemorySpace> A) : Conditi
template<typename MemorySpace>
AffineMap<MemorySpace>::AffineMap(StridedMatrix<double,MemorySpace> A,
StridedVector<double,MemorySpace> b) : ConditionalMapBase<MemorySpace>(A.extent(1),A.extent(0),0),
A_("A", A.layout()),
b_("b",b.layout())
A_("A", A.extent(0), A.extent(1)),
b_("b", b.extent(0))
{
Kokkos::deep_copy(A_, A);
Kokkos::deep_copy(b_, b);
Expand All @@ -42,13 +42,6 @@ AffineMap<MemorySpace>::AffineMap(StridedMatrix<double,MemorySpace> A,
template<typename MemorySpace>
void AffineMap<MemorySpace>::Factorize(){

// If A_ is not column major, create a column major version
if(A_.stride_0()!=1){
Kokkos::View<double**, Kokkos::LayoutLeft, MemorySpace> anew("A_", A_.extent(0), A_.extent(1));
Kokkos::deep_copy(anew, A_);
A_ = anew;
}

if(A_.extent(0)!=A_.extent(1)){
StridedMatrix<const double, MemorySpace> Asub = Kokkos::subview(A_, Kokkos::ALL(), std::make_pair(A_.extent(1)-A_.extent(0),A_.extent(1)));
luSolver_.compute(Asub);
Expand Down Expand Up @@ -145,19 +138,25 @@ template<typename MemorySpace>
void AffineMap<MemorySpace>::EvaluateImpl(StridedMatrix<const double, MemorySpace> const& pts,
StridedMatrix<double, MemorySpace> output)
{
unsigned int numPts = pts.extent(1);
Kokkos::MDRangePolicy<Kokkos::Rank<2>, typename MemoryToExecution<MemorySpace>::Space> policy({{0, 0}}, {{numPts, this->outputDim}});

// Linear part
if(A_.extent(0)>0){

// Initialize output to zeros
Kokkos::parallel_for(policy, KOKKOS_CLASS_LAMBDA(const int& j, const int& i) {
output(i,j) = 0.0;
});

dgemm<MemorySpace>(1.0, A_, pts, 0.0, output);

}else{
Kokkos::deep_copy(output, pts);
}

// Bias part
if(b_.size()>0){

unsigned int numPts = pts.extent(1);
Kokkos::MDRangePolicy<Kokkos::Rank<2>, typename MemoryToExecution<MemorySpace>::Space> policy({{0, 0}}, {{numPts, this->outputDim}});

Kokkos::parallel_for(policy, KOKKOS_CLASS_LAMBDA(const int& j, const int& i) {
output(i,j) += b_(i);
});
Expand Down
3 changes: 3 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ target_sources(mpart
MapFactoryImpl13.cpp
MapFactoryImpl14.cpp
MapFactoryImpl15.cpp
MapFactoryImpl16.cpp
MapFactoryImpl17.cpp
MapFactoryImpl18.cpp

${MPART_OPT_FILES}
Initialization.cpp
Expand Down
Loading

0 comments on commit a1a9a95

Please sign in to comment.