version 3.22
This function performs the QCA minimization of an input truth table, or if the input is a dataset the minimization it minimizes a set of causal conditions with respect to an outcome. Three minimization methods are available: the classical Quine-McCluskey, the enhanced Quine-McCluskey and the latest Consistency Cubes algorithm that is built for performance.
All algorithms return the same, exact solutions, see Dusa (2018) and Dusa and Thiem (2015)
minimize(input, include = "", dir.exp = NULL, details = FALSE, pi.cons = 0, sol.cons = 0, all.sol = FALSE, row.dom = FALSE, first.min = FALSE, max.comb = 0, use.labels = FALSE, method = "CCubes", ...Arguments
input
A truth table object (preferred) or a data frame containing calibrated causal conditions and an outcome. include
A vector of other output values to include in the minimization process. dir.exp
Character, a vector of directional expectations to derive intermediate solutions. details
Logical, print more details about the solution. pi.cons
Numerical fuzzy value between 0 and 1, minimal consistency threshold for a prime implicant to be declared as sufficient. sol.cons
Numerical fuzzy value between 0 and 1, minimal consistency threshold for a model to be declared as sufficient. all.sol
Logical, search for all possible solutions. row.dom
Logical, perform row dominance in the prime implicants' chart to eliminate redundant prime implicants. first.min
Logical, to return only the very first minimal solution (see Details). max.comb
Numeric real, to limit the size of the PI chart (see Details). use.labels
Logical, use category labels if present (See Examples). method
Minimization method, one of "CCubes"
(default), or"QMC"
the classical Quine-McCluskey, or"eQMC"
the enhanced Quine-McCluskey....
Other arguments to be passed to function truthTable()
.Details
Most of the times, this function takes a truth table object as the
input
for the minimization procedure, but the same argument can refer to a data frame containing calibrated columns.For the later case, the function
minimize()
originally had some additional formal arguments which were sent to the functiontruthTable()
:outcome
,conditions
,n.cut
,incl.cut
,show.cases
,use.letters
andinf.test
.All of these parameters are still possible with function
minimize()
, but since they are sent to thetruthTable()
function anyway, it is unnecessary to duplicate their explanation here. The only situation which does need an additional description relates to the argumentoutcome
, where unliketruthTable()
which accepts a single one, the functionminimize()
accepts multiple outcomes and performs a minimization for each of them (a situation when all columns are considered causal conditions).The argument
include
specifies which other truth table rows are included in the minimization process. Most often, the remainders are included but any value accepted in the argumentexplain
is also accepted in the argumentinclude
.The argument
dir.exp
is used to specify directional expectations, as described by Ragin (2003). They can be specified using SOP expressions, which opens up the possibility to experiment with conjunctural directional expectations. "Don't care" conditions are simply left unspecified.Activating the
details
argument has the effect of printing parameters of fit for each prime implicant and each overall solution, the essential prime implicants being listed in the top part of the table. It also prints the truth table, in case the argumentinput
has been provided as a data frame instead of a truth table object.The default method (when
all.sol
), is to find the minimal number (k
) of prime implicants needed to cover all initial positive output configurations (minterms), then exhaustively search through all possible disjunctions ofk
prime implicants which do cover those configurations.Once the PI chart is constructed using the prime implicants found in the previous stages, the argument
row.dom
can be used to further eliminate irrelevant prime implicants when solving the PI chart, applying the principle of row dominance: if a prime implicant A covers the same (intial) positive output configurations as another prime implicant B and in the same time covers other configurations which B does not cover, then B is irrelevant and eliminated.Depending on the complexity of the PI chart, it sometimes may take a very long time to identify all possible irredundant (disjunctions that are not subsets of previously found) disjunctive solutions. In such a situation, the number of combinations of all possible numbers of prime implicants is potentially too large to be solved in a polynomial time and if not otherwise specified, the depth for the disjunctive solutions is automatically bounded to 5 prime implicants.
If minimizing a dataset instead of a truth table, unless otherwise specified the argument
incl.cut
is automatically set to the minimum value betweenpi.cons
andsol.cons
, then passed to the functiontruthTable()
.The argument
sol.cons
introduces another possibility to change the method of solving the PI chart. Normally, once the solutions are found among all possible combinations ofk
prime implicants, consistencies and coverages are subsequently calculated. Whensol.cons
is lower than 1, then solutions are searched based on their consistencies, which should be at least equal to this threshold.A large number of causal conditions (i.e. over 15), combined with a large number of cases (i.e. hundreds) usually produce a very large number of prime implicants, resulting in a huge and extremely complex PI chart with sometimes thousands of rows and hundreds of columns.
For such a complex PI chart, even finding a minimum is a formidable task, and exhaustively solving it is very likely impossible in polynomial time. For this reason, after each level of complexity the CCubes algorithm determines if the PI chart is too difficult, by calculating the total number of combinations of minimum
k
PIs necessary to cover all columns.The argument \bold{\code{max.comb}} controls this maximum number of combinations. It is a rational number counted in (fractions of) billions, defaulted at zero to signal searching to the maximum possible extent. If the total number of combinations exceeds a positive value of
max.comb
, the PI chart is determined as too complex, the search is stopped and CCubes attempts to return all possible models using the PIs from the previous levels of complexity, when the PI chart was still not too complex.In the extreme situation even this is not feasible, the argument
first.min
controls returning only one (the very first found) minimal model, if at all possible.Value
An object of class
"qca"
when using a single outcome, or class"mqca"
when using multiple outcomes. These objects are lists having the following components:
tt
The truth table object. options
Values for the various options used in the function (including defaults). negatives
The line number(s) of the negative configuration(s). initials
The initial positive configuration(s). PIchart
A list containing the PI chart(s). primes
The prime implicant(s). solution
A list of solution(s). essential
A list of essential PI(s). pims
A list of PI membership scores. IC
The matrix containing the inclusion and coverage scores for the solution(s). SA
A list of simplifying assumptions. i.sol
A list of components specific to intermediate solution(s), each having a PI chart, prime implicant membership scores, (non-simplifying) easy counterfactuals and difficult counterfactuals. complex
Flag solutions from a too complex PI chart. call
The user's command which produced all these objects and result(s). References
Cebotari, V.; Vink, M.P. (2013) A Configurational Analysis of Ethnic Protest in Europe. International Journal of Comparative Sociology vol.54, no.4, pp.298-324, DOI: 10.1177/0020715213508567.
Cebotari, V.; Vink, M.P. (2015) Replication Data for: A configurational analysis of ethnic protest in Europe, Harvard Dataverse, V2, DOI: 10.7910/DVN/PT2IB9
Cronqvist, L.; Berg-Schlosser, D. (2009) Multi-Value QCA (mvQCA), in Rihoux, B.; Ragin, C. (eds.) Configurational Comparative Methods. Qualitative Comparative Analysis (QCA) and Related Techniques, SAGE.
Dusa, A.; Thiem, A. (2015) Enhancing the Minimization of Boolean and Multivalue Output Functions With eQMC Journal of Mathematical Sociology vol.39, no.2, pp.92-108, DOI: 10.1080/0022250X.2014.897949.
Dusa, A. (2018) Consistency Cubes: A Fast, Efficient Method for Boolean Minimization R Journal vol.10, no.2, pp.357-370, DOI: 10.32614/RJ-2018-080.
Dusa, A. (2019) QCA with R. A Comprehensive Resource. Springer International Publishing.
Ragin, C.C. (2003) Recent Advances in Fuzzy-Set Methods and Their Application to Policy Questions. WP 2003-9, COMPASSS.
Ragin, C.C. (2009) Qualitative Comparative Analysis Using Fuzzy-Sets (fsQCA), in Rihoux, B.; Ragin, C. (eds.) Configurational Comparative Methods. Qualitative Comparative Analysis (QCA) and Related Techniques, SAGE.
Ragin, C.C.; Strand, S.I. (2008) Using Qualitative Comparative Analysis to Study Causal Order: Comment on Caren and Panofsky (2005). Sociological Methods & Research vol.36, no.4, pp.431-441, DOI: 10.1177/0049124107313903.
Rihoux, B.; De Meur, G. (2009) Crisp Sets Qualitative Comparative Analysis (mvQCA), in Rihoux, B.; Ragin, C. (eds.) Configurational Comparative Methods. Qualitative Comparative Analysis (QCA) and Related Techniques, SAGE.
Examples
# ----- # Lipset binary crisp data # the associated truth table ttLC <- truthTable(LC, "SURV", sort.by = "incl, n") ttLCOUT: outcome value n: number of cases in configuration incl: sufficiency inclusion score DEV URB LIT IND STB OUT n incl PRI 32 1 1 1 1 1 1 4 1.000 1.000 22 1 0 1 0 1 1 2 1.000 1.000 24 1 0 1 1 1 1 2 1.000 1.000 1 0 0 0 0 0 0 3 0.000 0.000 2 0 0 0 0 1 0 2 0.000 0.000 5 0 0 1 0 0 0 2 0.000 0.000 6 0 0 1 0 1 0 1 0.000 0.000 23 1 0 1 1 0 0 1 0.000 0.000 31 1 1 1 1 0 0 1 0.000 0.000# conservative solution (Rihoux & De Meur 2009, p.57) cLC <- minimize(ttLC) cLCM1: DEV*urb*LIT*STB + DEV*LIT*IND*STB <=> SURV# view the Venn diagram for the associated truth table library(venn) venn(cLC)
# add details and case names minimize(ttLC, details = TRUE, show.cases = TRUE)n OUT = 1/0/C: 8/10/0 Total : 18 Number of multiple-covered cases: 2 M1: DEV*~URB*LIT*STB + DEV*LIT*IND*STB <=> SURV inclS PRI covS covU cases ------------------------------------------------------------------- 1 DEV*~URB*LIT*STB 1.000 1.000 0.500 0.250 FI,IE; FR,SE 2 DEV*LIT*IND*STB 1.000 1.000 0.750 0.500 FR,SE; BE,CZ,NL,UK ------------------------------------------------------------------- M1 1.000 1.000 1.000# negating the outcome ttLCn <- truthTable(LC, "~SURV", sort.by = "incl, n") minimize(ttLCn)M1: ~DEV*~URB*~IND + DEV*LIT*IND*~STB <=> ~SURV# parsimonious solution, positive output pLC <- minimize(ttLC, include = "?", details = TRUE, show.cases = TRUE) pLCn OUT = 1/0/C: 8/10/0 Total : 18 Number of multiple-covered cases: 0 M1: DEV*STB <=> SURV inclS PRI covS covU cases ----------------------------------------------------------------- 1 DEV*STB 1.000 1.000 1.000 - FI,IE; FR,SE; BE,CZ,NL,UK ----------------------------------------------------------------- M1 1.000 1.000 1.000# the associated simplifying assumptions pLC$SA$M1 DEV URB LIT IND STB 18 1 0 0 0 1 20 1 0 0 1 1 26 1 1 0 0 1 28 1 1 0 1 1 30 1 1 1 0 1# parsimonious solution, negative output pLCn <- minimize(ttLCn, include = "?", details = TRUE, show.cases = TRUE) pLCnn OUT = 1/0/C: 10/8/0 Total : 18 Number of multiple-covered cases: 5 M1: ~DEV + ~STB <=> ~SURV inclS PRI covS covU cases --------------------------------------------------------------- 1 ~DEV 1.000 1.000 0.800 0.300 GR,PT,ES; IT,RO; HU,PL; EE 2 ~STB 1.000 1.000 0.700 0.200 GR,PT,ES; HU,PL; AU; DE --------------------------------------------------------------- M1 1.000 1.000 1.000# ----- # Lipset multi-value crisp data (Cronqvist & Berg-Schlosser 2009, p.80) # truth table ttLM <- truthTable(LM, "SURV", conditions = "DEV, URB, LIT, IND", sort.by = "incl", show.cases = TRUE) # conservative solution, positive output minimize(ttLM, details = TRUE)n OUT = 1/0/C: 7/11/0 Total : 18 Number of multiple-covered cases: 0 M1: DEV[2]*LIT[1]*IND[1] + DEV[1]*URB[0]*LIT[1]*IND[0] => SURV[1] inclS PRI covS covU cases --------------------------------------------------------------------------- 1 DEV[2]*LIT[1]*IND[1] 1.000 1.000 0.625 0.625 FR,SE; BE,NL,UK 2 DEV[1]*URB[0]*LIT[1]*IND[0] 1.000 1.000 0.250 0.250 FI,IE --------------------------------------------------------------------------- M1 1.000 1.000 0.875# parsimonious solution, positive output minimize(ttLM, include = "?", details = TRUE, show.cases = TRUE)n OUT = 1/0/C: 7/11/0 Total : 18 Number of multiple-covered cases: 0 M1: DEV[2] + DEV[1]*IND[0] => SURV[1] inclS PRI covS covU cases ------------------------------------------------------------- 1 DEV[2] 1.000 1.000 0.625 0.625 FR,SE; BE,NL,UK 2 DEV[1]*IND[0] 1.000 1.000 0.250 0.250 FI,IE ------------------------------------------------------------- M1 1.000 1.000 0.875# negate the outcome ttLMn <- truthTable(LM, "~SURV", conditions = "DEV, URB, LIT, IND", sort.by = "incl", show.cases = TRUE) # conservative solution, negative output minimize(ttLMn, details = TRUE, show.cases = TRUE)n OUT = 1/0/C: 9/9/0 Total : 18 Number of multiple-covered cases: 0 M1: DEV[0]*URB[0]*IND[0] + DEV[1]*URB[0]*LIT[1]*IND[1] => ~SURV[1] inclS PRI covS covU cases ------------------------------------------------------------------------------------ 1 DEV[0]*URB[0]*IND[0] 1.000 1.000 0.800 0.800 GR,IT,PT,RO,ES; EE,HU,PL 2 DEV[1]*URB[0]*LIT[1]*IND[1] 1.000 1.000 0.100 0.100 AU ------------------------------------------------------------------------------------ M1 1.000 1.000 0.900# parsimonious solution, positive output minimize(ttLMn, include = "?", details = TRUE, show.cases = TRUE)n OUT = 1/0/C: 9/9/0 Total : 18 Number of multiple-covered cases: 0 M1: DEV[0] + DEV[1]*URB[0]*IND[1] => ~SURV[1] inclS PRI covS covU cases ----------------------------------------------------------------------------- 1 DEV[0] 1.000 1.000 0.800 0.800 GR,IT,PT,RO,ES; EE,HU,PL 2 DEV[1]*URB[0]*IND[1] 1.000 1.000 0.100 0.100 AU ----------------------------------------------------------------------------- M1 1.000 1.000 0.900# ----- # Lipset fuzzy sets data (Ragin 2009, p.112) ttLF <- truthTable(LF, "SURV", incl.cut = 0.8, show.cases = TRUE, sort.by="incl") # conservative solution minimize(ttLF, details = TRUE)n OUT = 1/0/C: 6/12/0 Total : 18 Number of multiple-covered cases: 0 M1: DEV*URB*LIT*IND*STB + DEV*~URB*LIT*~IND*STB => SURV inclS PRI covS covU cases ----------------------------------------------------------------- 1 DEV*URB*LIT*IND*STB 0.904 0.886 0.454 0.393 BE,CZ,NL,UK 2 DEV*~URB*LIT*~IND*STB 0.804 0.719 0.265 0.204 FI,IE ----------------------------------------------------------------- M1 0.870 0.843 0.658# parsimonious solution minimize(ttLF, include = "?", details = TRUE)n OUT = 1/0/C: 6/12/0 Total : 18 Number of multiple-covered cases: 0 M1: DEV*~IND + URB*STB => SURV inclS PRI covS covU cases ---------------------------------------------------- 1 DEV*~IND 0.815 0.721 0.284 0.194 FI,IE 2 URB*STB 0.874 0.845 0.520 0.430 BE,CZ,NL,UK ---------------------------------------------------- M1 0.850 0.819 0.714# intermediate solution minimize(ttLF, include = "?", details = TRUE, dir.exp = "DEV, URB, LIT, IND, STB")n OUT = 1/0/C: 6/12/0 Total : 18 From C1P1: Number of multiple-covered cases: 0 M1: DEV*URB*LIT*STB + DEV*LIT*~IND*STB => SURV inclS PRI covS covU cases ------------------------------------------------------------ 1 DEV*URB*LIT*STB 0.901 0.879 0.468 0.378 BE,CZ,NL,UK 2 DEV*LIT*~IND*STB 0.814 0.721 0.282 0.191 FI,IE ------------------------------------------------------------ M1 0.866 0.839 0.660# directional expectations can also be specified using a sequence minimize(ttLF, include = "?", details = TRUE, dir.exp = DEV:STB)n OUT = 1/0/C: 6/12/0 Total : 18 From C1P1: Number of multiple-covered cases: 0 M1: DEV*URB*LIT*STB + DEV*LIT*~IND*STB => SURV inclS PRI covS covU cases ------------------------------------------------------------ 1 DEV*URB*LIT*STB 0.901 0.879 0.468 0.378 BE,CZ,NL,UK 2 DEV*LIT*~IND*STB 0.814 0.721 0.282 0.191 FI,IE ------------------------------------------------------------ M1 0.866 0.839 0.660# URB as a don't care condition (left unspecified) and # conjunctural directional expectations minimize(ttLF, include = "?", details = TRUE, show.cases = TRUE, dir.exp = "DEV, STB, ~LIT*IND")n OUT = 1/0/C: 6/12/0 Total : 18 From C1P1: Number of multiple-covered cases: 0 M1: DEV*URB*STB + DEV*~IND*STB => SURV inclS PRI covS covU cases -------------------------------------------------------- 1 DEV*URB*STB 0.901 0.879 0.468 0.378 BE,CZ,NL,UK 2 DEV*~IND*STB 0.814 0.721 0.282 0.191 FI,IE -------------------------------------------------------- M1 0.866 0.839 0.660# ----- # Cebotari & Vink (2013, 2015) ttCVF <- truthTable(CVF, outcome = "PROTEST", incl.cut = 0.8, show.cases = TRUE, sort.by = "incl, n") pCVF <- minimize(ttCVF, include = "?", details = TRUE, show.cases = TRUE) pCVFn OUT = 1/0/C: 13/16/0 Total : 29 Number of multiple-covered cases: 5 M1: ~NATPRIDE + DEMOC*GEOCON*POLDIS + (~DEMOC*ETHFRACT*POLDIS + DEMOC*ETHFRACT*GEOCON) => PROTEST M2: ~NATPRIDE + DEMOC*GEOCON*POLDIS + (~DEMOC*ETHFRACT*POLDIS + DEMOC*ETHFRACT*~POLDIS) => PROTEST M3: ~NATPRIDE + DEMOC*GEOCON*POLDIS + (DEMOC*ETHFRACT*GEOCON + ETHFRACT*GEOCON*POLDIS) => PROTEST M4: ~NATPRIDE + DEMOC*GEOCON*POLDIS + (DEMOC*ETHFRACT*~POLDIS + ETHFRACT*GEOCON*POLDIS) => PROTEST --------------------------------- inclS PRI covS covU (M1) (M2) (M3) (M4) --------------------------------------------------------------------------------- 1 ~NATPRIDE 0.899 0.807 0.597 0.121 0.132 0.122 0.136 0.126 2 DEMOC*GEOCON*POLDIS 0.906 0.805 0.342 0.065 0.065 0.070 0.065 0.065 --------------------------------------------------------------------------------- 3 ~DEMOC*ETHFRACT*POLDIS 0.842 0.718 0.299 0.000 0.040 0.040 4 DEMOC*ETHFRACT*GEOCON 0.935 0.826 0.480 0.000 0.085 0.085 5 DEMOC*ETHFRACT*~POLDIS 0.932 0.773 0.417 0.000 0.085 0.085 6 ETHFRACT*GEOCON*POLDIS 0.869 0.786 0.365 0.005 0.045 0.045 --------------------------------------------------------------------------------- M1 0.877 0.777 0.805 M2 0.877 0.777 0.805 M3 0.879 0.782 0.810 M4 0.879 0.782 0.810 cases -------------------------------- 1 ~NATPRIDE CrimRussiansUkr,RussiansUkraine; HungariansYugo,KosovoAlbanians; RussiansLatvia; BasquesSpain; AlbaniansFYROM 2 DEMOC*GEOCON*POLDIS HungariansRom,CatholicsNIreland; AlbaniansFYROM; RussiansEstonia -------------------------------- 3 ~DEMOC*ETHFRACT*POLDIS HungariansYugo,KosovoAlbanians; GagauzMoldova 4 DEMOC*ETHFRACT*GEOCON BasquesSpain; SerbsFYROM,CatalansSpain; AlbaniansFYROM; RussiansEstonia 5 DEMOC*ETHFRACT*~POLDIS BasquesSpain; SerbsFYROM,CatalansSpain 6 ETHFRACT*GEOCON*POLDIS HungariansYugo,KosovoAlbanians; GagauzMoldova; AlbaniansFYROM; RussiansEstonia --------------------------------# inspect the PI chart pCVF$PIchart5 15 16 24 27 29 30 31 32 ~NATPRIDE x x - - x x - x - ~DEMOC*ETHFRACT*POLDIS - x x - - - - - - DEMOC*ETHFRACT*GEOCON - - - - - x x x x DEMOC*ETHFRACT*~POLDIS - - - - - x x - - DEMOC*GEOCON*POLDIS - - - x - - - x x ETHFRACT*GEOCON*POLDIS - x x - - - - x x# DEMOC*ETHFRACT*poldis is dominated by DEMOC*ETHFRACT*GEOCON # using row dominance to solve the PI chart pCVFrd <- minimize(ttCVF, include = "?", row.dom = TRUE, details = TRUE, show.cases = TRUE) # plot the prime implicants on the outcome pims <- pCVFrd$pims par(mfrow = c(2, 2)) for(i in 1:4) { XYplot(pims[, i], CVF$PROTEST, cex.axis = 0.6) }
# ----- # temporal QCA (Ragin & Strand 2008) serving the input as a dataset, # which will automatically be passed to truthTable() as an intermediary # step before the minimization minimize(RS, outcome = "REC", details = TRUE)OUT: outcome value n: number of cases in configuration incl: sufficiency inclusion score P E A EBA S OUT n incl PRI 5 0 0 0 - 0 0 3 0.000 0.000 17 0 1 0 - 0 0 1 0.000 0.000 20 0 1 1 0 1 1 1 1.000 1.000 29 1 0 0 - 0 0 1 0.000 0.000 30 1 0 0 - 1 0 3 0.000 0.000 36 1 0 1 - 1 0 2 0.000 0.000 42 1 1 0 - 1 1 1 1.000 1.000 44 1 1 1 0 1 1 1 1.000 1.000 45 1 1 1 1 0 1 2 1.000 1.000 46 1 1 1 1 1 1 2 1.000 1.000 n OUT = 1/0/C: 7/10/0 Total : 17 Number of multiple-covered cases: 3 M1: P*E*S + P*E*A*EBA + E*A*~EBA*S <=> REC inclS PRI covS covU ----------------------------------------- 1 P*E*S 1.000 1.000 0.571 0.143 2 P*E*A*EBA 1.000 1.000 0.571 0.286 3 E*A*~EBA*S 1.000 1.000 0.286 0.143 ----------------------------------------- M1 1.000 1.000 1.000# ----- # employ category labels ttLF <- truthTable(LF, SURV, incl.cut = 0.8, sort.by = "incl", show.cases = TRUE) minimize(ttLF, include = "?", use.labels = TRUE)M1: Developed*Not industrialised + High urbanisation*Stability -> Survival# or ttLF <- truthTable( LF, SURV, incl.cut = 0.8, sort.by = "incl", show.cases = TRUE, use.labels = TRUE ) minimize(ttLF, include = "?")M1: Developed*Not industrialised + High urbanisation*Stability -> Survival