Skip to content

cov_matrix_free accepts indefinite matrices and silently returns an unconstrained vector for a different matrix #3379

Description

@sims1253

cov_matrix_free checks squareness and a positive diagonal but never checks that the LLT factorization succeeded. An indefinite matrix with positive diagonal is accepted, and the returned vector does not round-trip:

Eigen::MatrixXd S(2, 2);
S << 1, 2, 2, 1;                        // indefinite, positive diagonal
Eigen::VectorXd z = stan::math::cov_matrix_free(S);   // no throw
// z = [0, 2, 0]
Eigen::MatrixXd back = stan::math::cov_matrix_constrain(z, 2);
// back = [[1, 2], [2, 5]]  — a different matrix than the input

The sibling cov_matrix_free_lkj does check the factorization and throws on the same input (LLT factorization failed), so the guard pattern already exists in the codebase.

This is reachable from user code through the unconstraining path (e.g. CmdStan's unconstrain with bad inits): invalid input silently produces a wrong unconstrained parameter vector instead of an error.

Check llt.info() like cov_matrix_free_lkj does is probably the only thing needed.

Environment:

  • Ubuntu 22.04.5 LTS (WSL2, kernel 6.18.33.2-microsoft-standard-WSL2), x86_64
  • stan-dev/math develop @ d20b238
  • g++ 11.4.0 (Ubuntu 22.04), -std=c++17

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions