## ----setup, include=FALSE-----------------------------------------------------
knitr::opts_chunk$set(echo = FALSE, message = FALSE, warning = FALSE)

## ----c4bis-fail-illustrative, eval=FALSE--------------------------------------
# library(gdpar)
# 
# set.seed(42L)
# df <- data.frame(x1 = rnorm(100L), x2 = rnorm(100L))
# df$y <- cbind(rnorm(100L), rnorm(100L))
# 
# spec_overlap <- amm_spec(
#   p      = 2L,
#   dims   = dimwise(a = ~ x1 + x2),
#   W      = W_basis(type = "polynomial", degree = 2),
#   x_vars = c("x1", "x2")          # overlap: x1 and x2 appear in both a and W
# )
# 
# # rigor = "full" (default): the check FAILS structurally before sampling.
# rep <- gdpar_check_identifiability(
#   amm = spec_overlap, data = df, rigor = "full"
# )
# rep$passed
# # [1] FALSE
# rep$c4_bis$per_k[[1L]]$shared_cols
# # [1] "x1" "x2"
# rep$c4_bis$per_k[[2L]]$shared_cols
# # [1] "x1" "x2"
# print(rep)
# # <gdpar_identifiability_report>
# #   passed             : FALSE
# #   ...
# #   C4-bis (per-coordinate cross-component):
# #     coord 1 (rigor=full) passed=FALSE cond=... shared_cols={x1,x2}
# #       ...
# #     coord 2 (rigor=full) passed=FALSE cond=... shared_cols={x1,x2}
# #       ...

## ----c4bis-fail-gdpar-illustrative, eval=FALSE--------------------------------
# fit <- tryCatch(
#   gdpar(y ~ x1 + x2, family = gdpar_family_multi("gaussian", p = 2L),
#         amm = spec_overlap, data = df),
#   gdpar_identifiability_error = function(e) e
# )
# # fit is the captured condition; fit$data$report has the same c4_bis breakdown.

## ----c4bis-pass-illustrative, eval=FALSE--------------------------------------
# df3 <- data.frame(
#   x1 = rnorm(100L),
#   x2 = rnorm(100L),
#   z1 = rnorm(100L),
#   z2 = rnorm(100L)
# )
# df3$y <- cbind(rnorm(100L), rnorm(100L))
# 
# spec_disjoint <- amm_spec(
#   p      = 2L,
#   dims   = dimwise(a = NULL) |>
#              override(k = 1L, a = ~ z1) |>
#              override(k = 2L, a = ~ z2),
#   W      = W_basis(type = "polynomial", degree = 2),
#   x_vars = c("x1", "x2")          # disjoint from {z1, z2}
# )
# 
# rep <- gdpar_check_identifiability(
#   amm = spec_disjoint, data = df3, rigor = "full"
# )
# rep$passed
# # [1] TRUE
# rep$c4_bis$per_k[[1L]]$shared_cols
# # character(0)
# rep$c4_bis$per_k[[2L]]$shared_cols
# # character(0)

## ----c7_example_fails, eval=FALSE---------------------------------------------
# set.seed(13L)
# n_per_group <- 20L; J <- 3L
# n <- n_per_group * J
# df <- data.frame(
#   x1 = rnorm(n),
#   group = factor(rep(letters[seq_len(J)], each = n_per_group))
# )
# df$y <- 0.4 * df$x1 +
#   rep(rnorm(J, sd = 1.5), each = n_per_group) +
#   rnorm(n, sd = 0.3)
# 
# spec <- amm_spec(a = ~ x1 + group)
# fit <- gdpar(
#   formula = y ~ x1 + group,
#   amm     = spec,
#   data    = df,
#   group   = ~ group,
#   chains  = 1L, iter_warmup = 50L, iter_sampling = 50L,
#   refresh = 0L, verbose = FALSE
# )
# # Aborts with either:
# #   - gdpar_identifiability_error (Block 1 catches the direct rank-deficiency), or
# #   - gdpar_input_error (C7 catches the residual aliasing).

## ----c7_example_const, eval=FALSE---------------------------------------------
# set.seed(13L)
# n_per_group <- 20L; J <- 3L
# n <- n_per_group * J
# df <- data.frame(
#   x1    = rnorm(n),
#   group = factor(rep(letters[seq_len(J)], each = n_per_group))
# )
# # z_const is a deterministic function of group (constant per group):
# df$z_const <- as.numeric(df$group)
# df$y <- 0.4 * df$x1 +
#   rep(rnorm(J, sd = 1.5), each = n_per_group) +
#   rnorm(n, sd = 0.3)
# 
# spec <- amm_spec(a = ~ x1, b = ~ z_const)
# fit <- gdpar(
#   formula = y ~ x1 + z_const,
#   amm     = spec,
#   data    = df,
#   group   = ~ group,
#   chains  = 1L, iter_warmup = 50L, iter_sampling = 50L,
#   refresh = 0L, verbose = FALSE
# )
# # Aborts with gdpar_input_error citing (C7) and naming the aliased column.
# # Remove z_const (or any deterministic function of group) from b, or
# # fit without the group argument.

