NEWS.md
citation("ThSQCA") now also lists the accompanying preprint (Toyoda, 2026, SocArXiv, doi:10.31235/osf.io/yb8xs_v1), which is also added to the README and to the reference list of the tutorial vignette.ThSQCA_Tutorial_EN was reorganized and extended: a quick start, data preparation (binary variables, pre_calibrated, sweeping membership scores), a section on choosing between complex, parsimonious and intermediate solutions and one on multiple minimal solutions (both with a second simulated data set that has logical remainders), guidance on reporting, and answers to common questions. Version-history headings were removed.ctSweepS() for one condition, ctSweepM() for several conditions), OTS (otSweep()), and DTS (dtSweep()). The former labels “TS-QCA” and “MCTS-QCA” were removed from the README and the vignettes. No function names, arguments, or results changed.install.packages("ThSQCA") as the primary installation route, and made the “Basic Setup” example use the bundled sample_data so that it runs as written. Fixed two bullet lists that were rendered as running text on CRAN.ThSQCA_Reproducible_EN are now named ThSQCA_* instead of TSQCA_*; TSQCA_MCTS_results.csv became ThSQCA_CTS_multi_results.csv. Added a pointer to Sweep Builder in ThSQCA_Tutorial_EN.QCA::truthTable() and QCA::minimize() inside the sweep loops now go through an internal helper, quiet_try(), which behaves like try(..., silent = TRUE) but also discards console output written by the QCA call itself. Warnings are passed on unchanged (they are collected while the output is diverted and signalled again afterwards). Results are unchanged.pre_calibrated variable that contains memberships of exactly 0.5 now produces one warning per sweep, naming the variable and the number of cases. Previously QCA’s own warning (“Fuzzy causal conditions should not have values of 0.5 in the data”) was repeated for every cell of the sweep (twice per cell) without saying which variable was affected; that per-cell warning is no longer repeated.otSweep_result, tsqca_result, and so on) are unchanged, so existing code that dispatches on them keeps working." ~TRU").minimize(tt), minimize(tt, include = "?") or minimize(tt, include = "?", dir.exp = c(...)) with your values) instead of a placeholder.generate_report() now shows the outcome name you supplied (for example LOY, or ~LOY for a negated outcome) in solution formulas, in the captured QCA console output, and in the “Solutions Overview” headings, where it previously showed the internal column name Y. The verification snippet at the end of each report now names your outcome and conditions and uses your incl.cut. Internally the outcome column is still called Y.pre_calibrated and give thresholds on the 0 to 1 scale); the tutorial has a new subsection on this. The warning for a variable that is both in pre_calibrated and in a sweep list now says how to sweep it (remove it from pre_calibrated) and no longer points to a vignette section that does not exist. The rule itself is unchanged: a pre_calibrated variable is used as it is and its sweep thresholds are ignored.get_n_solutions() no longer double-counts models when the intermediate solution spans multiple prime implicant charts. When dir.exp produces more than one prime implicant chart (QCA’s own chart indexing, visible as "From C1P1, C2P1:" in print(), as opposed to multiple parsimonious paths within a single chart, "From C1P1, C1P2:"), sol$i.sol holds one list entry per chart/path combination. Each entry’s own $solution field is computed independently by QCA::minimize() and is not guaranteed to be chart-exclusive: depending on the data, it may already enumerate the full, cross-chart set of tied minimal models. Summing length($solution) across every chart name, as get_n_solutions() previously did, could therefore double- (or N-fold) count identical models. This was visible as an inflated n_solutions in res$summary and in the Summary Table of generate_report()’s Markdown output; the displayed solution formula itself was already correct. A new internal helper, collect_unique_i_sol(), performs the same enumeration and then deduplicates by comparing each model’s term set (order-independent), so structurally identical models are counted once regardless of which chart(s) produced them. generate_report()’s two sol_list-construction blocks (used for the “Full Solutions” listing and as input to identify_epi()) were updated to use the same helper; the identify_epi() EPI/SPI content itself was unaffected by the duplication (set operations are insensitive to duplicate entries), only the displayed solution count was wrong. Cells with a single prime implicant chart, which are the common case, are unaffected.
The standalone identify_epi() function itself was audited and confirmed correct: it is a pure function over its solutions argument and does not read sol$solution internally. All three internal call sites already built their input via the sol$i.sol traversal above rather than a naive sol$solution read; the double-counting above was the only defect found in that path. Passing sol$solution (top level) directly to identify_epi(), as opposed to a sol_list built via sol$i.sol, is still not meaningful when dir.exp is specified and should be avoided: that slot holds the parsimonious solution’s terms in that case, not the intermediate solution’s.
qca_extract(extract_mode = "all" | "essential") now summarizes across the same set of solutions that n_solutions counts. These two modes derived their term sets from sol$i.sol$C1P1$solution, that is, from the first prime implicant chart only. That slot is the right basis for extract_mode = "first" (its first entry is the displayed M1), but whether it enumerates every chart’s model or only its own is an implementation detail of QCA::minimize()’s internal getSolution() call rather than a documented guarantee. Both modes now build their model list with collect_unique_i_sol(), the same enumeration get_n_solutions() counts, so the reported EPI/SPI terms and the reported solution count can no longer describe different sets. On data where the first chart already enumerated every model, which includes all cases checked here, the output is unchanged.
The same duplication defect was found and fixed in two further places. A follow-up audit of every sol$i.sol traversal in the package turned up two more sites built on the same chart-by-chart concatenation: extract_solution_list() (used by generate_config_chart()), where the inflated count made the chart announce too many equivalent solutions and emit one identical table per duplicate; and extract_sol_terms_by_model() (used by compute_fiss_core()), where it inflated the reported parsim_n_solutions and the tie warning derived from it. The core/peripheral classification itself was not affected, because it counts a status only where every minimal solution agrees, which is insensitive to duplicates. Both now deduplicate by term-set content. extract_all_metrics() reads the first chart’s IC deliberately, to match the displayed M1, and was left as it is.
ctSweepM() gained a thrX_default argument and no longer fails silently. A condition present in conditions but absent from both sweep_list and pre_calibrated previously had no column created at all, which made QCA::truthTable() fail and returned "No solution" for every cell with no error or warning. Such a condition is now either binarized at thrX_default (mirroring ctSweepS()) or, if thrX_default is not supplied, reported as an error naming the uncovered conditions and showing both ways to fix the call. Calls that already listed every condition in sweep_list are unaffected and produce identical results.print_fiss_summary() no longer requires thr_key. Omitting it raised R’s generic “argument is missing” error, and discovering the valid keys meant inspecting names(result$fiss_core) by hand. thr_key now defaults to NULL, which summarizes every threshold level in turn. Passing an explicit thr_key behaves as before, including the existing error that lists the available keys.T1, T2, … instead of M1, M2, … M1/M2 denote whole alternative minimal solutions throughout the package (as in print(sol)), so reusing M for the product terms within one solution made the two levels indistinguishable. This affects the column headers produced by build_config_matrix() (used by config_chart_multi_solutions() and related chart functions), the term columns of the cross-threshold Fiss chart, and the [Term ...] headings printed by print_fiss_summary(). Charts now read, for example, “Solution M1” with term columns T1, T2. This is a change to displayed output only; no computed value is affected.@return documentation of all four sweep functions (otSweep(), ctSweepS(), ctSweepM(), dtSweep()) now states explicitly that return_details changes the type of the returned object, not only its contents: with TRUE the summary table is at result$summary, while with FALSE the summary table is the returned object and result$summary is NULL. Code meant to work under both settings should branch on inherits(result, "data.frame") or always pass return_details = TRUE. The behavior itself is unchanged, since altering the return type would break existing scripts.Release date: 2026-07-23
dir.exp is used and the intermediate solution has several tied minimal solutions, QCA::minimize() splits the intermediate fit into $i.sol$C1P1$IC$individual[[k]] and $overall rather than storing a flat $sol.incl.cov, exactly as it does for the parsimonious solution. Version 2.0.4 read only the flat slot, so those cells reported inclS and covS as NA. The intermediate path now follows the same cascade as the parsimonious path: the displayed solution’s own fit for extract_mode = "first", and the aggregate for "all" and "essential". Cells that reported a fit in 2.0.4 are unchanged.compute_fiss_core() no longer biases conditions toward “core” when the parsimonious solution has several tied minimal solutions. The terms of all minimal solutions were pooled before the condition-status map was built, so a condition present in one minimal solution and absent in another ended up holding both statuses. An intermediate term then matched whichever polarity it used, and the condition was classified core either way. A status now counts only where every minimal parsimonious solution agrees, following the same principle as essential prime implicants: what cannot be asserted regardless of which minimal solution is selected is not treated as core. Cells with a single minimal parsimonious solution, which are the common case, are unaffected.compute_fiss_core() now records parsim_n_solutions for each threshold and warns when the parsimonious solution has tied minimal solutions, so the ambiguity behind a classification is visible rather than hidden.extract_solution_metrics_for_chart() and extract_path_metrics_for_chart() had the same gap. There it produced not NA but a silent fall-through to the parsimonious values, so configuration charts could show the parsimonious fit and the parsimonious per-term table for a displayed intermediate solution with several minimal solutions.inclS and covS are NA for that reason, instead of returning an unexplained NA.qca_extract(), both chart helpers, generate_report(), and the sweep functions end to end.Release date: 2026-07-22
dir.exp is specified, the sweep functions display the intermediate solution (sol$i.sol$C1P1$solution), but qca_extract() read inclS/covS from sol$IC, which describes the parsimonious solution. The displayed intermediate formula was therefore paired with the parsimonious fit: for a single parsimonious solution via sol$IC$sol.incl.cov, and for several (tied) parsimonious solutions via sol$IC$overall (the disjunction of the parsimonious solutions). The extractor now branches on the displayed solution and reads sol$i.sol$C1P1$IC$sol.incl.cov for intermediate solutions, so the fit matches the displayed expression and QCA::minimize()’s own print(). This affects the intermediate-solution output of otSweep(), ctSweepS(), ctSweepM(), and dtSweep() in every extract_mode, whether the cell has one or several minimal solutions.sol$IC$individual[[1]] rather than sol$IC$overall) is retained. Complex and parsimonious solutions, crisp-set analyses, single-solution cells, and no-solution cells are unchanged.extract_all_metrics() (used by generate_report()) and in the internal chart helpers extract_solution_metrics_for_chart() and extract_path_metrics_for_chart(): with multiple minimal solutions they reported the overall aggregate rather than the displayed solution’s own fit, and for intermediate solutions they could report the parsimonious fit. They now prefer the intermediate solution (when dir.exp is used) and then the displayed solution’s individual[[k]] fit, falling back to overall only when the per-solution fit is unavailable. generate_report() and the configuration charts now show fit measures consistent with the sweep tables.generate_report() now reports the intermediate fit in every section. Beyond the extractor fix above, the report’s “Solution Fit” and “Cross-Threshold Comparison” sections passed sol$IC (the parsimonious solution) to the extractor even when the displayed solution was the intermediate one, so those sections showed the parsimonious inclS/covS (and a parsimonious per-term row) under an intermediate formula, contradicting the report’s own Summary Table and its embedded QCA verification output. Both call sites now select sol$i.sol$C1P1$IC for intermediate solutions, matching the Summary Table. Non-intermediate reports are byte-for-byte unchanged.Release date: 2026-07-22
QCA::minimize() returns more than one minimal solution, it stores the fit of each solution in sol$IC$individual[[k]]$sol.incl.cov and the fit of the disjunction of all solutions in sol$IC$overall$sol.incl.cov. With extract_mode = "first" (the default) the sweep functions display the first solution (M1), but the internal extractor qca_extract() reported the overall aggregate for inclS/covS, so the printed formula (M1) and the printed fit did not correspond. The extractor now reads sol$IC$individual[[1]]$sol.incl.cov for the first solution. This affects otSweep(), ctSweepS(), ctSweepM(), and dtSweep(), which share qca_extract().
overall (the union coverage) is greater than any single solution’s coverage; the previously reported covS was biased upward. covS is the materially affected measure; inclS differs only marginally.extract_mode = "all" and extract_mode = "essential" still report the overall aggregate, which is appropriate because those modes summarize across all solutions rather than displaying one.Release date: 2026-07-15
DESCRIPTION and the package-level help. The robustness protocol at doi:10.1177/00491241211036158 is by Oana and Schneider (2024), not “Rubinson et al. (2019)”. The vignettes and README already cited this work correctly; this aligns the package metadata with them.inst/CITATION now derives the package version dynamically via paste("R package version", meta$Version) instead of hard-coding it.Release date: 2026-07-xx
QCA::truthTable() type issues before minimization. With QCA 3.25 / admisc 0.40, truthTable() can, for sparse truth tables, return the incl/PRI columns as character and represent logical-remainder rows (observed n = 0) with the string "-". Passing such a truth table to QCA::minimize() can, for some truth table structures, cause the minimization to hang or return misleading fit values. All sweep functions (otSweep(), ctSweepS(), ctSweepM(), dtSweep()) and the Fiss parsimonious step now coerce these columns to numeric and set remainder rows to 0 via an internal sanitize_truthtable() helper before calling minimize(). The OUT column is left untouched, so remainder handling is unaffected.Release date: 2026-05-XX
The package has been renamed from TSQCA to ThSQCA (Threshold-Sweep QCA).
Reviewers noted that TSQCA risks being misread as Time-Series QCA, since ts is the base R class for time-series objects. The new name ThSQCA unambiguously reflects the “Threshold-Sweep” methodology described in Toyoda (2026b, Quality & Quantity).
Users of TSQCA should update their code as follows:
# Old
install.packages("TSQCA")
library(TSQCA)
# New
install.packages("ThSQCA")
library(ThSQCA)All function names (otSweep, ctSweepS, ctSweepM, dtSweep, etc.) and internal logic remain unchanged. TSQCA will remain on CRAN for backward compatibility but will not receive further updates.
Release date: 2026-03-14
Three new functions implement the core/peripheral distinction introduced by Fiss (2011, Academy of Management Journal), which distinguishes between conditions that are central to a causal configuration and those that merely supplement it:
compute_fiss_core(result, conditions) — Augments any sweep result object with core/peripheral classification. For each threshold, it automatically re-runs QCA::minimize() with dir.exp = NULL to obtain the parsimonious solution, then compares it to the already-stored intermediate solution. Conditions appearing in both solutions are classified as core; conditions appearing only in the intermediate solution are classified as peripheral.
generate_fiss_chart(result, conditions, symbol_set, language) — Generates a Markdown-formatted cross-threshold configuration chart using four distinct symbols:
| Symbol (unicode) | Symbol (latex) | Symbol (ascii) | Meaning |
|---|---|---|---|
| ● | $\bullet$ |
O | Core condition present |
| ⊗ | $\otimes$ |
X | Core condition absent |
| ⊙ | $\odot$ |
o | Peripheral condition present |
| ⊘ | $\oslash$ |
x | Peripheral condition absent |
print_fiss_summary(result, thr_key, language) — Prints a human-readable summary of the core/peripheral classification for a specific threshold value.
Usage:
# Step 1: Run intermediate sweep (include = "?" + dir.exp required)
res <- otSweep(
dat = sample_data, outcome = "Y",
conditions = c("X1", "X2", "X3"),
sweep_range = 6:8, thrX = c(X1 = 7, X2 = 7, X3 = 7),
include = "?", dir.exp = c(1, 1, 1),
return_details = TRUE
)
# Step 2: Compute Fiss classification
res_fiss <- compute_fiss_core(res, conditions = c("X1", "X2", "X3"))
# Step 3: Generate Fiss-style four-symbol chart
cat(generate_fiss_chart(res_fiss, symbol_set = "unicode"))
cat(generate_fiss_chart(res_fiss, symbol_set = "latex")) # for papers
# Step 4: Inspect a specific threshold
print_fiss_summary(res_fiss, thr_key = "7")Prerequisites: compute_fiss_core() requires return_details = TRUE, include = "?", and dir.exp to be specified in the original sweep. If any of these are missing, an informative error is raised.
generate_report()
generate_report() gains a new include_fiss_core argument (default FALSE). When set to TRUE on a result augmented by compute_fiss_core(), all configuration charts in the report use the four-symbol Fiss notation and the Notes section includes the Fiss (2011) reference and symbol legend.
res_fiss <- compute_fiss_core(res)
generate_report(res_fiss, "report.md",
include_fiss_core = TRUE,
chart_symbol_set = "unicode")get_config_labels)Both English and Japanese label dictionaries in get_config_labels() now include Fiss-specific entries: fiss_core, fiss_peripheral, fiss_parsim, fiss_interm, fiss_note.
SYMBOL_SETS_FISS constant (analogous to SYMBOL_SETS) with four-symbol sets for unicode, latex, and ascii output formats.extract_cond_status_map(), classify_term_conditions(), run_parsimonious(), extract_sol_terms(), build_fiss_matrix().write_full_report() and write_simple_report() accept a new use_fiss logical parameter propagated from generate_report().TSQCA_Tutorial_EN.Rmd gains a new section “Fiss (2011) Core/Peripheral Classification (New in v1.3.2)” with full workflow and interpretation guidance.TSQCA_Reproducible_EN.Rmd gains a new Section 12 with complete reproducible Fiss workflow code.compute_fiss_core, generate_fiss_chart, print_fiss_summary, and SYMBOL_SETS_FISS.Fiss, P. C. (2011). Building better causal theories: A fuzzy set approach to typologies in organization research. Academy of Management Journal, 54(2), 393–420. doi:10.5465/amj.2011.60263120
Release date: 2026-02-18
pre_calibrated vignette section. The example referenced variables not included in the bundled sample_data. The section now provides a prose description of the feature; a worked example will be added when a suitable public dataset is available.@param documentation for thrX, thrX_default, sweep_list, and sweep_list_X: pre-calibrated variables do not require a threshold entry (the previous documentation incorrectly stated otherwise).Release date: 2026-02-18
All four sweep functions (otSweep, dtSweep, ctSweepS, ctSweepM) now support a pre_calibrated argument. Variables listed in pre_calibrated are passed through to QCA::truthTable() without binarization, enabling mixed crisp/fuzzy analyses where some conditions are pre-calibrated via QCA::calibrate() while others are binarized by threshold sweep.
Usage:
# AGE is pre-calibrated as a fuzzy set; other conditions are binarized
result <- otSweep(
dat = dat,
outcome = "INT",
conditions = c("CHT", "PRC", "UNQ", "AGE", "GEN"),
sweep_range = 6:9,
thrX = c(CHT = 7, PRC = 7, UNQ = 7, AGE = 0.5, GEN = 1),
pre_calibrated = c("AGE"),
include = "?",
dir.exp = c(1, 1, 1, "-", "-"),
incl.cut = 0.80,
n.cut = 2,
pri.cut = 0.50
)Validation: The function raises an error if a pre-calibrated variable is not found in conditions, or if its values fall outside the [0, 1] range. A warning is issued if a pre-calibrated variable is also listed as a sweep target (in sweep_list_X / sweep_list), since threshold sweeping has no effect on fixed fuzzy values.
Backward compatibility: When pre_calibrated = NULL (the default), all functions produce exactly the same output as v1.2.0.
prepare_dat_bin() in tsqca_core.R centralizes data preparation logic, replacing the inline binarization code that was duplicated across all four sweep functions.validate_pre_calibrated() in tsqca_core.R performs input validation for the pre_calibrated parameter.pre_calibrated is now stored in the params object returned by all sweep functions (when return_details = TRUE).generate_report() now displays pre-calibrated conditions in the Analysis Overview section.Release date: 2026-01-19
Problem: When dir.exp is specified for intermediate solutions, the QCA package stores: - sol$solution — Contains the Parsimonious solution - sol$i.sol$C1P1$solution — Contains the true Intermediate solution
Previous versions of TSQCA incorrectly prioritized sol$solution, causing Parsimonious solutions to be extracted and displayed when Intermediate solutions were expected.
Fix: All solution extraction functions now correctly prioritize sol$i.sol when available:
get_n_solutions() — Now checks i.sol firstqca_extract() — Now checks i.sol firstextract_solution_list() — Now checks i.sol firstwrite_full_report() — Fixed 3 locationswrite_simple_report() — Fixed 1 locationImpact: Users who specified dir.exp for intermediate solutions may have received incorrect results in: - Report generation (generate_report()) - Configuration charts - Solution expression extraction
Verification: The print(sol) output was always correct because the QCA package’s print method handles this correctly. Only programmatic extraction was affected.
Reports now explicitly display the solution type in the Analysis Overview section:
| Include | dir.exp | Solution Type |
|---|---|---|
"" |
any | Complex (Conservative) |
"?" |
NULL |
Parsimonious |
"?" |
specified | Intermediate |
Added optional raw QCA output section to reports for verification purposes:
generate_report(result, "report.md", include_raw_output = TRUE) # default
generate_report(result, "report.md", include_raw_output = FALSE) # disableWhen enabled, each threshold’s detailed results include:
#### QCA Package Output (for verification)
DEVURBLITSTB + DEVLIT~INDSTB -> SURV
This allows researchers to verify that TSQCA’s extraction matches the QCA package’s native output.
Release date: 2026-01-17
dir.exp = NULL BehaviorProblem: In v1.0.0, when dir.exp = NULL (the default), the package incorrectly converted it to c(1, 1, ...), which forced intermediate solution calculation regardless of user intent.
Fix: dir.exp = NULL is now correctly passed to QCA::minimize() without modification.
To ensure consistency with the QCA package, default argument values have been changed:
| Argument | v1.0.0 Default | v1.1.0 Default | Effect |
|---|---|---|---|
include |
"?" |
"" |
Complex solution (no logical remainders) |
dir.exp |
NULL → c(1,1,...) (bug) |
NULL |
No directional expectations |
Result: TSQCA now produces complex solutions by default, matching QCA::minimize() default behavior.
| Solution Type | How to Compute |
|---|---|
| Complex (default) |
include = "", dir.exp = NULL
|
| Parsimonious |
include = "?", dir.exp = NULL
|
| Intermediate |
include = "?", dir.exp = c(1, 1, ...)
|
# v1.0.0 (incorrect: intermediate solution by default due to bug)
result <- otSweep(dat, "Y", c("X1", "X2", "X3"), sweep_range = 7, thrX = thrX)
# v1.1.0: Complex solution (new default, QCA compatible)
result_comp <- otSweep(dat, "Y", c("X1", "X2", "X3"), sweep_range = 7, thrX = thrX)
# v1.1.0: Parsimonious solution (include = "?")
result_pars <- otSweep(dat, "Y", c("X1", "X2", "X3"), sweep_range = 7, thrX = thrX,
include = "?")
# v1.1.0: Intermediate solution (include = "?" + dir.exp)
result_int <- otSweep(dat, "Y", c("X1", "X2", "X3"), sweep_range = 7, thrX = thrX,
include = "?",
dir.exp = c(1, 1, 1))All four sweep functions (otSweep, dtSweep, ctSweepS, ctSweepM) now include examples demonstrating:
include = "?"
include = "?" with dir.exp
The @param dir.exp and @param include documentation now clearly explains: - Default behavior produces complex solutions (QCA compatible) - include = "?" enables logical remainders for parsimonious/intermediate - dir.exp specifies directional expectations for intermediate solutions
Release date: 2026-01-06
The default value for chart_level parameter has been changed from "summary" to "term".
Rationale: The solution-term level format (Fiss, 2011 notation) is the standard for academic publications, where each column represents one prime implicant (configuration). The previous default ("summary") aggregated all configurations at each threshold into a single column, which obscured the distinction between different sufficient paths.
Column header format updated: - Old format: thrY=6_M1 - New format: thrY = 6 (M1) (consistent with the paper format)
Affected functions: - generate_report() — default chart_level is now "term" - generate_cross_threshold_chart() — default chart_level is now "term"
Migration: If you prefer the previous behavior (threshold-level summary), explicitly specify chart_level = "summary":
generate_report(result, "report.md", chart_level = "summary")
generate_cross_threshold_chart(result, conditions, chart_level = "summary")Release date: 2026-01-03
Added support for solution-term level configuration charts following Fiss (2011) notation. This feature allows generating charts where each column represents a single prime implicant (configuration), which is the standard format for academic publications.
New parameter for generate_report():
chart_level — Character. Either "summary" (default) or "term".
"summary": Threshold-level summaries where each column represents one threshold, showing all conditions that appear in any configuration at that threshold."term": Solution-term level (Fiss-style) where each column represents one prime implicant (sufficient configuration). Recommended for academic publications.New functions:
generate_cross_threshold_chart() — Generate configuration charts from sweep results with chart_level option.parse_solution_terms() — Internal function to parse solution expressions into individual terms.get_condition_status() — Internal function to determine condition presence/absence in a term.generate_term_level_chart() — Internal function for term-level chart generation.generate_threshold_level_chart() — Internal function for threshold-level chart generation.Example:
# Threshold-level summary (default)
generate_report(result, "report.md", chart_level = "summary")
# Solution-term level (Fiss-style, recommended for publications)
generate_report(result, "report.md", chart_level = "term")When the solution is X3 + X1*X2, the term-level chart will show two separate columns (thrY=7_M1 for X3 and thrY=7_M2 for X1*X2), while the summary-level chart shows one column (thrY=7) with all three conditions marked.
Release date: 2026-01-03
Fixed non-working code examples in all vignettes (Tutorial and Reproducible, both EN/JA):
Yvar/Xvars to outcome/conditions
ctSweepM() examples to use sweep_list parameter instead of old sweep_vars/sweep_range
dat parameter to all generate_report() exampleshead(res$summary) to summary(res) for consistency with S3 methodsoutcome, conditions)dat parameter to generate_report() examplesRelease date: 2026-01-01
When multiple logically equivalent solutions (M1, M2, M3…) exist, configuration charts now automatically include a note explaining that M1 is displayed.
New parameters for generate_report():
solution_note — Logical. If TRUE (default), adds note when multiple solutions existsolution_note_style — "simple" (default) or "detailed" (includes EPIs)solution_note_lang — "en" (default) or "ja" for JapaneseNew parameters for config_chart_from_paths():
n_sol — Number of equivalent solutions (triggers note if > 1)solution_note — Logical. Whether to add solution notesolution_note_style — "simple" or "detailed"
epi_list — Character vector of EPIs for detailed notesNew exported functions:
generate_solution_note() — Generate solution note textidentify_epi() — Identify Essential Prime Implicants from multiple solutionsExample output (simple):
*Note: 2 logically equivalent solutions were identified. This table presents configurations based on M1.*
Example output (detailed with EPIs):
*Note: 3 logically equivalent solutions were identified (M1-M3). This table presents configurations based on M1. All solutions share the essential prime implicants: A·B and C.*
Example (Japanese):
*注: 論理的に等価な2つの解が得られた。本表はM1に基づく構成を示す。*
Release date: 2025-12-31
Configuration charts are now automatically included in reports generated by generate_report().
New parameters for generate_report():
include_chart — Logical. If TRUE (default), includes Fiss-style configuration chartschart_symbol_set — Symbol set: "unicode" (default), "ascii", or "latex"
Example:
# Generate report with configuration charts (default)
generate_report(result, "my_report.md", format = "full")
# Generate report without charts
generate_report(result, "my_report.md", include_chart = FALSE)
# Generate report with LaTeX symbols (for PDF/academic papers)
generate_report(result, "my_report.md", chart_symbol_set = "latex")generate_config_chart() — Generate chart from QCA solution objectconfig_chart_from_paths() — Generate chart from path strings (e.g., “AB~C”)config_chart_multi_solutions() — Generate separate charts for multiple solutionsFeatures:
"unicode" (● / ⊗), "ascii" (O / X), "latex" ( / )Fixed incorrect use of “Core Conditions” terminology:
| Old (incorrect) | New (correct) | Meaning |
|---|---|---|
extract_mode = "core" |
extract_mode = "essential" |
Mode for extracting shared terms |
core_terms |
essential_terms |
Terms in ALL solutions |
peripheral_terms |
selective_terms |
Terms in SOME solutions |
Migration: Change extract_mode = "core" to extract_mode = "essential".
Fixed incorrect use of “Core Conditions” terminology. The terms that appear in ALL equivalent solutions (M1, M2, M3…) are now correctly called Essential Prime Implicants (EPI), following standard Boolean minimization terminology.
Changed terms:
| Old (incorrect) | New (correct) | Meaning |
|---|---|---|
extract_mode = "core" |
extract_mode = "essential" |
Mode for extracting shared terms |
core_terms |
essential_terms |
Terms in ALL solutions |
peripheral_terms |
selective_terms |
Terms in SOME solutions |
| “Core Conditions” | “Essential Prime Implicants (EPI)” | Report labels |
| “Peripheral Terms” | “Selective Prime Implicants (SPI)” | Report labels |
Why this matters:
The term “Core Conditions” in QCA literature (Fiss, 2011) refers to conditions appearing in both parsimonious AND intermediate solutions—a comparison between solution types. This is distinct from terms shared across multiple equivalent solutions of the same type, which are properly called “Essential Prime Implicants” in Boolean algebra terminology.
Migration:
If you used extract_mode = "core" in previous versions, change to extract_mode = "essential". The output structure is identical; only the names have changed for methodological accuracy.
Added functions for generating Fiss-style configuration charts (Table 5 format) commonly used in QCA publications.
New functions:
generate_config_chart() — Generate configuration chart from QCA solution objectconfig_chart_from_paths() — Generate chart from path strings (e.g., “AB~C”)config_chart_multi_solutions() — Generate separate charts for multiple solutionsFeatures:
"unicode" (● / ⊗), "ascii" (O / X), "latex" ( / )Example:
# From QCA solution object
chart <- generate_config_chart(sol, symbol_set = "unicode")
cat(chart)
# From path strings
paths <- c("A*B*~C", "A*D")
chart <- config_chart_from_paths(paths)
cat(chart)result$details
generate_report() for dtSweep and ctSweepM resultsotSweep_result, dtSweep_result, ctSweepS_result, ctSweepM_result inherit from tsqca_result
print() methods for all result types
summary() methods for all result types
Yvar to outcome and Xvars to conditions in all sweep functions
Yvar, Xvars) are still supported with deprecation warningsoutcome = "~Y")
truthTable() convention for negationotSweep(), dtSweep(), ctSweepS(), ctSweepM()
generate_report() now displays “(negated)” indicator when analyzing negated outcomes
# Old syntax (still works, but shows deprecation warning)
result <- otSweep(dat, Yvar = "Y", Xvars = c("X1", "X2"), ...)
# New syntax (recommended)
result <- otSweep(dat, outcome = "Y", conditions = c("X1", "X2"), ...)
# Negated outcome (new feature)
result <- otSweep(dat, outcome = "~Y", conditions = c("X1", "X2"), ...)extract_mode parameter to all sweep functions (otSweep(), dtSweep(), ctSweepS(), ctSweepM()) with three options:
"first" (default): Returns only the first solution (M1), maintaining backward compatibility"all": Returns all intermediate solutions concatenated (e.g., “M1: AB; M2: AC”)"essential": Returns essential prime implicants common to all solutions, plus peripheral and unique termsget_n_solutions() helper function to count the number of intermediate solutionsgenerate_report() function for automatic markdown report generation with two formats:
"full": Comprehensive report including all analysis details, solution formulas, and fit measures"simple": Condensed format designed for journal manuscript supplementary materialsreturn_details default from FALSE to TRUE for better integration with generate_report()
n.cut default from 2 to 1 to align with QCA package conventionspri.cut default from 0.5 to 0 to align with QCA package conventionsctSweepS(): Single-condition X sweep (CTS-QCA)ctSweepM(): Multi-condition X sweep (MCTS-QCA)otSweep(): Outcome Y sweep (OTS-QCA)dtSweep(): Two-dimensional X and Y sweep (DTS-QCA)qca_bin(), qca_extract()