| is.inus | R Documentation |
is.inus checks for each element of a character vector of disjunctive normal forms (DNFs) or expressions in the syntax of CNA solution formulas whether it has INUS form, meaning whether it is free of redundancies in necessary or sufficient conditions, free of structural and partial structural redundancies, whether it has constant factors or identical outcomes, and whether it is tautologous or contradictory.
is.inus(cond, x = NULL, csf.info = FALSE, def = c("implication", "equivalence"),
func.minim = FALSE)
cond |
Character vector of DNFs or expressions in the syntax of CNA solutions (i.e. asf or csf). |
x |
Optional argument providing a |
csf.info |
Logical; if |
def |
Character string specifying the definition of partial structural redundancy (PSR) to be applied. If |
func.minim |
Logical: If |
A Boolean dependency structure is not interpretable in terms of a deterministic causal structure if it contains at least one of the following (cf. the Examples below for illustrations):
redundancies in necessary or sufficient conditions,
structural redundancies,
partial structural redundancies,
constant factors,
tautologous or contradictory substructures,
multiple instances of the same outcome.
The function is.inus takes a character vector cond specifying Boolean disjunctive normal forms (DNFs) or expressions in the syntax of CNA solution formulas as input and runs a series of checks on cond, one for each of the conditions (1) to (6). For instance, whenever cond logically implies a syntactic proper part of itself, the surplus in cond is redundant, meaning that it violates condition (1) and is not causally interpretable. To illustrate, “A + a*B <-> C” implies and is even logically equivalent to “A + B <-> C”. Hence, "a" is redundant in the first expression, which is not causally interpretable due to a violation of condition (1).
Or the first asf in “(a + C <-> D)*(D + G <-> A)” implies that whenever "a" is given, so is "D", while the second asf implies that whenever "D" is given, so is "A". It follows that "a" cannot ever be given, meaning that the factor A takes the constant value 1 and, hence, violates condition (4). As constant factors can neither be causes nor effects, “(a + C <-> D)*(D + G <-> A)” is not a well-formed causal structure.
If an expression passes the is.inus check it can be interpreted as a causal structure according to Mackie's (1974) INUS theory of causation or modern variants thereof (e.g. Grasshoff and May 2001; Baumgartner and Falk 2023). In other words, such an expression has the form of an INUS structure, i.e. it has INUS form, for short.
Zhang and Zhang (2023) impose a further minimality constraint on the causal interpretability of Boolean functions, which they call functional minimality.
A Boolean function is functionally minimal if, and only if, its outcome(s) cannot be modeled on the basis of a proper subset of its factors. Zhang and Zhang formulate the constraint for the purely conceptual context of defining causation. For the context of causal discovery, functional minimality has been operationalized for INUS-formhood as implemented in fm_structural, which evaluates every formula in cond against the ideal data it generates (selectCases(cond[i])) and tests, for every asf contained in it and every factor of that asf, whether the outcome is constant across the configurations that agree on the remaining factors of the asf. If this holds for at least one factor, that factor is functionally redundant and the formula fails the check. At func.minim = TRUE, is.inus imposes functional minimality in that sense.
In the function's default call with x = NULL, the INUS checks are performed relative to full.ct(cond); if x is not NULL, the checks are performed relative to full.ct(x). As full.ct(cond) and full.ct(x) coincide in case of binary factors, the argument x has no effect in the crisp-set and fuzzy-set cases. For multi-value factors, however, the argument x should be specified in order to define the factors' value ranges (see Examples below).
If the argument csf.info is set to its non-default value TRUE and cond has the syntax of a csf, the results of the individual checks of conditions (1) to (6) are printed (in that order) to the console.
At its default settings, cna does not output solutions that lack INUS form. Only when cna is modified by passing inus.only = FALSE to its control argument may non-INUS solutions be returned (cf. Examples below). The function is.inus is standardly called from within the cna function to ensure that its output has INUS form.
is.inus also serves an important purpose in the context of benchmark tests. Not every Boolean expression can be interpreted as representing a causal structure; only expressions in INUS form can. That means when simulating data on randomly drawn target structures, it must be ensured that the latter have INUS form. An expression such as “A + a*B <-> C”, which has a logically equivalent proper part and, hence, does not have INUS form, is not a well-formed causal structure that could be used as a search target in a benchmark test.
Logical vector of the same length as cond, named by cond; if cond is a csf and is.inus is called with csf.info = TRUE, an attribute “csf.info” is added.
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")}
Grasshoff, Gerd and Michael May. 2001. “Causal Regularities.” In W. Spohn, M. Ledwig, M. Esfeld (eds.), Current Issues in Causation, pp. 85-114. Mentis, Paderborn.
Mackie, John L. 1974. The Cement of the Universe: A Study of Causation. Oxford: Oxford University Press. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1093/0198246420.001.0001")}
Zhang, Jiji and Kun Zhang. 2023. “A New Minimality Condition for Boolean Accounts of Causal Regularities.” Erkenntnis 90(1):67-86. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1007/s10670-023-00685-4")}
condition, condList, configTable, full.ct, cna, func_minim
# Crisp-set case
# --------------
# Testing disjunctive normal forms.
is.inus(c("A", "A + B", "A + a*B", "A + a", "A*a", "A*a + B"))
# Testing expressions in the syntax of atomic solution formulas.
is.inus(c("A + B <-> C", "A + B <-> c", "A + a*B <-> C", "A*a + B <-> C", "A + a <-> C",
"F*G + f*g + H <-> E", "F*G + f*g + H*F + H*G <-> E"))
# Testing expressions in the syntax of complex solution formulas.
is.inus(c("(A + B <-> C)*(c + E <-> D)", "(A <-> B)*(B <-> C)", "(A <-> B)*(B <-> C)*(C <-> D)",
"(A <-> B)*(B <-> a)", "(A*B + c <-> D)*(E + f <-> D)",
"(A + B <-> C)*(B*c + E <-> D)"))
# A redundancy in necessary or sufficient conditions, i.e.
# a non-INUS asf in a csf.
is.inus("(A + A*B <-> C)*(B + D <-> E)", csf.info = TRUE)
# A structural redundancy in a csf.
cond1 <- "(e + a*D <-> C)*(C + A*B <-> D)*(a + c <-> E)"
is.inus(cond1, csf.info = TRUE)
# The first asf in cond1 is redundant.
minimalizeCsf(cond1, selectCases(cond1))
# A partial structural redundancy in a csf.
cond2 <- "(A + B*c + c*E <-> D)*(B + C <-> E)"
is.inus(cond2, csf.info = TRUE)
# The second or third disjunct in the first asf of cond2 is redundant.
cna(selectCases(cond2))
# The notion of a partial structural redundancy (PSR) can be defined in two
# different ways. To illustrate, consider the following two csf.
cond2b <- "(B + F*C <-> A)*(A*e*f <-> B)"
cond2c <- "(B + F*C <-> A)*(A*f <-> B)"
# cond2c is a proper submodel of cond2b, and cond2b logically implies cond2c,
# but the two csf are not logically equivalent (i.e. cond2c does not
# imply cond2b). If a PSR is said to obtain when one csf logically implies
# a proper submodel of itself, then cond2b contains a PSR. If a csf has to be
# logically equivalent to a proper submodel of itself in order for a PSR to
# obtain, then cond2b does not contain a PSR. This difference is implemented
# in the argument def of is.inus(). The default is def = "implication".
is.inus(cond2b, csf.info = TRUE, def = "implication")
is.inus(cond2b, csf.info = TRUE, def = "equivalence")
# The two definitions of PSR only come apart in case of cyclic structures.
# In versions of the cna package prior to 3.6.0, is.inus() implemented the
# "equivalence" definition of PSR. That is, to reproduce results of earlier
# versions, def may have to be set to "equivalence".
# A csf entailing that one factor is constant.
is.inus("(a + C <-> D)*(D + G <-> A)", csf.info = TRUE)
# A contradictory (i.e. logically constant) csf.
is.inus("(A <-> B)*(B <-> a)", csf.info = TRUE)
# A csf with multiple identical outcomes.
is.inus("(A + C <-> B)*(C + E <-> B)", csf.info = TRUE)
# The airconditioning example Zhang and Zhang (2023) use to illustrate
# functional minimality.
aircon <- selectCases("(A + B <-> E1)*(A*b + A*C <-> E2)")
cond <- csf(cna(aircon))$condition
# Without functional minimality imposed.
is.inus(cond)
# With functional minimality imposed.
is.inus(cond, func.minim = TRUE)
# Multi-value case
# ----------------
# In case of multi-value data, is.inus() needs to be given a dataset x determining
# the value ranges of the factors in cond.
mvdata <- configTable(setNames(allCombs(c(2, 3, 2, 3)) -1, c("C", "F", "V", "O")))
is.inus("C=1 + F=2*V=0 <-> O=2", mvdata)
# x can also be given to is.inus() as a list.
is.inus("C=1 + F=2*V=0 <-> O=2", list(C=0:1, F=0:2, V=0:1, O=0:2))
# When x is NULL, is.inus() is applied to full.ct("C=1 + F=2*V=0"), which has only
# one single row. That row is then interpreted to be the only possible configuration,
# in which case C=1 + F=2*V=0 is tautologous and, hence, non-INUS.
is.inus("C=1 + F=2*V=0 <-> O=2")
is.inus("C=1 + C=0*C=2", configTable(d.pban)) # contradictory
is.inus("C=0 + C=1 + C=2", configTable(d.pban)) # tautologous
# A redundancy in necessary or sufficient conditions, i.e. a
# non-INUS asf in a csf.
fullDat <- full.ct(list(A=1:3, B=1:3, C=1:3, D=1:3, E=1:3))
is.inus("(A=1 + A=1*B=2 <-> C=3)*(B=2 + D=3 <-> E=1)", fullDat, csf.info = TRUE)
# A structural redundancy in a csf.
cond3 <- "(E=2 + C=1*D=3 <-> A=1)*(A=3*E=1 + C=2*D=2 <-> B=3)*(A=1*E=3 + D=2*E=3 <-> C=1)*
(A=1*C=2 + A=1*C=3 <-> E=2)"
is.inus(cond3, fullDat, csf.info = TRUE)
# The last asf in cond3 is redundant.
minimalizeCsf(cond3, selectCases(cond3, fullDat))
# A partial structural redundancy in a csf.
cond4 <- "(B=2*C=3 + C=2*D=1 + B=2*C=1*D=2*E=1 <-> A=2)*(D=2*E=1 + D=3*E=1 <-> B=1)"
is.inus(cond4, fullDat, csf.info = TRUE)
# The third disjunct in the first asf of cond4 is redundant.
cna(selectCases(cond4, fullDat))
# A csf entailing that one factor is constant. (I.e. D is constantly ~(D=1).)
cond5 <- "(A=1 + B=2 + E=3 <->C=3)*(A=1*C=1 + B=2*C=1 <-> D=1)"
is.inus(cond5, fullDat, csf.info = TRUE)
# A contradictory csf.
is.inus("(A=1 <-> C=1)*(A=1 <-> C=2)*(A=1 <-> C=3)", fullDat, csf.info = TRUE)
# A csf with multiple identical outcomes.
is.inus("(A=1 + B=2 + D=3 <-> C=1)*(A=2 + B=3 + D=2 <-> C=1)", fullDat, csf.info = TRUE)
# Fuzzy-set case
# --------------
fsdata <- configTable(d.jobsecurity)
conds <- csf(cna(fsdata, con = 0.85, cov = 0.85, inus.only = FALSE))$condition
# Various examples of different types.
is.inus(conds[1:10], fsdata, csf.info = TRUE)
is.inus(c("S + s", "S + s*R", "S*s"), fsdata)
# A redundancy in necessary or sufficient conditions, i.e. a
# non-INUS asf in a csf.
is.inus("(S + s*L <-> JSR)*(R + P <-> V)", fsdata, csf.info = TRUE)
# A structural redundancy in a csf.
is.inus("(s + l*R <-> C)*(C + L*V <-> R)*(l + c <-> S)", fsdata, csf.info = TRUE)
# A partial structural redundancy in a csf.
is.inus("(S + L*c + c*R <-> P)*(L + C <-> R)", fsdata, csf.info = TRUE)
# A csf entailing that one factor is constant.
is.inus("(S + L <-> P)*(L*p <-> JSR)", csf.info = TRUE)
# A contradictory csf.
is.inus("(S <-> JSR)*(JSR <-> s)", fsdata, csf.info = TRUE)
# A csf with multiple identical outcomes.
is.inus("(S*C + V <-> JSR)*(R + P <-> JSR)", fsdata, csf.info = TRUE)
# Modifying cna()
# ---------------
# If the cna() function is modified through inus.only = FALSE, it may output solutions
# that fail the INUS check.
ana.aut <- cna(d.autonomy, ordering = "AU", con = .9, cov = .9,
maxstep = c(2, 2, 8), control = cnaControl(inus.only = FALSE))
csf(ana.aut) # The column "inus" is generated by is.inus().
is.inus(csf(ana.aut)$condition)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.