{"action":"created","issue":{"url":"https://api.github.com/repos/stan-dev/stan/issues/1369","labels_url":"https://api.github.com/repos/stan-dev/stan/issues/1369/labels{/name}","comments_url":"https://api.github.com/repos/stan-dev/stan/issues/1369/comments","events_url":"https://api.github.com/repos/stan-dev/stan/issues/1369/events","html_url":"https://github.com/stan-dev/stan/issues/1369","id":61394221,"number":1369,"title":"ragged array assignment (not declaration)","user":{"login":"bob-carpenter","id":3383807,"avatar_url":"https://avatars.githubusercontent.com/u/3383807?v=3","gravatar_id":"","url":"https://api.github.com/users/bob-carpenter","html_url":"https://github.com/bob-carpenter","followers_url":"https://api.github.com/users/bob-carpenter/followers","following_url":"https://api.github.com/users/bob-carpenter/following{/other_user}","gists_url":"https://api.github.com/users/bob-carpenter/gists{/gist_id}","starred_url":"https://api.github.com/users/bob-carpenter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bob-carpenter/subscriptions","organizations_url":"https://api.github.com/users/bob-carpenter/orgs","repos_url":"https://api.github.com/users/bob-carpenter/repos","events_url":"https://api.github.com/users/bob-carpenter/events{/privacy}","received_events_url":"https://api.github.com/users/bob-carpenter/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/stan-dev/stan/labels/Feature","name":"Feature","color":"84b6eb"},{"url":"https://api.github.com/repos/stan-dev/stan/labels/language","name":"language","color":"d4c5f9"}],"state":"open","locked":false,"assignee":{"login":"bob-carpenter","id":3383807,"avatar_url":"https://avatars.githubusercontent.com/u/3383807?v=3","gravatar_id":"","url":"https://api.github.com/users/bob-carpenter","html_url":"https://github.com/bob-carpenter","followers_url":"https://api.github.com/users/bob-carpenter/followers","following_url":"https://api.github.com/users/bob-carpenter/following{/other_user}","gists_url":"https://api.github.com/users/bob-carpenter/gists{/gist_id}","starred_url":"https://api.github.com/users/bob-carpenter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bob-carpenter/subscriptions","organizations_url":"https://api.github.com/users/bob-carpenter/orgs","repos_url":"https://api.github.com/users/bob-carpenter/repos","events_url":"https://api.github.com/users/bob-carpenter/events{/privacy}","received_events_url":"https://api.github.com/users/bob-carpenter/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/stan-dev/stan/milestones/2","html_url":"https://github.com/stan-dev/stan/milestones/Future","labels_url":"https://api.github.com/repos/stan-dev/stan/milestones/2/labels","id":341383,"number":2,"title":"Future","description":"For tasks and features not scheduled for the next release.","creator":{"login":"bob-carpenter","id":3383807,"avatar_url":"https://avatars.githubusercontent.com/u/3383807?v=3","gravatar_id":"","url":"https://api.github.com/users/bob-carpenter","html_url":"https://github.com/bob-carpenter","followers_url":"https://api.github.com/users/bob-carpenter/followers","following_url":"https://api.github.com/users/bob-carpenter/following{/other_user}","gists_url":"https://api.github.com/users/bob-carpenter/gists{/gist_id}","starred_url":"https://api.github.com/users/bob-carpenter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bob-carpenter/subscriptions","organizations_url":"https://api.github.com/users/bob-carpenter/orgs","repos_url":"https://api.github.com/users/bob-carpenter/repos","events_url":"https://api.github.com/users/bob-carpenter/events{/privacy}","received_events_url":"https://api.github.com/users/bob-carpenter/received_events","type":"User","site_admin":false},"open_issues":164,"closed_issues":3,"state":"open","created_at":"2013-05-24T19:02:14Z","updated_at":"2015-03-25T23:28:36Z","due_on":null,"closed_at":null},"comments":30,"created_at":"2015-03-14T03:59:14Z","updated_at":"2015-03-26T02:56:11Z","closed_at":null,"body":"From Ben Goodrich on stan-dev:\r\n\r\nOK. I invented a new rule (locally): You are allowed to assign anything to a matrix with 0 rows and 0 columns. So, this now works:\r\n\r\n```\r\nmodel {\r\n  matrix[0,0] X[2];\r\n  vector[4] ones;\r\n  ones[1] <- 1;\r\n  ones[2] <- 1;\r\n  ones[3] <- 1;\r\n  ones[4] <- 1;\r\n  X[1] <- diag_matrix(ones);\r\n  theta ~ normal(0,1);\r\n}\r\n```\r\n\r\nBut it would probably be better to support (outside of the data and parameters blocks)\r\n\r\n```\r\nmatrix X[2]; \r\n// parse to vector<Eigen::Matrix<T__,Eigen::Dynamic,Eigen::Dynamic> > X(2);\r\n// i.e. no fill value after the 2\r\n```\r\n\r\nrather than making users declare\r\n\r\n```\r\nmatrix[0,0] X[2];\r\n```\r\n\r\nI think we're good in that case in the sense that this runs so I guess the column vector gets promoted:\r\n\r\n```\r\n#include <vector>\r\n#include <Eigen/Dense>\r\n\r\nint main() {\r\n  std::vector<Eigen::Matrixd> > x(2);\r\n  Eigen::MatrixXd m(2,2);\r\n  m(0,0) = 3;\r\n  m(1,0) = 2.5;\r\n  m(0,1) = -1;\r\n  m(1,1) = m(1,0) + m(0,1);\r\n  x[0] = m;\r\n  x[1] = m.col(1);\r\n  return 0;\r\n}\r\n```\r\n\r\nHowever, the comment in `src/stan/math/prim/mat/fun/assign.hpp` does not seem to match what the code does. I had to do trial and error to figure out that this was being called rather than the one above it that allegedly fires when the dimensions do not match. \r\n\r\n```\r\n/** \r\n * Copy the right-hand side's value to the left-hand side \r\n * variable. \r\n * \r\n * The <code>assign()</code> function is overloaded.  This \r\n * instance will be called for arguments that are both \r\n * <code>Eigen::Matrix</code> types and whose shapes match.  The \r\n * shapes are specified in the row and column template parameters. \r\n * \r\n * @tparam LHS Type of left-hand side matrix elements. \r\n * @tparam RHS Type of right-hand side matrix elements. \r\n * @tparam R Row shape of both matrices. \r\n * @tparam C Column shape of both mtarices. \r\n * @param x Left-hand side matrix. \r\n * @param y Right-hand side matrix. \r\n * @throw std::invalid_argument if sizes do not match. \r\n */ \r\ntemplate <typename LHS, typename RHS, int R, int C> \r\ninline void \r\nassign(Eigen::Matrix<LHS,R,C>& x, \r\n       const Eigen::Matrix<RHS,R,C>& y) { \r\n  if(x.rows() == 0 && x.cols() == 0) { \r\n    x = y; \r\n    return ; \r\n  } \r\n  stan::math::check_matching_dims(\"assign\", \r\n                                            \"x\", x, \r\n                                            \"y\", y); \r\n  for (int i = 0; i < x.size(); ++i) \r\n    assign(x(i),y(i)); \r\n} \r\n```"},"comment":{"url":"https://api.github.com/repos/stan-dev/stan/issues/comments/86312910","html_url":"https://github.com/stan-dev/stan/issues/1369#issuecomment-86312910","issue_url":"https://api.github.com/repos/stan-dev/stan/issues/1369","id":86312910,"user":{"login":"bgoodri","id":3386282,"avatar_url":"https://avatars.githubusercontent.com/u/3386282?v=3","gravatar_id":"","url":"https://api.github.com/users/bgoodri","html_url":"https://github.com/bgoodri","followers_url":"https://api.github.com/users/bgoodri/followers","following_url":"https://api.github.com/users/bgoodri/following{/other_user}","gists_url":"https://api.github.com/users/bgoodri/gists{/gist_id}","starred_url":"https://api.github.com/users/bgoodri/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bgoodri/subscriptions","organizations_url":"https://api.github.com/users/bgoodri/orgs","repos_url":"https://api.github.com/users/bgoodri/repos","events_url":"https://api.github.com/users/bgoodri/events{/privacy}","received_events_url":"https://api.github.com/users/bgoodri/received_events","type":"User","site_admin":false},"created_at":"2015-03-26T02:56:11Z","updated_at":"2015-03-26T02:56:11Z","body":"On Wed, Mar 25, 2015 at 10:21 PM, Bob Carpenter <notifications@github.com>\nwrote:\n\n> > And if the \"best\" thing to do is to do something that is inconsistent\n> with\n> > one of the central tenets of programming, then the design has a problem.\n>\n> Agreed. This seems like a problem with our enforcing positive\n> definiteness.\n>\n> > This problem could be solved by disabling the positive definiteness check\n> > and the matrix resizing issue could be solved by disabling the size\n> check.\n>\n> Where would it be OK to use a correlation matrix that doesn't pass\n> positive-definiteness checks? Shouldn't it then just be declared\n> as a matrix?\n>\n\nIt is a dilemma that is self-inflicted by the user who writes\ntransformations that are not consistent with the constraints by\nconstruction.\n\n   - If someone passes an indefinite symmetric matrix to a function like\n   multi_normal, then any number multi_normal() outputs is not sound\n   (hopefully it would throw an exception or return NaN).\n   - If someone passes only the symmetric matrices that pass the positive\n   definiteness check to a function like multi_normal, then multi_normal won't\n   throw an exception or return NaN but the draws are not sound. Basically,\n   the user should be truncating the relevant priors by dividing them by the\n   non-constant 1 - Pr(indefinite) but there is no way to do that truncation\n   in Stan.\n\nSo, the only way to get sound posterior draws is to only use\ntransformations that are positive definite with probability one. And if do\nthat, then you don't want to check for positive definiteness at runtime in\nproduction code both because it is slower and also because you can get\npositive definite matrices that are numerically indefinite.\n\nFor positive definiteness, there are ways of circumventing the check by\njust declaring it as a plain square matrix. But the larger point I am\ntrying to make is that requiring everything to be checked for validity\nhurts people who write valid code in order to prevent people who write\ninvalid code from hurting themselves. In the original case of size checking\nmatrices, there is virtually no runtime cost but the cost is that we can't\nresize them and we can't implement C++ or user-defined functions that\nreturn multiple matrices of different sizes. So Sebastian can't do things\nlike\n\ntransformed parameters {\n  matrix my_stuff[P];\n  my_stuff <- make_stuff(lots, of, arguments); // for a user-defined\nmake_stuff\n}\n\nand export that single make_stuff function to R to use in posterior\npredictive simulations. But it is really the principle that everyone has to\nsuffer in order to catch someone else's typos that bothers me.\n\nBen\n"}}