-
-
Notifications
You must be signed in to change notification settings - Fork 190
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature: L1 and L2 norms #2636
Merged
Merged
Feature: L1 and L2 norms #2636
Changes from 29 commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
47c5bd8
working L1 norm and tests
lyndond 7dbd6a9
fix typo
lyndond f89d5f0
norm2 and tests done
lyndond d27f237
revert back dot_self
lyndond 71b3181
pass lint check
lyndond c6721c6
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot e54389c
make dot_self templated
lyndond a504f17
template and Eigen::Map norm1,norm2
lyndond 94b5ff3
clean up tests
lyndond 1b991ad
rebase
lyndond fc9d2ad
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot fe3be43
reduce redundancy by using apply_vector_unary
lyndond 2d234bb
Merge branch 'l1_l2_norms' of https://github.com/lyndond/math into l1…
lyndond a7aaa48
cpplint
lyndond 9b3c93d
change dot_self.hpp back bc no longer used in norms
lyndond dfc9a8a
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot 8e70232
Revert "[Jenkins] auto-formatting by clang-format version 6.0.0-1ubun…
lyndond 1b3ffc9
add require_not_st_var to prim funs to fix rev tests
lyndond 665d254
Merge commit 'a43562ea29ef1bb892cb7942787d682f002dfc7c' into HEAD
yashikno ce03d8b
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot b745142
fix broken var in norm2
lyndond 100eb4c
remove unnecessary includes
lyndond 19e4736
commit suggestions by @andrjohns
lyndond fcbe661
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot 7adbc75
added forward-mode specializations
lyndond 18bee81
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot d731ef2
template argument fix
lyndond 548bccf
Merge branch 'l1_l2_norms' of https://github.com/lyndond/math into l1…
lyndond 61fc4ab
forward specializations
lyndond 238420e
require_st_arithmetic for prim functions
lyndond 535f0cb
replace omitted require_container_t
lyndond File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#ifndef STAN_MATH_FWD_FUN_NORM1_HPP | ||
#define STAN_MATH_FWD_FUN_NORM1_HPP | ||
|
||
#include <stan/math/fwd/meta.hpp> | ||
#include <stan/math/fwd/core.hpp> | ||
#include <stan/math/prim/meta.hpp> | ||
#include <stan/math/prim/fun/Eigen.hpp> | ||
#include <stan/math/prim/fun/constants.hpp> | ||
#include <stan/math/prim/fun/norm1.hpp> | ||
#include <stan/math/prim/fun/sign.hpp> | ||
#include <stan/math/prim/fun/to_ref.hpp> | ||
|
||
namespace stan { | ||
namespace math { | ||
|
||
/** | ||
* Compute the L1 norm of the specified vector of values. | ||
* | ||
* @tparam T Type of input vector. | ||
* @param[in] x Vector of specified values. | ||
* @return L1 norm of x. | ||
*/ | ||
template <typename Container, | ||
require_container_st<is_fvar, Container>* = nullptr> | ||
inline auto norm1(const Container& x) { | ||
return apply_vector_unary<ref_type_t<Container>>::reduce( | ||
to_ref(x), [&](const auto& v) { | ||
using T_fvar_inner = typename value_type_t<decltype(v)>::Scalar; | ||
return fvar<T_fvar_inner>(norm1(v.val()), | ||
v.d().cwiseProduct(sign(v.val())).sum()); | ||
}); | ||
} | ||
|
||
} // namespace math | ||
} // namespace stan | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#ifndef STAN_MATH_FWD_FUN_NORM2_HPP | ||
#define STAN_MATH_FWD_FUN_NORM2_HPP | ||
|
||
#include <stan/math/fwd/meta.hpp> | ||
#include <stan/math/fwd/core.hpp> | ||
#include <stan/math/prim/meta.hpp> | ||
#include <stan/math/prim/fun/Eigen.hpp> | ||
#include <stan/math/prim/fun/norm2.hpp> | ||
#include <stan/math/prim/fun/to_ref.hpp> | ||
|
||
namespace stan { | ||
namespace math { | ||
|
||
/** | ||
* Compute the L2 norm of the specified vector of values. | ||
* | ||
* @tparam T Type of input vector. | ||
* @param[in] x Vector of specified values. | ||
* @return L2 norm of x. | ||
*/ | ||
template <typename Container, | ||
require_container_st<is_fvar, Container>* = nullptr> | ||
inline auto norm2(const Container& x) { | ||
return apply_vector_unary<ref_type_t<Container>>::reduce( | ||
to_ref(x), [&](const auto& v) { | ||
using T_fvar_inner = typename value_type_t<decltype(v)>::Scalar; | ||
T_fvar_inner res = norm2(v.val()); | ||
return fvar<T_fvar_inner>(res, | ||
v.d().cwiseProduct((v.val() / res)).sum()); | ||
}); | ||
} | ||
|
||
} // namespace math | ||
} // namespace stan | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#ifndef STAN_MATH_PRIM_FUN_NORM1_HPP | ||
#define STAN_MATH_PRIM_FUN_NORM1_HPP | ||
|
||
#include <stan/math/prim/meta.hpp> | ||
#include <stan/math/prim/err.hpp> | ||
#include <stan/math/prim/fun/Eigen.hpp> | ||
|
||
namespace stan { | ||
namespace math { | ||
|
||
/** | ||
* Returns L1 norm of a vector. For vectors that equals the | ||
* sum of magnitudes of its individual elements. | ||
* | ||
* @tparam T type of the vector (must be derived from \c Eigen::MatrixBase) | ||
* @param v Vector. | ||
* @return L1 norm of v. | ||
*/ | ||
template <typename Container, require_container_t<Container>* = nullptr, | ||
require_not_st_var<Container>* = nullptr, | ||
require_not_st_fvar<Container>* = nullptr> | ||
inline auto norm1(const Container& x) { | ||
return apply_vector_unary<ref_type_t<Container>>::reduce( | ||
to_ref(x), [](const auto& v) { return v.template lpNorm<1>(); }); | ||
} | ||
|
||
} // namespace math | ||
} // namespace stan | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#ifndef STAN_MATH_PRIM_FUN_NORM2_HPP | ||
#define STAN_MATH_PRIM_FUN_NORM2_HPP | ||
|
||
#include <stan/math/prim/meta.hpp> | ||
#include <stan/math/prim/err.hpp> | ||
#include <stan/math/prim/fun/Eigen.hpp> | ||
|
||
namespace stan { | ||
namespace math { | ||
|
||
/** | ||
* Returns L2 norm of a vector. For vectors that equals the square-root of the | ||
* sum of squares of the elements. | ||
* | ||
* @tparam T type of the vector (must be derived from \c Eigen::MatrixBase) | ||
* @param v Vector. | ||
* @return L2 norm of v. | ||
*/ | ||
template <typename Container, require_container_t<Container>* = nullptr, | ||
require_not_st_var<Container>* = nullptr, | ||
require_not_st_fvar<Container>* = nullptr> | ||
inline auto norm2(const Container& x) { | ||
return apply_vector_unary<ref_type_t<Container>>::reduce( | ||
to_ref(x), [](const auto& v) { return v.template lpNorm<2>(); }); | ||
} | ||
|
||
} // namespace math | ||
} // namespace stan | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
#ifndef STAN_MATH_REV_FUN_NORM1_HPP | ||
#define STAN_MATH_REV_FUN_NORM1_HPP | ||
|
||
#include <stan/math/rev/meta.hpp> | ||
#include <stan/math/rev/core.hpp> | ||
#include <stan/math/rev/core/typedefs.hpp> | ||
#include <stan/math/prim/err.hpp> | ||
#include <stan/math/prim/fun/Eigen.hpp> | ||
#include <stan/math/prim/fun/sign.hpp> | ||
|
||
namespace stan { | ||
namespace math { | ||
|
||
/** | ||
* Returns the L1 norm of a vector of var. | ||
* | ||
* @tparam T type of the vector (must have one compile-time dimension equal to | ||
* 1) | ||
* @param[in] v Vector. | ||
* @return L1 norm of v. | ||
*/ | ||
template <typename T, require_eigen_vector_vt<is_var, T>* = nullptr> | ||
inline var norm1(const T& v) { | ||
arena_t<T> arena_v = v; | ||
var res = norm1(arena_v.val()); | ||
reverse_pass_callback([res, arena_v]() mutable { | ||
arena_v.adj().array() += res.adj() * sign(arena_v.val().array()); | ||
}); | ||
return res; | ||
} | ||
|
||
/** | ||
* Returns the L1 norm of a `var_value<Vector>`. | ||
* | ||
* @tparam A `var_value<>` whose inner type has one compile-time row or column. | ||
* @param[in] v Vector. | ||
* @return L1 norm of v. | ||
*/ | ||
// | ||
template <typename T, require_var_matrix_t<T>* = nullptr> | ||
inline var norm1(const T& v) { | ||
return make_callback_vari(norm1(v.val()), [v](const auto& res) mutable { | ||
v.adj().array() += res.adj() * sign(v.val().array()); | ||
}); | ||
} | ||
|
||
} // namespace math | ||
} // namespace stan | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#ifndef STAN_MATH_REV_FUN_NORM2_HPP | ||
#define STAN_MATH_REV_FUN_NORM2_HPP | ||
|
||
#include <stan/math/rev/meta.hpp> | ||
#include <stan/math/rev/core.hpp> | ||
#include <stan/math/rev/core/typedefs.hpp> | ||
#include <stan/math/prim/err.hpp> | ||
#include <stan/math/prim/fun/Eigen.hpp> | ||
|
||
namespace stan { | ||
namespace math { | ||
|
||
/** | ||
andrjohns marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* Returns the L2 norm of a vector of var. | ||
* | ||
* @tparam T type of the vector (must have one compile-time dimension equal to | ||
* 1) | ||
* @param[in] v Vector. | ||
* @return L2 norm of v. | ||
*/ | ||
template <typename T, require_eigen_vector_vt<is_var, T>* = nullptr> | ||
inline var norm2(const T& v) { | ||
arena_t<T> arena_v = v; | ||
var res = norm2(arena_v.val()); | ||
reverse_pass_callback([res, arena_v]() mutable { | ||
arena_v.adj().array() += res.adj() * (arena_v.val().array() / res.val()); | ||
}); | ||
return res; | ||
} | ||
|
||
/** | ||
* Returns the L2 norm of a `var_value<Vector>`. | ||
* | ||
* @tparam A `var_value<>` whose inner type has one compile-time row or column. | ||
* @param[in] v Vector. | ||
* @return L2 norm of v. | ||
*/ | ||
template <typename T, require_var_matrix_t<T>* = nullptr> | ||
inline var norm2(const T& v) { | ||
return make_callback_vari(norm2(v.val()), [v](const auto& res) mutable { | ||
v.adj().array() += res.adj() * (v.val().array() / res.val()); | ||
}); | ||
} | ||
|
||
} // namespace math | ||
} // namespace stan | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#include <test/unit/math/test_ad.hpp> | ||
#include <vector> | ||
|
||
TEST(MathMixMatFun, norm1) { | ||
auto f = [](const auto& y) { return stan::math::norm1(y); }; | ||
|
||
Eigen::VectorXd x0(0); | ||
|
||
Eigen::VectorXd x1(1); | ||
x1 << 2; | ||
|
||
Eigen::VectorXd x2(2); | ||
x2 << 2, 3; | ||
|
||
Eigen::VectorXd x3(3); | ||
x3 << 2, 3, 4; | ||
|
||
for (const auto& a : std::vector<Eigen::VectorXd>{x0, x1, x2, x3}) { | ||
stan::test::expect_ad(f, a); | ||
stan::test::expect_ad_matvar(f, a); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#include <test/unit/math/test_ad.hpp> | ||
#include <vector> | ||
|
||
TEST(MathMixMatFun, norm2) { | ||
auto f = [](const auto& y) { return stan::math::norm2(y); }; | ||
|
||
Eigen::VectorXd x0(0); | ||
|
||
Eigen::VectorXd x1(1); | ||
x1 << 2; | ||
|
||
Eigen::VectorXd x2(2); | ||
x2 << 2, 3; | ||
|
||
Eigen::VectorXd x3(3); | ||
x3 << 2, 3, 4; | ||
|
||
for (const auto& a : std::vector<Eigen::VectorXd>{x0, x1, x2, x3}) { | ||
stan::test::expect_ad(f, a); | ||
stan::test::expect_ad_matvar(f, a); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
#include <stan/math/prim.hpp> | ||
#include <gtest/gtest.h> | ||
#include <cmath> | ||
#include <limits> | ||
#include <vector> | ||
|
||
TEST(MathFunctions, norm1) { | ||
std::vector<double> x(3), y(3); | ||
x[0] = 2.33; | ||
x[1] = 8.88; | ||
x[2] = 9.81; | ||
y[0] = 2.46; | ||
y[1] = 4.45; | ||
y[2] = 1.03; | ||
|
||
EXPECT_FLOAT_EQ(21.02, stan::math::norm1(x)); | ||
EXPECT_FLOAT_EQ(7.94, stan::math::norm1(y)); | ||
} | ||
|
||
TEST(MathFunctions, norm1_nan) { | ||
std::vector<double> x(3); | ||
x[0] = 2.33; | ||
x[1] = 8.88; | ||
x[2] = 9.81; | ||
|
||
double nan = std::numeric_limits<double>::quiet_NaN(); | ||
x[2] = nan; | ||
|
||
EXPECT_TRUE(std::isnan(stan::math::norm1(x))); | ||
|
||
x[0] = nan; | ||
x[1] = nan; | ||
x[2] = nan; | ||
EXPECT_TRUE(std::isnan(stan::math::norm1(x))); | ||
} | ||
|
||
TEST(MathMatrixPrimMat, norm1) { | ||
using stan::math::norm1; | ||
|
||
Eigen::Matrix<double, Eigen::Dynamic, 1> v1(1); | ||
v1 << 2.0; | ||
EXPECT_NEAR(2.0, norm1(v1), 1E-12); | ||
Eigen::Matrix<double, Eigen::Dynamic, 1> v2(2); | ||
v2 << 2.0, 3.0; | ||
EXPECT_NEAR(5.0, norm1(v2), 1E-12); | ||
Eigen::Matrix<double, Eigen::Dynamic, 1> v3(3); | ||
v3 << 2.0, 3.0, 4.0; | ||
EXPECT_NEAR(9.0, norm1(v3), 1E-12); | ||
|
||
Eigen::Matrix<double, 1, Eigen::Dynamic> rv1(1); | ||
rv1 << 2.0; | ||
EXPECT_NEAR(2.0, norm1(rv1), 1E-12); | ||
Eigen::Matrix<double, 1, Eigen::Dynamic> rv2(2); | ||
rv2 << 2.0, 3.0; | ||
EXPECT_NEAR(5.0, norm1(rv2), 1E-12); | ||
Eigen::Matrix<double, 1, Eigen::Dynamic> rv3(3); | ||
rv3 << 2.0, 3.0, 4.0; | ||
EXPECT_NEAR(9.0, norm1(rv3), 1E-12); | ||
|
||
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> m1(1, 1); | ||
m1 << 2.0; | ||
EXPECT_NEAR(2.0, norm1(m1), 1E-12); | ||
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> m2(2, 1); | ||
m2 << 2.0, 3.0; | ||
EXPECT_NEAR(5.0, norm1(m2), 1E-12); | ||
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> m3(3, 1); | ||
m3 << 2.0, 3.0, 4.0; | ||
EXPECT_NEAR(9.0, norm1(m3), 1E-12); | ||
|
||
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> mm2(1, 2); | ||
mm2 << 2.0, 3.0; | ||
EXPECT_NEAR(5.0, norm1(mm2), 1E-12); | ||
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> mm3(1, 3); | ||
mm3 << 2.0, 3.0, 4.0; | ||
EXPECT_NEAR(9.0, norm1(mm3), 1E-12); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These templates can be a little stricter by specifying that they're only for arithmetic types, see the
log_softmax
header for an exampleThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, I changed the templates to include
require_st_arithmetic<>
to match the template oflog_softmax
.Does
require_st_arithmetic<>
do the job of bothrequire_not_st_var<>
andrequire_not_st_fvar<>
? These are what I used to resolve ambiguity betweenprim
vsrev
andprim
vsfwd
, respectively.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, it will restrict to only matching inputs that satisfy
std::is_arithmetic