File size: 11,611 Bytes
cf52a55 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | """
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
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Estrutura de um silogismo
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
@dataclass
class Syllogism:
major: str # premissa maior (universal)
minor: str # premissa menor (particular/singular)
conclusion: str # conclusΓ£o derivada
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}"
)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# As 8 regras do silogismo cientΓfico
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
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)
# R1 β Apenas trΓͺs termos, cada um no mesmo sentido
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: # heurΓstica liberal
violations.append("R1: mais de trΓͺs termos distintos detectados")
# R2 β Termo mΓ©dio nΓ£o aparece na conclusΓ£o
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")
# R3 β ConclusΓ£o nΓ£o excede extensΓ£o das premissas
if not c_part and (m_part or n_part):
violations.append("R3: conclusΓ£o mais extensa que as premissas")
# R4 β Termo mΓ©dio deve ser universal pelo menos uma vez
if m_part and n_part:
violations.append("R4: termo mΓ©dio nunca Γ© universal")
# R5 β De duas negativas, nada se conclui
if m_neg and n_neg:
violations.append("R5: duas premissas negativas β conclusΓ£o invΓ‘lida")
# R6 β Duas afirmativas β conclusΓ£o afirmativa
if not m_neg and not n_neg and c_neg:
violations.append("R6: premissas afirmativas exigem conclusΓ£o afirmativa")
# R7 β De duas particulares, nada se conclui
if m_part and n_part:
violations.append("R7: duas premissas particulares β conclusΓ£o invΓ‘lida")
# R8 β "Parte Fraca": conclusΓ£o segue a premissa mais fraca
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
# ββ helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββ #
@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}
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Filtro de Hempel (anti-confirmaΓ§Γ£o espΓΊria)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
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 # pouca sobreposiΓ§Γ£o = provΓ‘vel espΓΊrio
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PrincΓpio da Falseabilidade de Popper
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
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]], # (juΓzo, score_BD)
) -> 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:
# ProposiΓ§Γ΅es universais: presume falso atΓ© evidΓͺncia forte
if j.quantidade == "Universal":
adjusted = score if score >= self.floor else 0.0
falsified = adjusted < self.floor
# Singulares: usa o score direto
else:
adjusted = score
falsified = False
result.append((j, adjusted, falsified))
return result
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Pipeline integrado
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
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, # termo_proposicao β score [0,1]
) -> List[Tuple[KantianJudgment, float]]:
"""
Filtra e pontua as hipΓ³teses.
Retorna lista ordenada de (juΓzo, score_final).
"""
# 1. Remove hipΓ³teses espΓΊrias (Hempel)
non_spurious = [
j for j in judgments
if not self.hempel.is_spurious(j, prompt_terms)
]
# 2. Valida via silogismo (usa prioridade L2 como par maior/menor)
scored: List[Tuple[KantianJudgment, float]] = []
for j in non_spurious:
# ConstrΓ³i silogismo sintΓ©tico para validaΓ§Γ£o
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)))
# 3. Aplica falseabilidade (Popper)
with_falsifiability = self.popper.apply(scored)
# 4. Remove falsificadas e reordena
valid = [
(j, score)
for j, score, falsified in with_falsifiability
if not falsified
]
valid.sort(key=lambda x: x[1], reverse=True)
return valid
|