| """ |
| MΓDULO β Silogismo CientΓfico AristotΓ©lico + Paradoxo de Hempel + Popper |
| ========================================================================= |
| Integrado entre L2 e L3 (etapa 4 e 5 do fluxo). |
| |
| Filtra as hipΓ³teses kantianas pelas 8 regras do silogismo cientΓfico e |
| aplica o princΓpio da falseabilidade: toda conclusΓ£o Γ© tratada como |
| FALSA atΓ© que se encontre evidΓͺncia verdadeira equivalente. |
| |
| Paradoxo de Hempel implementado como filtro negativo: |
| Nem toda palavra posterior pode ser inferida da anterior. |
| Objetos irrelevantes nΓ£o validam uma teoria. |
| """ |
|
|
| from __future__ import annotations |
| from dataclasses import dataclass |
| from typing import List, Optional, Tuple |
| from l2_kantian_judgments import KantianJudgment |
|
|
|
|
| |
| |
| |
|
|
| @dataclass |
| class Syllogism: |
| major: str |
| minor: str |
| conclusion: str |
| valid: bool = True |
| violations: List[str] = None |
|
|
| def __post_init__(self): |
| if self.violations is None: |
| self.violations = [] |
|
|
| def __str__(self) -> str: |
| status = "β VΓLIDO" if self.valid else f"β INVΓLIDO ({'; '.join(self.violations)})" |
| return ( |
| f" Maior : {self.major}\n" |
| f" Menor : {self.minor}\n" |
| f" Concl.: {self.conclusion}\n" |
| f" Status: {status}" |
| ) |
|
|
|
|
| |
| |
| |
|
|
| class AristotelianSyllogismValidator: |
| """ |
| Valida um silogismo segundo as 8 regras aristotΓ©licas e retorna |
| a lista de violaΓ§Γ΅es (vazia se vΓ‘lido). |
| """ |
|
|
| def validate(self, major: str, minor: str, conclusion: str) -> List[str]: |
| violations: List[str] = [] |
| m_neg = self._is_negative(major) |
| n_neg = self._is_negative(minor) |
| c_neg = self._is_negative(conclusion) |
| m_part = self._is_particular(major) |
| n_part = self._is_particular(minor) |
| c_part = self._is_particular(conclusion) |
|
|
| |
| terms_m = self._extract_key_terms(major) |
| terms_n = self._extract_key_terms(minor) |
| terms_c = self._extract_key_terms(conclusion) |
| all_terms = terms_m | terms_n | terms_c |
| if len(all_terms) > 6: |
| violations.append("R1: mais de trΓͺs termos distintos detectados") |
|
|
| |
| middle = terms_m & terms_n - terms_c |
| if not middle and terms_m & terms_n: |
| violations.append("R2: termo mΓ©dio pode estar na conclusΓ£o") |
|
|
| |
| if not c_part and (m_part or n_part): |
| violations.append("R3: conclusΓ£o mais extensa que as premissas") |
|
|
| |
| if m_part and n_part: |
| violations.append("R4: termo mΓ©dio nunca Γ© universal") |
|
|
| |
| if m_neg and n_neg: |
| violations.append("R5: duas premissas negativas β conclusΓ£o invΓ‘lida") |
|
|
| |
| if not m_neg and not n_neg and c_neg: |
| violations.append("R6: premissas afirmativas exigem conclusΓ£o afirmativa") |
|
|
| |
| if m_part and n_part: |
| violations.append("R7: duas premissas particulares β conclusΓ£o invΓ‘lida") |
|
|
| |
| if (m_neg or n_neg) and not c_neg: |
| violations.append("R8: premissa negativa exige conclusΓ£o negativa") |
| if (m_part or n_part) and not c_part and not c_neg: |
| violations.append("R8: premissa particular exige conclusΓ£o particular") |
|
|
| return violations |
|
|
| |
|
|
| @staticmethod |
| def _is_negative(text: str) -> bool: |
| neg_markers = {"nΓ£o", "nunca", "nenhum", "jamais", "nem", "negativo"} |
| return any(w in text.lower().split() for w in neg_markers) |
|
|
| @staticmethod |
| def _is_particular(text: str) -> bool: |
| part_markers = {"algum", "alguma", "alguns", "algumas", "certo", |
| "parte", "pode", "possΓvel"} |
| return any(w in text.lower().split() for w in part_markers) |
|
|
| @staticmethod |
| def _extract_key_terms(text: str) -> set: |
| stop = {"Γ©", "sΓ£o", "de", "do", "da", "em", "com", "por", |
| "para", "este", "esta", "esse", "toda", "todo", "um", "uma"} |
| import re |
| tokens = re.findall(r"[a-zÑà ãÒéΓͺΓóôáúüçA-ZΓΓΓΓΓΓΓΓΓΓΓΓΓ]+", text.lower()) |
| return {t for t in tokens if t not in stop and len(t) > 2} |
|
|
|
|
| |
| |
| |
|
|
| class HempelFilter: |
| """ |
| Paradoxo de Hempel: objetos irrelevantes nΓ£o devem confirmar hipΓ³teses. |
| Implementado como detecΓ§Γ£o de correlaΓ§Γ΅es espΓΊrias entre termos do |
| prompt e termos do banco de dados sem relaΓ§Γ£o semΓ’ntica real. |
| """ |
|
|
| def __init__(self, relevance_threshold: float = 0.25) -> None: |
| self.threshold = relevance_threshold |
|
|
| def is_spurious(self, judgment: KantianJudgment, prompt_terms: set) -> bool: |
| """ |
| Retorna True se a hipΓ³tese Γ© provavelmente espΓΊria |
| (confirmaΓ§Γ£o por objeto irrelevante). |
| """ |
| import re |
| hyp_terms = set(re.findall( |
| r"[a-zÑà ãÒéΓͺΓóôáúüçA-ZΓΓΓΓΓΓΓΓΓΓΓΓΓ]+", |
| judgment.proposicao.lower() |
| )) |
| overlap = len(hyp_terms & prompt_terms) / max(len(hyp_terms), 1) |
| return overlap < self.threshold |
|
|
|
|
| |
| |
| |
|
|
| class PopperFalsifiability: |
| """ |
| Toda conclusΓ£o Γ© tratada como FALSA atΓ© que se encontre evidΓͺncia |
| verdadeira equivalente no banco de dados. |
| |
| Implementa o princΓpio do Cisne Negro: a proposiΓ§Γ£o universal |
| "todo cisne Γ© branco" Γ© falsa atΓ© que seja falsificada por um cisne preto. |
| """ |
|
|
| def __init__(self, falsifiability_floor: float = 0.1) -> None: |
| """ |
| falsifiability_floor : score mΓnimo de evidΓͺncia para aceitar |
| a hipΓ³tese como nΓ£o-falsificada. |
| """ |
| self.floor = falsifiability_floor |
|
|
| def apply( |
| self, |
| hypotheses: List[Tuple[KantianJudgment, float]], |
| ) -> List[Tuple[KantianJudgment, float, bool]]: |
| """ |
| Retorna triplas (juΓzo, score, falsificada?). |
| HipΓ³teses universais afirmativas partem sempre de score 0 |
| (falsas atΓ© prova em contrΓ‘rio). |
| """ |
| result = [] |
| for j, score in hypotheses: |
| |
| if j.quantidade == "Universal": |
| adjusted = score if score >= self.floor else 0.0 |
| falsified = adjusted < self.floor |
| |
| else: |
| adjusted = score |
| falsified = False |
| result.append((j, adjusted, falsified)) |
| return result |
|
|
|
|
| |
| |
| |
|
|
| class ScientificSyllogismPipeline: |
| """ |
| Integra: Silogismo AristotΓ©lico + Filtro de Hempel + Falseabilidade. |
| Chamado entre L2 e L3. |
| """ |
|
|
| def __init__(self) -> None: |
| self.validator = AristotelianSyllogismValidator() |
| self.hempel = HempelFilter() |
| self.popper = PopperFalsifiability() |
|
|
| def run( |
| self, |
| judgments: List[KantianJudgment], |
| prompt_terms: set, |
| kb_scores: dict, |
| ) -> List[Tuple[KantianJudgment, float]]: |
| """ |
| Filtra e pontua as hipΓ³teses. |
| Retorna lista ordenada de (juΓzo, score_final). |
| """ |
| |
| non_spurious = [ |
| j for j in judgments |
| if not self.hempel.is_spurious(j, prompt_terms) |
| ] |
|
|
| |
| scored: List[Tuple[KantianJudgment, float]] = [] |
| for j in non_spurious: |
| |
| major = f"Universal: {j.proposicao}" |
| minor = f"Singular: {j.proposicao}" |
| conclusion = j.proposicao |
| violations = self.validator.validate(major, minor, conclusion) |
| penalty = len(violations) * 0.1 |
| base_score = kb_scores.get(j.proposicao[:30], j.prioridade) |
| scored.append((j, max(0.0, base_score - penalty))) |
|
|
| |
| with_falsifiability = self.popper.apply(scored) |
|
|
| |
| valid = [ |
| (j, score) |
| for j, score, falsified in with_falsifiability |
| if not falsified |
| ] |
| valid.sort(key=lambda x: x[1], reverse=True) |
| return valid |
|
|