Skip to content

Commit 859f2c8

Browse files
committed
Skeleton of rev
1 parent fb463df commit 859f2c8

3 files changed

Lines changed: 49 additions & 5 deletions

File tree

stan/math/prim/constraint/sum_to_zero_constrain.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ inline plain_type_t<Mat> sum_to_zero_constrain(const Mat& x) {
8383
}
8484
auto&& x_ref = to_ref(x);
8585

86-
Eigen::VectorXd beta = Eigen::VectorXd::Zero(N);
86+
Eigen::Matrix<value_type_t<Mat>, -1, 1> beta = Eigen::VectorXd::Zero(N);
8787

8888
for (int j = M - 1; j >= 0; --j) {
8989
value_type_t<Mat> ax_previous(0);

stan/math/rev/constraint/sum_to_zero_constrain.hpp

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,34 @@ inline auto sum_to_zero_constrain(T&& y) {
6969
return arena_z;
7070
}
7171

72+
/**
73+
* Return a matrix that sums to zero over both the rows
74+
* and columns corresponding to the free matrix x.
75+
*
76+
* This is a linear transform, with no Jacobian.
77+
*
78+
* @tparam Mat type of the matrix
79+
* @param x Free matrix input of dimensionality (N - 1, M - 1).
80+
* @return Zero-sum matrix of dimensionality (N, M).
81+
*/
82+
template <typename T, require_rev_matrix_t<T>* = nullptr,
83+
require_not_t<is_rev_vector<T>>* = nullptr>
84+
inline auto sum_to_zero_constrain(T&& x) {
85+
using ret_type = plain_type_t<T>;
86+
if (unlikely(x.size() == 0)) {
87+
return arena_t<ret_type>(Eigen::MatrixXd{{0}});
88+
}
89+
auto arena_x = to_arena(std::forward<T>(x));
90+
arena_t<ret_type> arena_z = sum_to_zero_constrain(arena_x.val());
91+
92+
reverse_pass_callback([arena_x, arena_z]() mutable {
93+
const auto N = arena_x.rows();
94+
const auto M = arena_x.cols();
95+
});
96+
97+
return arena_z;
98+
}
99+
72100
/**
73101
* Return a vector with sum zero corresponding to the specified
74102
* free vector.
@@ -89,12 +117,12 @@ inline auto sum_to_zero_constrain(T&& y) {
89117
*
90118
* This is a linear transform, with no Jacobian.
91119
*
92-
* @tparam Vec type of the vector
93-
* @param y Free vector input of dimensionality K - 1.
120+
* @tparam T type of the vector or matrix
121+
* @param y Free vector or matrix.
94122
* @param lp unused
95-
* @return Zero-sum vector of dimensionality K.
123+
* @return Zero-sum vector or matrix which is one larger in each dimension
96124
*/
97-
template <typename T, typename Lp, require_rev_col_vector_t<T>* = nullptr>
125+
template <typename T, typename Lp, is_rev_matrix<T>* = nullptr>
98126
inline auto sum_to_zero_constrain(T&& y, Lp& lp) {
99127
return sum_to_zero_constrain(std::forward<T>(y));
100128
}

test/unit/math/mix/constraint/sum_to_zero_constrain_test.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,20 @@ TEST(MathMixMatFun, sum_to_zeroTransform) {
5555
Eigen::VectorXd v5(5);
5656
v5 << 1, -3, 2, 0, -1;
5757
sum_to_zero_constrain_test::expect_sum_to_zero_transform(v5);
58+
59+
Eigen::MatrixXd m0_0(0, 0);
60+
sum_to_zero_constrain_test::expect_sum_to_zero_transform(m0_0);
61+
62+
Eigen::MatrixXd m1_1(1, 1);
63+
m1_1 << 1;
64+
sum_to_zero_constrain_test::expect_sum_to_zero_transform(m1_1);
65+
66+
Eigen::MatrixXd m2_2(2, 2);
67+
m2_2 << 1, 2, -3, 4;
68+
sum_to_zero_constrain_test::expect_sum_to_zero_transform(m2_2);
69+
70+
Eigen::MatrixXd m3_4(3, 4);
71+
m3_4 << 1, 2, -3, 4, 5, 6, -7, 8, 9, -10, 11, -12;
72+
73+
sum_to_zero_constrain_test::expect_sum_to_zero_transform(m3_4);
5874
}

0 commit comments

Comments
 (0)