File size: 2,990 Bytes
1ed1403 | 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 | import re
from typing import List, Dict, Any
from sympy import sympify, simplify, Eq, parse_expr
def extract_equations(text: str) -> List[str]:
"""Extracts mathematical equations or expressions from a reasoning step."""
# Simplified extraction logic: finding equals signs or math blocks
# In production, uses robust RegEx or specialized NLP parsing
lines = text.split('\\n')
equations = []
for line in lines:
if "=" in line and sum(c.isalpha() for c in line) < len(line) / 2:
equations.append(line.strip())
return equations
def check_logical_progression(step_n: str, step_n_plus_1: str) -> bool:
"""
Implements the SymPy Validation function \\vartheta(r_{jl}).
Checks if step (n+1) is a logically sound derivative of step (n).
"""
eqs_n = extract_equations(step_n)
eqs_n_plus_1 = extract_equations(step_n_plus_1)
# If no math found natively, fallback to semantic/LLM truth (handled via Logic score)
if not eqs_n or not eqs_n_plus_1:
return True
try:
# Example validation: if step_n is 'a = b' and step is 'a + 1 = b + 1'
# Simplifying via SymPy
for eq1 in eqs_n:
for eq2 in eqs_n_plus_1:
e1_left, e1_right = eq1.split('=')
e2_left, e2_right = eq2.split('=')
# Verify equivalence: Left - Right should be 0
expr1 = sympify(f"({e1_left}) - ({e1_right})")
expr2 = sympify(f"({e2_left}) - ({e2_right})")
# Check if they denote the same equality (simplified algebra)
if simplify(expr1 - expr2) == 0:
return True
except Exception:
# Syntax error parsing SymPy, fall back to safe true
pass
# By default, if we can't prove it false, we assume conditional true
# MVM2 specifically flags "1=2" paradoxes
if "1 = 2" in step_n_plus_1 or "1=2" in step_n_plus_1:
return False
return True
def calculate_symbolic_score(reasoning_trace: List[str]) -> float:
"""
Calculates V^{sym}_j based on the logical sequence of steps.
Score drops linearly for every failed contiguous logic check.
"""
if len(reasoning_trace) <= 1:
return 1.0
valid_transitions = 0
total_transitions = len(reasoning_trace) - 1
for i in range(total_transitions):
is_valid = check_logical_progression(reasoning_trace[i], reasoning_trace[i+1])
if is_valid:
valid_transitions += 1
v_sym = float(valid_transitions) / float(total_transitions)
# If a critical hallucination is detected (e.g. proof of 1=2), heavily penalize
for step in reasoning_trace:
if "1 = 2" in step or "1=2" in step:
v_sym = 0.0
break
return round(v_sym, 2)
|