% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/tsqca_cts.R
\name{ctSweepM}
\alias{ctSweepM}
\title{MCTS–QCA: Multi-condition threshold sweep}
\usage{
ctSweepM(
  dat,
  outcome = NULL,
  conditions = NULL,
  sweep_list,
  thrY,
  thrX_default = NULL,
  pre_calibrated = NULL,
  dir.exp = NULL,
  include = "",
  incl.cut = 0.8,
  n.cut = 1,
  pri.cut = 0,
  extract_mode = c("first", "all", "essential"),
  return_details = TRUE,
  Yvar = NULL,
  Xvars = NULL
)
}
\arguments{
\item{dat}{Data frame containing the outcome and condition variables.}

\item{outcome}{Character. Outcome variable name. Supports negation with
tilde prefix (e.g., \code{"~Y"}) following QCA package conventions.}

\item{conditions}{Character vector. Names of condition variables.}

\item{sweep_list}{Named list. Each element is a numeric vector of
candidate thresholds for the corresponding X. Names must match
\code{conditions}. Variables listed in \code{pre_calibrated} do not
need a \code{sweep_list} entry. Every condition must receive a threshold
from one of \code{sweep_list}, \code{pre_calibrated}, or
\code{thrX_default}; a condition covered by none of these raises an
error. To hold a condition at a fixed value while sweeping others, give
it a length-one entry (e.g. \code{list(SPV = 6:8, PRD = 7)}).}

\item{thrY}{Numeric. Threshold for Y (fixed).}

\item{thrX_default}{Numeric or \code{NULL}. Threshold used to binarize any
condition that appears in neither \code{sweep_list} nor
\code{pre_calibrated}, mirroring the argument of the same name in
\code{\link{ctSweepS}}. Default is \code{NULL}, in which case such a
condition is an error rather than being silently dropped.}

\item{pre_calibrated}{Character vector or \code{NULL}. Names of condition
variables that have been pre-calibrated (e.g., via \code{QCA::calibrate()})
and should be passed through to \code{QCA::truthTable()} without
binarization. These variables must contain values in the \code{[0, 1]}
range. Variables not listed here will be binarized using \code{sweep_list}
thresholds as usual. Default is \code{NULL} (all variables binarized).
It is recommended to sweep variables on their original (raw) scale rather
than as pre-calibrated fuzzy values, because raw-scale thresholds are
easier to interpret substantively.}

\item{dir.exp}{Directional expectations for \code{minimize}.
If \code{NULL} (default), no directional expectations are applied.
To compute the \strong{intermediate solution}, specify a numeric vector
(1, 0, or -1 for each condition). Example: \code{dir.exp = c(1, 1, 1)}
for three conditions all expected to contribute positively.}

\item{include}{Inclusion rule for \code{minimize}. 
\code{""} (default, QCA compatible) computes the \strong{complex solution}
without logical remainders.
Use \code{"?"} to include logical remainders for \strong{parsimonious}
(with \code{dir.exp = NULL}) or \strong{intermediate} solutions
(with \code{dir.exp} specified).}

\item{incl.cut}{Consistency cutoff for \code{truthTable}.}

\item{n.cut}{Frequency cutoff for \code{truthTable}.}

\item{pri.cut}{PRI cutoff for \code{minimize}.}

\item{extract_mode}{Character. How to handle multiple solutions:
\code{"first"} (default), \code{"all"}, or \code{"essential"}.
See \code{\link{qca_extract}} for details.}

\item{return_details}{Logical. If \code{TRUE} (default), returns both
summary and detailed objects for use with \code{generate_report()}.}

\item{Yvar}{Deprecated. Use \code{outcome} instead.}

\item{Xvars}{Deprecated. Use \code{conditions} instead.}
}
\value{
If \code{return_details = FALSE}, a data frame with columns:
\itemize{
  \item \code{combo_id} — index of the threshold combination
  \item \code{threshold} — character string summarizing thresholds,
    e.g. \code{"X1=6, X2=7, X3=7"}
  \item \code{expression} — minimized solution expression
  \item \code{inclS} — solution consistency
  \item \code{covS} — solution coverage
  \item (additional columns depending on \code{extract_mode})
}

If \code{return_details = TRUE}, a list with:
\itemize{
  \item \code{summary} — the data frame above
  \item \code{details} — per-combination list of
    \code{combo_id}, \code{thrX_vec}, \code{truth_table}, \code{solution}
}

Note that \code{return_details} changes the \emph{type} of the returned
object, not just its contents: with \code{TRUE} the summary table is at
\code{result$summary}, whereas with \code{FALSE} the summary table
\emph{is} the returned object and \code{result$summary} is \code{NULL}.
Code intended to work under both settings should branch on
\code{inherits(result, "data.frame")} (or simply always pass
\code{return_details = TRUE}) rather than assuming \code{result$summary}
exists.
}
\description{
Performs a grid search over thresholds of multiple X variables.
For each combination of thresholds in \code{sweep_list}, the outcome Y
and all X variables are binarized, and a crisp-set QCA is executed.
}
\examples{
# Load sample data
data(sample_data)

# === Three Types of QCA Solutions ===

# Quick demonstration with 2 conditions
sweep_list <- list(X1 = 7, X2 = 7)

# 1. Complex Solution (default, QCA compatible)
result_comp <- ctSweepM(
  dat = sample_data,
  outcome = "Y",
  conditions = c("X1", "X2"),
  sweep_list = sweep_list,
  thrY = 7
  # include = "" (default), dir.exp = NULL (default)
)
head(result_comp$summary)

# 2. Parsimonious Solution (include = "?")
result_pars <- ctSweepM(
  dat = sample_data,
  outcome = "Y",
  conditions = c("X1", "X2"),
  sweep_list = sweep_list,
  thrY = 7,
  include = "?"  # Include logical remainders
)
head(result_pars$summary)

# 3. Intermediate Solution (include = "?" + dir.exp)
result_int <- ctSweepM(
  dat = sample_data,
  outcome = "Y",
  conditions = c("X1", "X2"),
  sweep_list = sweep_list,
  thrY = 7,
  include = "?",
  dir.exp = c(1, 1)  # Positive expectations
)
head(result_int$summary)

# === Threshold Sweep Example ===

# Using 2 conditions and 2 threshold levels
sweep_list <- list(
  X1 = 6:7,
  X2 = 6:7
)

# Run multiple condition threshold sweep (complex solutions by default)
result_quick <- ctSweepM(
  dat = sample_data,
  outcome = "Y",
  conditions = c("X1", "X2"),
  sweep_list = sweep_list,
  thrY = 7
)
head(result_quick$summary)

# Run with negated outcome (~Y)
result_neg <- ctSweepM(
  dat = sample_data,
  outcome = "~Y",
  conditions = c("X1", "X2"),
  sweep_list = sweep_list,
  thrY = 7
)
head(result_neg$summary)

\donttest{
# Full multi-condition analysis (27 combinations)
sweep_list_full <- list(
  X1 = 6:8,
  X2 = 6:8,
  X3 = 6:8
)

result_full <- ctSweepM(
  dat = sample_data,
  outcome = "Y",
  conditions = c("X1", "X2", "X3"),
  sweep_list = sweep_list_full,
  thrY = 7
)
head(result_full$summary)
}
}
