Unfeasible intermediate solution

53 views
Skip to first unread message

Luigi Rombi

unread,
Dec 20, 2023, 11:40:04 AM12/20/23
to QCA with R
Dear all, 
I am trying to perform the minimization of my truth table and I find no issues on finding the complex and parsimonious solutions. However, when it comes to the intermediate solution, for which I have to use the dir.exp option, there is not way to do that and all I get is an error message. 

This is my code: 

R.version
               _                          
platform       aarch64-apple-darwin20      
arch           aarch64                    
os             darwin20                    
system         aarch64, darwin20          
status                                    
major          4                          
minor          3.2                        
year           2023                        
month          10                          
day            31                          
svn rev        85441                      
language       R                          
version.string R version 4.3.2 (2023-10-31)
nickname       Eye Holes                  

sessionInfo()
R version 4.3.2 (2023-10-31)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Ventura 13.4

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.11.0

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: Europe/Rome
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base    

other attached packages:
[1] QCA_3.21    admisc_0.34

loaded via a namespace (and not attached):
 [1] digest_0.6.33   later_1.3.1     R6_2.5.1        httpuv_1.6.12   fastmap_1.1.1   magrittr_2.0.3  shiny_1.8.0     htmltools_0.5.7 lifecycle_1.0.4 promises_1.2.1  cli_3.6.1       lpSolve_5.6.19  venn_1.11      
[14] xtable_1.8-4    compiler_4.3.2  tools_4.3.2     mime_0.12       ellipsis_0.3.2  Rcpp_1.0.11     rlang_1.1.2   

library(QCA)
library(admisc)
current_data <- read.csv("File.csv")
outcome <- c("Y")
configurator_list <- c("A", "B", "C", "D", "E", "F", "G")

results <- truthTable(current_data, outcome = outcome, conditions = paste(configurator_list, collapse = ","), use.letters = TRUE, incl.cut = 0.8, n.cut = 2, pri.cut = 0.65)

Complex <- minimize(results, details = TRUE)
Parsimonious <- minimize(results, include = "?", details = TRUE)

# NO PROBLEMS UNTIL HERE

directional_expectations <- c("G")
Intermediate <- minimize(results, include = "?", details = TRUE, dir.exp =directional_expectations)
Error: Unkown condition(s) in the expression.

Intermediate <- minimize(results, include = "?", details = TRUE, dir.exp = G)
Error: Unkown condition(s) in the expression.

Intermediate <- minimize(results, include = "?", details = TRUE, dir.exp = c("G"))
Error: Unkown condition(s) in the expression.

Intermediate <- minimize(results, include = "?", details = TRUE, dir.exp = c(G))
Error: Unkown condition(s) in the expression.

Thank you for your help,
Luigi

Adrian Dușa

unread,
Dec 20, 2023, 5:01:35 PM12/20/23
to Luigi Rombi, QCA with R
Hello Luigi,

We need a minimal reproducible example. The provided script is good, but unless we can replicate your error, finding a solution is just a guess.
The associated data would be helpful, or a script to produce a dataset similar to yours, that ends up in the same error.

All the best,
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 on the web visit https://groups.google.com/d/msgid/qcawithr/29da3b8b-ca38-41d9-884c-9c88ff857eben%40googlegroups.com.

Luigi Rombi

unread,
Dec 21, 2023, 4:42:22 AM12/21/23
to QCA with R
Hello Adrian,
thank you for your prompt answer. Here attached my file. I hope it helps to find the solution.

Best,
Luigi 

File.csv

Adrian Dușa

unread,
Dec 21, 2023, 11:32:24 AM12/21/23
to Luigi Rombi, QCA with R
This is strange.
I also have an ARM Mac (mine is M2 but it shouldn't matter), and have no problems running your script. My R.version() and sessionInfo() are almost identical to yours.

I even ran it under Windows, and still no problems at all... total mystery.
In case it helps, this is what I get:

From C1P1:

M1:    B*D + D*~E*~F + ~A*~C*~E*~F + ~A*D*~E*~G + A*C*D*~E -> Y

                inclS   PRI   covS   covU  
------------------------------------------
1          B*D  0.776  0.714  0.573  0.114
2      D*~E*~F  0.760  0.687  0.575  0.038
3  ~A*~C*~E*~F  0.755  0.679  0.282  0.020
4   ~A*D*~E*~G  0.837  0.772  0.463  0.079
5     A*C*D*~E  0.763  0.692  0.196  0.017
------------------------------------------
            M1  0.767  0.695  0.937


From C1P2:

M1:    B*D + D*~E*~F + ~A*D*~E*~G + A*C*D*~E + ~A*~C*~E*~F*~G -> Y

                   inclS   PRI   covS   covU  
---------------------------------------------
1             B*D  0.776  0.714  0.573  0.114
2         D*~E*~F  0.760  0.687  0.575  0.043
3      ~A*D*~E*~G  0.837  0.772  0.463  0.079
4        A*C*D*~E  0.763  0.692  0.196  0.017
5  ~A*~C*~E*~F*~G  0.834  0.773  0.274  0.018
---------------------------------------------
               M1  0.769  0.697  0.936 


All the best,
Adrian

Luigi Rombi

unread,
Dec 21, 2023, 3:04:38 PM12/21/23
to QCA with R
Dear Adrian,
if you don't have answers, I don't know what to say. 

The curious thing is that I just tried on Parallel and.. it works. 

I think that, for the same (obscure) reason, I have issues in the pof command (this also in Parallel).
Specifically, no matter how I specify my outcome the command does not recognize its negated version.

As an example, here's my script.

library(QCA)
library(admisc)
current_data <- read.csv("File.csv")
outcome <- c("Y")
negated_outcome <- c("~Y")
configurator_list <- c("A", "B", "C", "D", "E", "F", "G")
POS <- pof(A, outcome, data = current_data, relation = "necessity")
NEG <- pof(A, negated_outcome, data = current_data, relation = "necessity")

POS

       inclN   RoN   covN  
--------------------------
1   A  0.427  0.847  0.754
--------------------------

NEG

       inclN   RoN   covN  
--------------------------
1   A  0.427  0.847  0.754
-------------------------- 

Any clue about this?

Thanks again for your time,
Luigi

Adrian Dușa

unread,
Dec 22, 2023, 7:44:14 AM12/22/23
to Luigi Rombi, QCA with R
That is to be expected, since the pof() command accepts unquoted expressions that are evaluated in the dataset provided via the argument "data".

These work, however:

pof(A, ~Y, data = current_data, relation = "necessity")

pof(A <- ~Y, data = current_data)

I would personally recommend the second, being clear that it is a necessity relation (<-)
But I do see your point about the object negated_outcome, although I am not quite certain why anyone would specify ~Y (more visible, more obvious) via another object having the same negated value.

In the end, it is a matter of using the tool the way it works, instead of expecting it to work under all possible use case scenarios.

I hope this helps,
Adrian




Luigi Rombi

unread,
Dec 27, 2023, 11:38:26 AM12/27/23
to QCA with R
Hi Adrian, 
thank you for your prompt answer and forgive me for my late one. 

Yes, you are right (of course) saying that the ~Y is more visible and obvious. 

I was opting for this alternative (the object having the same negated value) because in my script I have different outcomes (and different negated values). 
Therefore, in total laziness, I had to change only the object once to run my analyses rather than doing it several times. 

Thank you again,
Luigi

Adrian Dușa

unread,
Dec 27, 2023, 3:42:14 PM12/27/23
to Luigi Rombi, QCA with R
Hi Luigi,

You can also quote the expression, like this:
pof("A <- ~Y", data = current_data)

and replace as needed, using sprintf():

pof(sprintf("A <- %s", "~Y"), data = current_data)

and use your own object, as you originally intended:

pof(sprintf("A <- %s", negated_outcome), data = current_data)

I hope this helps,
Adrian


Luigi Rombi

unread,
Jan 4, 2024, 1:01:38 PM1/4/24
to QCA with R
Dear Adrian, 
thanks again for your response. It works perfectly for a single year.

I wonder whether it can be stretched for the lazybones like myself. 
Specifically, as I am running different analyses in different years, I wonder whether it can be modified accordingly as I have several configurators and outcomes (named consistently, of course).

As an example, here's a snippet of the script I'm working on that, at the moment, does not recognize the difference between the outcome and its negated version.

outcome <- c("Y")
negated_outcome <- c("~Y")
configurator_list <- c("A", "B", "C", "D", "E", "F", "G")

year_list <- seq(2018, 2020, by = 2)

necessity_results <- list()
sufficiency_results <- list()
necessity_results_NEG <- list()
sufficiency_results_NEG <- list()

necessity_list <- list()
sufficiency_list <- list()
necessity_list_NEG <- list()
sufficiency_list_NEG <- list()

# Here, I extract values from pof results for the necessity and sufficiency of configurators
extract_pof_values <- function(pof_result, relation) {
  if (relation == "necessity") {
    return(round(c(
      inclN = pof_result$incl.cov$inclN,
      RoN = pof_result$incl.cov$RoN,
      covN = pof_result$incl.cov$covN
    ), 3))
  } else if (relation == "sufficiency") {
    return(round(c(
      inclS = pof_result$incl.cov$inclS,
      PRI = pof_result$incl.cov$PRI,
      covS = pof_result$incl.cov$covS,
      covU = pof_result$incl.cov$covU
    ), 3))
  }
}

# Then, with a for cycle, I do it for the years I am interested in
for (i in seq_along(year_list)) {
  year <- year_list[i]
  # Create the file name for the current year
  current_file <- paste("yearSINGLE_", year, ".csv", sep = "")
  current_data <- read.csv(current_file)
# Here I modified sprintf() so that it would accommodate both the configurator and the outcome
for (variable in configurator_list) {
    pof_result_necessity <- pof(sprintf("%s <- %s", variable, outcome), data = current_data)
    necessity_list[[length(necessity_list) + 1]] <- c(
      Year = year,
      Variable = variable,
      extract_pof_values(pof_result_necessity, "necessity")
    )
   
    pof_result_sufficiency <- pof(sprintf("%s -> %s", variable, outcome), data = current_data)
    sufficiency_list[[length(sufficiency_list) + 1]] <- c(
      Year = year,
      Variable = variable,
      extract_pof_values(pof_result_sufficiency, "sufficiency")
    )
 
 
    pof_result_necessity_NEG <- pof(sprintf("%s <- %s", variable, negated_outcome), data = current_data)
    necessity_list_NEG[[length(necessity_list_NEG) + 1]] <- c(
      Year = year,
      Variable = variable,
      extract_pof_values(pof_result_necessity, "necessity")
    )
   
    pof_result_sufficiency_NEG <- pof(sprintf("%s -> %s", variable, negated_outcome), data = current_data)
    sufficiency_list_NEG[[length(sufficiency_list_NEG) + 1]] <- c(
      Year = year,
      Variable = variable,
      extract_pof_values(pof_result_sufficiency, "sufficiency")
    )
  }


}

# Then I convert everything to a dataframe and add the rows for each configurator/year and print it

necessity_df <- do.call(rbind, necessity_list)
necessity_df_NEG <- do.call(rbind, necessity_list_NEG)
sufficiency_df <- do.call(rbind, sufficiency_list)
sufficiency_df_NEG <- do.call(rbind, sufficiency_list_NEG)


necessity_results[[length(necessity_results) + 1]] <- necessity_df
necessity_results_NEG[[length(necessity_results_NEG) + 1]] <- necessity_df_NEG
sufficiency_results[[length(sufficiency_results) + 1]] <- sufficiency_df
sufficiency_results_NEG[[length(sufficiency_results_NEG) + 1]] <- sufficiency_df_NEG


print(necessity_df)
print(necessity_df_NEG)

print(sufficiency_df)
print(sufficiency_df_NEG)



I am attaching two files to test if you want.

As always thanks for your time,
Luigi
yearSINGLE_2020.csv
yearSINGLE_2018.csv

Adrian Dușa

unread,
Jan 4, 2024, 3:45:05 PM1/4/24
to Luigi Rombi, QCA with R
Hello Luigi,

At your third batch of extract_pof_values(), I think it should be:
extract_pof_values(pof_result_necessity_NEG, "necessity")

since you are calculating the pof() results into pof_result_necessity_NEG, isn't it?
(ditto for the fourth batch)

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.

Luigi Rombi

unread,
Jan 4, 2024, 4:06:06 PM1/4/24
to QCA with R
Hi Adrian, 
thank you for your careful looking at my snippet. 

It works perfectly now.

Again, thank you for your time.

Best,
Luigi
Reply all
Reply to author
Forward
0 new messages