% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/tmpinv.R
\name{tmpinv}
\alias{tmpinv}
\title{Solve a tabular matrix estimation problem via Convex Least Squares
Programming (CLSP).}
\usage{
tmpinv(
  S = NULL,
  M = NULL,
  b_row = NULL,
  b_col = NULL,
  b_val = NULL,
  i = 1L,
  j = 1L,
  zero_diagonal = FALSE,
  reduced = NULL,
  symmetric = FALSE,
  bounds = NULL,
  replace_value = NA_real_,
  tolerance = sqrt(.Machine$double.eps),
  iteration_limit = 50L,
  r = 1L,
  final = TRUE,
  alpha = NULL,
  cond_tolerance = NULL,
  ...
)
}
\arguments{
\item{S}{numeric matrix of size \eqn{(m + p) \times (m + p)}, optional.
A diagonal sign-slack (surplus) matrix with entries in
\eqn{\{0, \pm 1\}}.
\itemize{
\item \code{0} enforces equality (== \code{b_row} or \code{b_col}),
\item \code{1} enforces a lower-than-or-equal (\eqn{\le}) condition,
\item \code{-1} enforces a greater-than-or-equal (\eqn{\ge}) condition.
The first \code{m} diagonal entries correspond to row constraints,
and the remaining \code{p} correspond to column constraints.
}}

\item{M}{numeric matrix of size \eqn{k \times (m p)}, optional.
A model matrix, typically with entries in \eqn{\{0,1\}}. Each row
defines a linear restriction on the flattened solution matrix.
The corresponding right-hand-side values must be supplied in
\code{b_val}. This block encodes known cell values.}

\item{b_row}{numeric vector of length \code{m}.
Right-hand-side vector of row totals.}

\item{b_col}{numeric vector of length \code{p}.
Right-hand-side vector of column totals.}

\item{b_val}{numeric vector of length \code{k}.
Right-hand-side vector of known cell values.}

\item{i}{integer, default = \code{1}.
Number of row groups.}

\item{j}{integer, default = \code{1}.
Number of column groups.}

\item{zero_diagonal}{logical scalar, default = \code{FALSE}.
If \code{TRUE}, enforces a structural zero diagonal.}

\item{reduced}{integer vector of length \code{2}, optional.
Dimensions of the reduced problem. If supplied, estimation is
performed block-wise on contiguous submatrices. For example,
\code{reduced = c(6,6)} yields \eqn{5 \times 5} blocks with one
slack row and one slack column (edge blocks may be smaller).}

\item{symmetric}{logical scalar, default = \code{FALSE}.
If TRUE, enforces symmetry of the estimated matrix via
\code{x <- 0.5 * (x + t(x))}. This applies to \code{tmpinv$x} only.
For symmetry in the model, add explicit symmetry rows to
\code{M} instead of using this flag.}

\item{bounds}{NULL, \code{numeric(2)}, or list of \code{numeric(2)}.
Bounds on cell values. If a single pair \code{c(low, high)} is
given, it is applied to all \eqn{m p} cells.
Example: \code{c(0, NA)}.}

\item{replace_value}{numeric scalar or \code{NA}, default = \code{NA}.
Final replacement value for any cell that violates the bounds by
more than the given tolerance.}

\item{tolerance}{numeric scalar, default = \code{sqrt(.Machine$double.eps)}.
Convergence tolerance for bounds.}

\item{iteration_limit}{integer, default = \code{50}.
Maximum number of iterations allowed in the refinement loop.}

\item{r}{integer scalar, default = \code{1}
Number of refinement iterations for the first step of the CLSP estimator.}

\item{final}{logical scalar, default = \code{TRUE}
If \code{FALSE}, only the first step of the CLSP estimator is performed.}

\item{alpha}{numeric scalar, numeric vector, or \code{NULL},
Regularization parameter for the second step of the CLSP estimator.}

\item{cond_tolerance}{numeric scalar or \code{NULL}, default = \code{NULL}
Singular-value cutoff for the custom condition number function.
If \code{NULL}, the implementation uses an internal relative cutoff of
1e-14.}

\item{...}{Additional arguments passed to the \pkg{rclsp} solver.}
}
\value{
An object of class \code{"tmpinv"} containing the fitted CLSP
model (\code{tmpinv$model}) and solution matrix (\code{tmpinv$x}).
}
\description{
Solve a tabular matrix estimation problem via Convex Least Squares
Programming (CLSP).
}
\note{
\enumerate{
\item In the reduced model, \code{S} is ignored. Slack behaviour is
inferred from block-wise marginal totals.
Likewise, \code{M} must be a unique row subset of an identity
matrix (diagonal-only). Non-diagonal model matrices cannot be
mapped into reduced blocks.
\item Internal keyword arguments \code{b_lim} and \code{C_lim} are
passed to \code{.tmpinv.instance()} and contain cell-value
bounds. These arguments are ignored in the reduced model.
}
}
\examples{
\donttest{
  ## Example 1: AP/TM reconstruction on a symmetric 20x20 matrix
  ## (10 percent known entries)

  RNGkind("L'Ecuyer-CMRG")
  set.seed(123456789)

  m <- 20L
  p <- 20L

  # sample (dataset)
  X_true <- abs(matrix(rnorm(m * p), nrow = m, ncol = p))
  X_true <- 0.5 * (X_true + t(X_true))              # symmetric

  idx <- sample.int(
      m * p,
      size = max(1L, floor(0.1 * (m * p))),         # 10 percent known
      replace = FALSE
  )

  M     <- diag(m * p)[idx, , drop = FALSE]
  b_row <- rowSums(X_true)
  b_col <- colSums(X_true)
  b_val <- matrix(as.numeric(X_true)[idx], ncol = 1L)

  # model (unique MNBLUE estimator)
  result <- tmpinv(
      M = M,
      b_row = b_row,
      b_col = b_col,
      b_val = b_val,
      bounds = c(0, NA),                            # non-negativity
      symmetric = TRUE,
      r = 1L,
      alpha = 1.0
  )

  # coefficients
  print("true X:")
  print(round(X_true, 4))

  print("X_hat:")
  print(round(result$x, 4))

  # numerical stability
  print("\nNumerical stability:")
  print(paste("  kappaC :", result$model$kappaC))
  print(paste("  kappaB :", result$model$kappaB))
  print(paste("  kappaA :", result$model$kappaA))

  # diagnostics
  print("\nGoodness-of-fit:")
  print(paste("  NRMSE :", result$model$nrmse))
  print(paste("  Diagnostic band (min):", min(result$model$x_lower)))
  print(paste("  Diagnostic band (max):", max(result$model$x_upper)))

  # bootstrap NRMSE t-test
  tt <- rclsp::ttest(
      result$model,
      sample_size = 30L,
      seed = 123456789L,
      distribution = rnorm,
      partial = TRUE
  )
  print("\nBootstrap t-test:")
  print(tt)

  ## Example 2: AP/TM reconstruction on a 40x40 matrix
  ## with zero diagonal and reduced (20,20) submodels
  ## (20 percent known entries)

  RNGkind("L'Ecuyer-CMRG")
  set.seed(123456789)

  m <- 40L
  p <- 40L

  # sample (dataset)
  X_true <- abs(matrix(rnorm(m * p), nrow = m, ncol = p))
  diag(X_true) <- 0                                 # zero diagonal

  idx <- sample.int(
      m * p,
      size = max(1L, floor(0.2 * (m * p))),         # 20 percent known
      replace = FALSE
  )

  M     <- diag(m * p)[idx, , drop = FALSE]
  b_row <- rowSums(X_true)
  b_col <- colSums(X_true)
  b_val <- matrix(as.numeric(X_true)[idx], ncol = 1L)

  # model (reduced models of size 20x20)
  result <- tmpinv(
      M = M,
      b_row = b_row,
      b_col = b_col,
      b_val = b_val,
      zero_diagonal = TRUE,
      reduced = c(20L, 20L),
      bounds = c(0, NA),
      r = 1L,
      alpha = 1.0
  )

  print("true X:")
  print(round(X_true, 4))

  print("X_hat:")
  print(round(result$x, 4))

  # numerical stability across submodels
  kC <- sapply(result$model, function(CLSP) CLSP$kappaC)
  kB <- sapply(result$model, function(CLSP) CLSP$kappaB)
  kA <- sapply(result$model, function(CLSP) CLSP$kappaA)

  print("\nNumerical stability (min-max across models):")
  print(paste("  kappaC :", range(kC)))
  print(paste("  kappaB :", range(kB)))
  print(paste("  kappaA :", range(kA)))

  # diagnostics (min-max)
  nrmse <- sapply(result$model, function(CLSP) CLSP$nrmse)
  x_low <- unlist(lapply(result$model, function(CLSP) CLSP$x_lower))
  x_up  <- unlist(lapply(result$model, function(CLSP) CLSP$x_upper))

  print("\nGoodness-of-fit (min-max across models):")
  print(paste("  NRMSE :", range(nrmse)))
  print(paste("  Diagnostic band (min):", range(x_low)))
  print(paste("  Diagnostic band (max):", range(x_up)))

  # bootstrap t-tests across all block models
  print("\nBootstrap t-tests:")
  tests <- lapply(
      result$model,
      function(CLSP) rclsp::ttest(
          CLSP,
          sample_size = 30L,
          seed = 123456789L,
          distribution = rnorm,
          partial = TRUE
      )
  )
  print(tests)
}

}
\seealso{
\link[rclsp]{clsp}

\link[CVXR]{CVXR-package}
}
