Source code for txgraffiti.logic.conjectures

# txgraffiti.logic.conjectures.py

import pandas as pd
from txgraffiti.logic.predicates import Predicate

# ───────── Conjecture ─────────

__all__ = [
    'Conjecture',
]

[docs] class Conjecture(Predicate): """ A logical implication between two predicates. Represents a rule of the form: (hypothesis) → (conclusion). Parameters ---------- hypothesis : Predicate The antecedent of the implication. conclusion : Predicate The consequent of the implication. Examples -------- >>> from txgraffiti.logic import KnowledgeTable, Conjecture >>> df = KnowledgeTable({ ... 'alpha': [1, 2, 3], ... 'beta': [3, 1, 1], ... 'connected': [True, True, True], ... 'tree': [False, False, True], ... }) >>> alpha = df.alpha >>> beta = df.beta >>> connected = df.connected >>> conj = Conjecture(connected, beta >= alpha - 2) >>> conj.is_true(df) True """ def __init__(self, hypothesis: Predicate, conclusion: Predicate): name = f"({hypothesis.name}) → ({conclusion.name})" func = lambda df: (~hypothesis(df)) | conclusion(df) super().__init__(name, func) object.__setattr__(self, 'hypothesis', hypothesis) object.__setattr__(self, 'conclusion', conclusion)
[docs] def is_true(self, df: pd.DataFrame) -> bool: """ Check if the conjecture holds on all rows of the DataFrame. Parameters ---------- df : pd.DataFrame The data to evaluate. Returns ------- bool True if all rows satisfy the implication. """ return bool(self(df).all())
[docs] def accuracy(self, df: pd.DataFrame) -> float: """ Compute the conditional accuracy of the conjecture. This is defined as the fraction of rows satisfying the conclusion among those satisfying the hypothesis. Parameters ---------- df : pd.DataFrame The data to evaluate. Returns ------- float The accuracy of the conjecture. """ hyp = self.hypothesis(df) if not hyp.any(): return 0.0 return float(self(df)[hyp].mean())
[docs] def counterexamples(self, df: pd.DataFrame) -> pd.DataFrame: """ Return the rows that violate the conjecture. Parameters ---------- df : pd.DataFrame The data to search. Returns ------- pd.DataFrame Subset of rows where the implication fails. """ return df[~self(df)]
def __repr__(self): return f"<Conj {self.name}>"
[docs] def contrapositive(self) -> "Conjecture": """ Return the contrapositive: ¬(conclusion) → ¬(hypothesis). """ return (~self.conclusion) >> (~self.hypothesis)