Redundant prime implicants, contradictory simplifying assumptions

6 views
Skip to first unread message

Alexander Strelkov

unread,
Jun 7, 2026, 5:07:35 PM (6 days ago) Jun 7
to QCA with R

Dear group members, good evening
     A couple of question on redundant prime implicants and contradictory simplifying assumptions.

Question 1: When running a code for an intermediate solution, are there no objections to adding row.dom to the syntax to avoid redundant prime implicants? 
I ran the code, it works but I wonder if there are any "conceptual objections" to doing so

intcheck<-minimize(tt,details = TRUE,include = "?",dir.exp = dir.exp,row.dom = TRUE)

  Question 2: When doing enhanced standard analysis, can I search for contradictory simplifying assumptions by using the intermediate but not the parsimonious solution? In Oana/Schneider/Thomann 2021 (p.132) the example was provided with a parsimonious

  Question 3: When searching for contradictory simplifying assumptions, is better to use the LR.intersect function OR findRows (as in findRows(obj=truth table, type=2). Is there any meaningful difference between them?

Many thanks for your assistance!
Best wishes, 
Alexander

Adrian Dușa

unread,
Jun 8, 2026, 12:21:08 PM (5 days ago) Jun 8
to Alexander Strelkov, QCA with R
Dear Alexander,

I might attempt to answer your questions, most of them pertaining to the inner workings of the QCA package.

1. The argument row.dom has nothing (particularly) to do with the solution type (it can be applied for all conservative, parsimonious and intermediate). All it does is to simplify the prime implicants chart, removing dominated prime implicants that are covered by other prime implicants that explain at least as many (if not more) positive configurations from the truth table. In doing so, the number of solution models decreases (sometimes dramatically), and that is one way of dealing with high model ambiguity.

2. I would definitely say a parsimonious solution. Simplifying assumptions, as per Ragin's theory, are discussed in relation to parsimonious solutions. The focus of the intermediate solution is less on simplifying assumptions (contradictory or not) but rather on the complexity - parsimony continuum, so simplifying assumptions must be known to be subjected against the theoretical expectations. On a side note, many (even experts) say the directional expectations filter the remainders, but that is not exactly what it happens and I only describe what the algorithm really does (for a dedicated section on this topic, see: https://adriandusa.com/research/articles/2025-QQ/)

3. Likely a matter of taste, but I would warmly recommend findRows() since it is part of the main package QCA and thoroughly tested. As a less known feature that will be part of a future second edition of my book, users can specify additional parameters such as a different inclusion threshold for the negation of the outcome. This really does simplify the process a lot, at least this is how I perceive it. Most of the work is done by the computer, while users have full control over what is used and asked for.

I hope this helps,
Adrian

--
You received this message because you are subscribed to the Google Groups "QCA with R" group.
To unsubscribe from this group and stop receiving emails from it, send an email to qcawithr+u...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/qcawithr/840c221f-5763-4119-bce0-bf5a88b26d39n%40googlegroups.com.

Ingo Rohlfing

unread,
Jun 8, 2026, 4:18:04 PM (5 days ago) Jun 8
to QCA with R
If I may follow up on Adrian's email on the third point. I find the findRows() function more convenient because it is easier to use. In relation with the original question, however, I wondered how it handles model ambiguity. LR.intersect() allows one to pick a specific model in the presence of model ambiguity. This is necessary because each model is based on different simplifying assumptions, so I wondered how findRows() deals with it.

Adrian Dușa

unread,
Jun 9, 2026, 5:53:26 AM (5 days ago) Jun 9
to Ingo Rohlfing, QCA with R
Hello Ingo,

Actually, the process is a little bit different. I am attaching an older presentation all the way back from Zurich, see for instance slide 24.
The whole procedure is explained in detail, including the conjunctural directional expectations.

I am not sure what exactly LR.intersect() does, but I am certain about what the algorithm does: all intermediate models are based on the same set of simplifying assumptions.
A smaller subset of these SAs is selected that are compatible with the complexity - parsimony continuum, then a classical QM minimization is performed from that subset and the initial observed positive configurations. Obviously, this minimization can yield multiple models (like any other minimization, just like the conservative solution can yield ambiguity) but the point is the resulting models don't have different simplifying assumptions.

This is a likely different explanation of the process than many of the other expert explanations (probably even taught in summer schools): but it is what it is, and the code behind it is open source for anyone to inspect and perform a scrutiny check...

I hope this helps, with all my best,
Adrian

Mechanics of (conjunctural) directional expectations.pdf

Alexander Strelkov

unread,
Jun 9, 2026, 9:25:20 AM (4 days ago) Jun 9
to Adrian Dușa, Ingo Rohlfing, QCA with R
Dear Adrian, Dear Ingo, 
     Another follow-up question in relation to enhanced standard analysis.
Running the code with findRows:

consias<-findRows(obj = tt, type = 2)

TTnew<-esa(oldtt=tt,contrad_rows=c(consias))

intnew<-minimize(TTnew,details = TRUE,include = "?",dir.exp = dir.exp,row.dom = TRUE)

This gives me a whopping 72 solutions (C1P72)


Running the code with LR.intersect:

CSA<-LR.intersect(par,negpar)

tt2<-esa(oldtt = tt,contrad_rows = c(CSA))

int4<-minimize(tt2,details = TRUE, include = "?",dir.exp = dir.exp, row.dom = TRUE)

Same whopping 72 solutions (C1P72)


However, just doing the standard intermediate solution provides me with one solution (6 pathways) which is conceptually much easier to interpret

intcheck<-minimize(tt,details = TRUE,include = "?",dir.exp = dir.exp,row.dom = TRUE)

In this respect two questions:

1) What causes this "explosion" of output? Computing contradictory simplifying assumptions seems to complicate things and I do not have conceptual/theoretical grounds for selecting one of the 72 models?

2) In terms of standards, can I just continue with a "traditional" intermediate solution (given that I do not have contradicting claims of necessity and no impossible remainders)?

Many thanks in advance for your insights!

Best wishes, 

Alexander




Breno A. H. Marisguia

unread,
Jun 9, 2026, 2:21:51 PM (4 days ago) Jun 9
to Alexander Strelkov, Adrian Dușa, Ingo Rohlfing, QCA with R
To answer Alexander's third question from the first message more clearly:

`findRows(type = 2)`, if I'm not mistaken, takes the original truth table, constructs a new one also for the negation of the outcome, runs the minimization (with `include = "?"`) for both, and then returns the row numbers of the simplifying assumptions that coincide between the two.

`LR.intersect` is just a neat way of wrapping simplifying assumptions (`solution$SA$M#` in parsimonious solutions) or easy counterfactuals (`solution$i.sol$C#P#$EC` in intermediate solutions) for people not familiar with what lurks within a `QCA_min` object.

Check the example below:

```
library(QCA)
library(SetMethods)

data(LF)

# LF tt for Y
tt_y <- truthTable(
  LF,
  outcome = "SURV",
  conditions = c("DEV", "URB", "LIT", "IND", "STB"),
  incl.cut = 0.8
)


# LF tt for ~Y
tt_not_y <- truthTable(
  LF,
  outcome = "~SURV",
  conditions = c("DEV", "URB", "LIT", "IND", "STB"),
  incl.cut = 0.8
)


# Parsimonious for Y
par_y <- minimize(
  tt_y,
  include = "?",
  details = TRUE
)


# Parsimonious for ~Y
par_not_y <- minimize(
  tt_not_y,
  include = "?",
  details = TRUE
)


# LR.intersect (returns "10" "12" "14" "16" "17" "21" "25" "29")
LR.intersect(
  results1 = par_y,
  results2 = par_not_y,
  sol1 = 1,
  sol2 = 1
)


# Alternatively, you could just do it like this (which also returns "10" "12" "14" "16" "17" "21" "25" "29"):
intersect(
    rownames(par_y$SA$M1),
    rownames(par_not_y$SA$M1)
)

# Or even like this, which is actually what LR.intersect() does behind the curtains (I'm pretty sure):
intersect(
  rownames(get("M1", pos = par_y$SA)),
  rownames(get("M1", pos = par_not_y$SA))
)
```

For the "72 solutions!" part, check your `consias` object. It is probably returning many contradictory simplifying assumption rows, which then won't be available for minimization. If those rows were doing much of the simplifying work, removing them can, therefore, yield many models.

Now, when it comes to standards for including logical remainders, well... you can do whatever you want, as long as you are transparent about the pros, the cons, and where the specialized literature stands. But be warned, if you go too deep into this rabbit hole, you may find that things get a bit heated down there.

My honest suggestion though: focus on the back-and-forth between theory and evidence. Maybe it's time to tweak your research design! Are you still trying to run, like, 15 conditions at once?

Breno


Alexander Strelkov

unread,
Jun 9, 2026, 4:39:25 PM (4 days ago) Jun 9
to Breno A. H. Marisguia, Adrian Dușa, Ingo Rohlfing, QCA with R
Dear Breno, 
    Much obliged for an extensive response!
No, not 15 conditions:) Tried mvQCA with 7 conditions (3 of which are multivalue), might try crisp-set with making all 7 conditions binary (without turning multi-value conditions into binary what resulted in...proliferation of conditions:)
Best wishes, 
Alexander

Adrian Dușa

unread,
Jun 11, 2026, 1:41:08 PM (2 days ago) Jun 11
to Breno A. H. Marisguia, Alexander Strelkov, Ingo Rohlfing, QCA with R
Dear Alexander,

In continuation of Breno's message, I wanted to underline that the "explosion of output" (as you call it, this is in fact just high model ambiguity) is not caused in any way by the intermediate solution or by selecting simplifying assumptions.

The "C1P72" is tale telling here: it seems that you have (at least) 72 models in the parsimonious solution. But that is not high model ambiguity in the intermediate solution, it is ambiguity in the parsimonious solution ("P72" where P stands for parsimonious)

Hence, no matter what you do in the (enhanced) standard analysis phase, you are still confronted with a high number of parsimonious solution models, which is a different topic altogether. I believe there are many articles dealing with this, but generally it means there are many paths where the outcome is instantiated. As Bruno says, you might want to revisit your conceptual model, or your causal conditions, or their calibrations, and this is good practice: QCA is a constant dialog with the data.

Indeed, the more conditions you add in the minimization process, the higher the likelihood that your model ambiguity will increase. But model ambiguity is also related to the number of positive observed configurations: the more such truth table rows, the larger the prime implicants matrix, the higher the likelihood to find (very) many combinations of prime implicants to cover those positive configurations.

I hope this helps,
Adrian
Reply all
Reply to author
Forward
0 new messages