% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/theory.test.R
\name{theory.test}
\alias{theory.test}
\alias{print.theory_test}
\alias{as.data.frame.theory_test}
\title{Theory-specification robustness for QCA models}
\usage{
theory.test(
  data,
  outcome,
  theories,
  incl.cut = 1,
  n.cut = 1,
  solution = "all",
  include = NULL,
  dir.exp = NULL,
  which_M = 1,
  i_mode = "C1P1",
  exclude_mode = c("recompute", "static", "none"),
  exclude_recompute = list(type = 2),
  exclude_static = NULL,
  progress = TRUE,
  ...
)

\method{print}{theory_test}(x, row.names = FALSE, ...)

\method{as.data.frame}{theory_test}(x, ...)
}
\arguments{
\item{data}{A non-empty data frame containing the calibrated outcome and
calibrated condition columns.}

\item{outcome}{Name of the calibrated outcome column in \code{data}.}

\item{theories}{Named list of theory-specific condition sets. Each entry
must be a non-empty character vector of condition names in \code{data}.
Conditions may be shared across theories, but no theory may contain the
outcome as a condition.}

\item{incl.cut}{Inclusion cutoff to be used for every theory-specific truth
table.}

\item{n.cut}{Frequency cutoff to be used for every theory-specific truth
table.}

\item{solution}{Solution type to compare. Accepted values are \code{"all"},
\code{"con"} or \code{"conservative"}, \code{"par"} or \code{"parsimonious"}, and \code{"int"} or
\code{"intermediate"}.}

\item{include}{Optional minimization include setting. Currently, this
argument accepts only \code{NULL}, \code{""}, or \code{"?"}.}

\item{dir.exp}{Theory-specific directional expectations. Use \code{NULL} when no
intermediate solutions are monitored. Otherwise supply a named list with
one entry per theory. Each entry may be an ordered character vector aligned
to that theory's conditions or a named character vector whose names match
that theory's conditions.}

\item{which_M}{Positive integer giving which solution alternative to use
when minimization returns multiple models.}

\item{i_mode}{Character string controlling intermediate-solution selection.
Accepted values are \code{"C1P1"} and \code{"all"}. The default is \code{"C1P1"} because
comparative theory testing needs a single comparable intermediate branch
per theory by default.}

\item{exclude_mode}{Character string controlling how excluded rows are
handled for parsimonious and intermediate minimization. \code{"recompute"}
recalculates exclusions separately for each theory-specific truth table,
\code{"static"} reuses theory-specific static exclusions supplied through
\code{exclude_static}, and \code{"none"} does not use exclusions.}

\item{exclude_recompute}{Named list of arguments passed to \code{\link[QCA:findRows]{QCA::findRows()}}
when \code{exclude_mode = "recompute"}.}

\item{exclude_static}{Static exclusions used when \code{exclude_mode = "static"}.
For
\code{theory.test()}, this must be a named list with one entry per theory when
parsimonious or intermediate solutions are monitored.}

\item{progress}{Logical; if \code{TRUE}, show a text progress bar during
per-theory QCA runs in interactive sessions.}

\item{...}{Additional arguments split between \code{\link[QCA:truthTable]{QCA::truthTable()}} and
\code{\link[QCA:minimize]{QCA::minimize()}}. The function also looks in \code{...} for \code{include},
\code{dir.exp}, or \code{direxp} if those arguments were not supplied explicitly. In
\code{\link[=print.theory_test]{print.theory_test()}}, \code{...} is passed to \code{\link[=print.data.frame]{print.data.frame()}}. In
\code{\link[=as.data.frame.theory_test]{as.data.frame.theory_test()}}, \code{...} is ignored.}

\item{x}{A \code{theory_test} object returned by \code{\link[=theory.test]{theory.test()}}.}

\item{row.names}{Logical; if \code{TRUE}, print row names in the selected
solutions table printed by \code{\link[=print.theory_test]{print.theory_test()}}.}
}
\value{
An object of class \code{theory_test} with the following components:
\describe{
\item{\code{diagnostics}}{A detailed internal diagnostics table with one row
per theory and monitored solution type.}
\item{\code{results}}{A named list with \code{models}, \code{pairwise}, and
\code{solutions} tables. \code{models} is populated with model-level diagnostics
and fit values; \code{solutions} is populated with selected solution terms
and term-level fit values; \code{pairwise} is populated with pairwise theory
comparisons by solution type.}
\item{\code{by_theory}}{A named list containing the theory-specific condition
sets, directional expectations, truth tables, exclusions, minimization
objects, selected solution terms used for comparison, and current run
status.}
\item{\code{settings}}{A list containing the analysis settings used in the
call.}
}

\code{print.theory_test()} prints a compact theory-specification summary and
the selected solutions table. \code{as.data.frame.theory_test()} returns
\code{results$models}.
}
\description{
Compare several theoretically oriented QCA condition sets while holding the
outcome, truth-table cutoffs, solution type, exclusion handling, and
model-selection settings constant. Each theory supplies its own condition
set.
}
\details{
The function builds a separate truth table for each theory, recomputes
exclusions separately when requested, and runs the monitored solution types
under the same analytic settings. The raw per-theory QCA objects are stored
in \code{by_theory}. \code{results$models} gives the clean model-level comparison
table, and \code{results$solutions} gives the selected prime implicants or
solution terms by theory and solution type. \code{results$pairwise} compares selected
solution memberships across theories using fuzzy Jaccard similarity and
mean absolute membership differences.
}
\examples{
\donttest{
library(QCA)
data(LR)

outcome <- "SURV"

thresholds <- list(
  DEV = findTh(LR$DEV, groups = 7),
  URB = findTh(LR$URB, groups = 4),
  LIT = findTh(LR$LIT, groups = 4),
  IND = findTh(LR$IND, groups = 4),
  STB = findTh(LR$STB, groups = 4),
  SURV = findTh(LR$SURV, groups = 4)
)

dat <- LR
dat$DEV <- calibrate(LR$DEV, type = "fuzzy", thresholds = thresholds$DEV)
dat$URB <- calibrate(LR$URB, type = "fuzzy", thresholds = thresholds$URB)
dat$LIT <- calibrate(LR$LIT, type = "fuzzy", thresholds = thresholds$LIT)
dat$IND <- calibrate(LR$IND, type = "fuzzy", thresholds = thresholds$IND)
dat$STB <- calibrate(LR$STB, type = "fuzzy", thresholds = thresholds$STB)
dat$SURV <- calibrate(LR$SURV, type = "fuzzy", thresholds = thresholds$SURV)

theories <- list(
  development = c("DEV", "URB", "LIT"),
  industrial = c("DEV", "URB", "IND"),
  broad = c("DEV", "URB", "LIT", "IND", "STB")
)

dir_exp <- list(
  development = c("1", "1", "1"),
  industrial = c("1", "1", "1"),
  broad = c("1", "1", "1", "1", "1")
)

theory_out <- theory.test(
  data = dat,
  outcome = outcome,
  theories = theories,
  incl.cut = 0.8,
  n.cut = 1,
  solution = "all",
  dir.exp = dir_exp,
  progress = TRUE
)

theory_out
as.data.frame(theory_out)
theory_out$results$solutions
theory_out$results$pairwise
}

}
\seealso{
\code{\link[=calib.test]{calib.test()}}, \code{\link[=incl.test]{incl.test()}}, \code{\link[=ncut.test]{ncut.test()}}, \code{\link[=loo.test]{loo.test()}},
\code{\link[=subsample.test]{subsample.test()}}, \code{\link[=altset.test]{altset.test()}}, \code{\link[=cluster.test]{cluster.test()}}, \code{\link[=sol.df]{sol.df()}}
}
