Source code for qca.engines.gsqca

"""Generalized-set QCA engine."""

from __future__ import annotations

from collections.abc import Sequence
from typing import Any

import pandas as pd

from qca.core.conditions import ConditionSpec, condition_specs_from_schema
from qca.engines.base import QCAEngineBase


[docs] class GSQCA(QCAEngineBase): """Generalized-set QCA over crisp, fuzzy, and multi-value conditions. ``GSQCA`` provides a generalized-set interface in which crisp-set, fuzzy-set, and multi-value QCA can be handled by a common truth-table and minimization workflow. The implementation is designed to make the generalized-set assumptions explicit in PyQCA rather than to claim one-to-one compatibility with any single external package. Multi-value conditions can be represented either by a crisp categorical column or by value-specific calibrated membership columns through :class:`qca.ConditionSpec.value_columns`. """ qca_type = "GSQCA" workflow_prefix = "GSQCA" def __init__( self, data: pd.DataFrame, case_id: str | None = None, set_conditions: Sequence[str] | None = None, multivalue_conditions: Sequence[str] | None = None, outcome: str | None = None, conditions: Sequence[str] | None = None, condition_types: dict[str, str] | None = None, condition_specs: Any | None = None, schema: Any | None = None, ) -> None: if schema is not None and condition_specs is not None: raise ValueError("schema and condition_specs cannot be combined.") normalized_specs = ( condition_specs_from_schema(schema) if schema is not None else condition_specs ) super().__init__( data=data, case_id=case_id, set_conditions=set_conditions, multivalue_conditions=multivalue_conditions, outcome=outcome, conditions=conditions, condition_types=condition_types, condition_specs=normalized_specs, )
[docs] @classmethod def from_schema( cls, data: pd.DataFrame, outcome: str, schema: Any, case_id: str | None = None, ) -> GSQCA: """Build ``GSQCA`` from a unified condition schema.""" return cls(data=data, case_id=case_id, outcome=outcome, schema=schema)
[docs] @classmethod def from_condition_specs( cls, data: pd.DataFrame, outcome: str, condition_specs: Sequence[ConditionSpec], case_id: str | None = None, ) -> GSQCA: """Build ``GSQCA`` from normalized ``ConditionSpec`` objects.""" return cls( data=data, case_id=case_id, outcome=outcome, condition_specs=condition_specs, )
@property def schema(self) -> pd.DataFrame: """Alias for the normalized condition schema.""" return self.condition_schema @property def workflow_kinds(self) -> tuple[str, ...]: """Condition kinds present in this workflow, in canonical order.""" present = set(self.condition_types.values()) return tuple(kind for kind in ("crisp", "fuzzy", "multi") if kind in present) @property def workflow(self) -> str: """Human-readable workflow label derived from the condition schema.""" kinds = self.workflow_kinds if len(kinds) == 1: return f"{self.workflow_prefix}-{kinds[0]}-only" return f"{self.workflow_prefix}-{'-'.join(kinds)}" @property def is_generalized_workflow(self) -> bool: """Whether the model combines more than one condition kind.""" return len(self.workflow_kinds) > 1 @property def has_crisp_conditions(self) -> bool: """Return whether crisp-set conditions are present.""" return "crisp" in self.workflow_kinds @property def has_fuzzy_conditions(self) -> bool: """Return whether fuzzy-set conditions are present.""" return "fuzzy" in self.workflow_kinds @property def has_multivalue_conditions(self) -> bool: """Return whether multi-value conditions are present.""" return "multi" in self.workflow_kinds def _validate(self) -> None: super()._validate() if not self.conditions: raise ValueError("GSQCA requires at least one condition.") def __repr__(self) -> str: return ( "GSQCA(" f"n_cases={self.n_cases}, " f"workflow={self.workflow!r}, " f"conditions={self.conditions}, " f"outcome={self.outcome!r}" ")" )
__all__ = ["GSQCA"]