cna-solutions: Extract solutions from an object of class "cna"

cna-solutionsR Documentation

Extract solutions from an object of class “cna”

Description

Given a solution object x produced by cna, msc(x) extracts all minimally sufficient conditions, asf(x) all atomic solution formulas, and csf(x, n.init) builds approximately n.init complex solution formulas. All solution attributes (details) available in showMeasures can be computed. The three functions return a data frame with the additional class attribute “condTbl”.

Usage

msc(x, details = x$details, cases = FALSE)
asf(x, details = x$details)
csf(x, n.init = 1000, details = x$details, asfx = NULL, 
    inus.only = x$control$inus.only, inus.def = x$control$inus.def,  
    minimalizeCsf = inus.only, 
    acyclic.only = x$acyclic.only, cycle.type = x$cycle.type, 
    func.minimal.only = x$control$func.minimal.only, verbose = FALSE)

Arguments

x

Object of class “cna”.

details

A character vector specifying the evaluation measures and additional solution attributes to be computed. Possible elements are all the measures in
showMeasures. Defaults to the details specification stored in x. Can also be TRUE/FALSE. If FALSE, no additional attributes are returned; TRUE resolves to c("inus", "cyclic", "fm_empirical","fm_structural", "exhaustiveness",
"faithfulness", "coherence") for csf, to c("inus", "exhaustiveness", "faithfulness") for asf, and to c("exhaustiveness", "faithfulness") for msc (cf. detailMeasures).

cases

Logical; if TRUE, an additional column listing the cases where the msc is instantiated in combination with the outcome is added to the output.

n.init

Integer capping the amount of initial asf combinations. Defaults to 1000. Serves to control the computational complexity of the csf building process.

asfx

Object of class “condTbl” produced by the asf function. Internal parameter not meant to be set by users.

inus.only

Logical; if TRUE, csf are freed of structural redundancies and only csf not featuring partial structural redundancies are retained (cf. vignette("cna"); cf. also is.inus and cnaControl).

inus.def

Character string specifying the definition of partial structural redundancy to be applied. Possible values are "implication" or "equivalence". The strings can be abbreviated. Cf. also is.inus and cnaControl.

minimalizeCsf

Logical; if TRUE, csf are freed of structural redundancies (cf. vignette("cna")). Defaults to the value of inus.only.

acyclic.only

Logical; if TRUE, csf featuring a cyclic substructure are not returned. Defaults to the setting stored in x.

cycle.type

Character string specifying what type of cycles to be detected: "factor" or "value" (cf. cyclic). Defaults to the setting stored in x (normally "factor").

func.minimal.only

Logical; if TRUE, only functionally minimal csf, as implemented in fm_empirical (see also func_minim), are included in the list of csf. Defaults to the setting stored in x; at the default settings of cnaControl, this is FALSE.

verbose

Logical; if TRUE, some details on the csf building process are printed. FALSE by default.

Details

Depending on the processed data, the solutions (models) output by cna are often ambiguous, to the effect that many atomic and complex solutions fit the data equally well. To facilitate the inspection of the cna output, however, cna standardly returns only 5 minimally sufficient conditions (msc) and 5 atomic solution formulas (asf) for each outcome as well as 5 complex solution formulas (csf). msc can be used to extract all msc from an object x of class “cna”, asf to extract all asf, and csf to build approximately n.init csf from the asf stored in x. All solution attributes (details) that are saved in x are recovered as well. Moreover, all evaluation measures and solution attributes available in showMeasures—irrespective of whether they are saved in x—can be computed by specifying them in the details argument. The outputs of msc, asf, and csf can be further processed by the condition function.

While msc and asf merely extract information stored in x, csf builds csf from the inventory of asf recovered at the end of the third stage of the cna algorithm (cf. vignette("cna"), section 4). That is, the csf function implements the fourth stage of that algorithm. It proceeds in a stepwise manner as follows.

  1. n.init possible conjunctions featuring one asf of every outcome are built.

  2. If inus.only = TRUE or minimalizeCsf = TRUE, the solutions resulting from step 1 are freed of structural redundancies (cf. Baumgartner and Falk 2023).

  3. If inus.only = TRUE, tautologous and contradictory solutions as well as solutions with partial structural redundancies (as defined in inus.def) and constant factors are eliminated. [If inus.only = FALSE and minimalizeCsf = TRUE, only structural redundancies are eliminated, meaning only step 2, but not step 3, is executed.]

  4. If acyclic.only = TRUE, solutions with cyclic substructures are eliminated.

  5. Solutions that are a submodel of another solution are removed.

  6. If func.minimal.only = TRUE, solutions that are not functionally minimal in the sense of fm_empirical are removed.

  7. For those solutions that were modified in the previous steps, the scores on the selected evaluation measures are re-calculated and solutions that no longer reach con or cov are eliminated (cf. cna).

  8. The remaining solutions are returned as csf, ordered by complexity and the product of their scores on the evaluation measures.

Value

msc, asf and csf return objects of class “condTbl”, which are similar to a data.frame and feature the following components:

outcome: the outcomes
condition: the relevant conditions or solutions
con: the scores on the sufficiency measure (e.g. consistency)
cov: the scores on the necessity measure (e.g. coverage)
complexity: the complexity scores (number of factor value appearances to the left of “<->”)
...: scores on additional evaluation measures and solution attributes as specified in
details

The condition column carries the class “stdAtomic” or “stdComplex”, depending on whether it holds asf or csf. Functions such as detailMeasures use this class to tell the two apart, so it should not be dropped, for instance by c().

References

Baumgartner, Michael and Christoph Falk. 2023. “Boolean Difference-Making: A Modern Regularity Theory of Causation.” The British Journal for the Philosophy of Science, 74(1):171-197. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1093/bjps/axz047")}

Lam, Wai Fung and Elinor Ostrom. 2010. “Analyzing the Dynamic Complexity of Development Interventions: Lessons from an Irrigation Experiment in Nepal.” Policy Sciences 43(2):1-25. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1007/s11077-009-9082-6")}

See Also

cna, configTable, condition, condTbl, cnaControl, is.inus, detailMeasures, showMeasures, cyclic, func_minim, d.irrigate

Examples

# Crisp-set data from Lam and Ostrom (2010) on the impact of development interventions
# ------------------------------------------------------------------------------------
# CNA with causal ordering that corresponds to the ordering in Lam and Ostrom (2010); coverage 
# cut-off at 0.9 (consistency cut-off at 1).
cna.irrigate <- cna(d.irrigate, ordering = "A, R, F, L, C < W", cov = .9,
                    maxstep = c(4, 4, 12), details = TRUE)
cna.irrigate

# The previous function call yields a total of 12 complex solution formulas, only
# 5 of which are returned in the default output. 
# Here is how to extract all 12 complex solution formulas along with all 
# solution attributes.
csf(cna.irrigate)
# With only the default solution attributes plus exhaustiveness and faithfulness.
csf(cna.irrigate, details = c("exh", "fai"))
# Calculate additional evaluation measures from showConCovMeasures().
csf(cna.irrigate, details = c("exh", "fai", "PAcon", "PACcov", "AACcon", "AAcov"))

# Return only the functionally minimal csf (cf. ?fm_empirical).
csf(cna.irrigate, func.minimal.only = TRUE)

# Extract all atomic solution formulas.
asf(cna.irrigate, details = c("exh", "fai"))

# Extract all minimally sufficient conditions.
msc(cna.irrigate) # capped at 20 rows
print(msc(cna.irrigate), n = Inf) # prints all rows
# Add cases featuring the minimally sufficient conditions combined 
# with the outcome.
(msc.table <- msc(cna.irrigate, cases = TRUE))
# Render as data frame.
as.data.frame(msc.table)

# Extract only the conditions (solutions).
csf(cna.irrigate)$condition
asf(cna.irrigate)$condition
msc(cna.irrigate)$condition

# A CNA of d.irrigate without outcome specification and ordering is even more
# ambiguous.
cna2.irrigate <- cna(d.irrigate, cov = .9, maxstep = c(4, 4, 12), 
                     details = c("exh", "fai", "ccon", "ccov"))

# Reduce the initial asf combinations to 50.
csf(cna2.irrigate, n.init = 50)
# Print the first 20 csf.
csf(cna2.irrigate, n.init = 50)[1:20, ]

# Only the functionally minimal csf, with printed details about the csf building
# process.
csf(cna2.irrigate, func.minimal.only = TRUE, verbose = TRUE)

# Return evaluation measures and solution attributes with 5 digits.
print(asf(cna2.irrigate), digits = 5)
 

# Further examples
# ----------------
# An example generating structural redundancies.
target <- "(A*B + C <-> D)*(c + a <-> E)"
dat1 <- selectCases(target)
ana1 <- cna(dat1, maxstep = c(3, 4, 10))
# Run csf with elimination of structural redundancies.
csf(ana1, verbose = TRUE)
# Run csf without elimination of structural redundancies. 
csf(ana1, verbose = TRUE, inus.only = FALSE)

# An example generating partial structural redundancies.
dat2 <- data.frame(
  A=c(0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 1),
  B=c(0,0,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1),
  C=c(1,1,0,0,0,1,0,0,1,1,0,1,1,0,1,1,0,1,1,1,0,1,0,1,0,1,0),
  D=c(0,1,1,1,0,1,1,1,0,0,0,1,0,1,0,0,0,1,0,0,0,1,1,0,0,1,0),
  E=c(1,0,0,0,0,1,1,1,1,1,1,0,0,1,0,0,0,1,1,1,1,0,0,0,0,1,1),
  F=c(1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0),
  G=c(1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1))
ana2 <- cna(dat2, con = .8, cov = .8, maxstep = c(3, 3, 10))
# Run csf without elimination of partial structural redundancies.
csf(ana2, inus.only = FALSE, verbose = TRUE)
# Run csf with elimination of partial structural redundancies.
csf(ana2, verbose = TRUE)
# Prior to version 3.6.0, the "equivalence" definition of partial structural
# redundancy was used by default (see ?is.inus() for details). Now, the 
# "implication" definition is used. To replicate old behavior
# set inus.def to "equivalence".
csf(ana2, verbose = TRUE, inus.def = "equivalence")
# The two definitions only come apart in case of cyclic structures.
# Build only acyclic models.
csf(ana2, verbose = TRUE, acyclic.only = TRUE)
# Add further details.
csf(ana2, verbose = TRUE, acyclic.only = TRUE, details = c("PAcon", "PACcov"))


cna documentation built on Oct. 28, 2026, 9:07 a.m.