Actualización del motor algebraico para permitir asignaciones duales, integrando ecuaciones en el contexto de SymPy. Se mejora la gestión de variables y se optimiza la lógica de resolución, asegurando que las soluciones se apliquen correctamente al sistema. Se actualiza el historial de cálculos con nuevas expresiones.
This commit is contained in:
parent
242d5095af
commit
b7e35d1ae3
|
@ -1,9 +1,12 @@
|
|||
|
||||
61.6/2.54
|
||||
x=t**2+5/m
|
||||
t=?
|
||||
|
||||
m=3
|
||||
x=4
|
||||
|
||||
t=?
|
||||
|
||||
k=2.54
|
||||
|
||||
1080/1440
|
||||
|
||||
1920/(3/4)
|
||||
|
||||
|
|
|
@ -350,7 +350,7 @@ class PureAlgebraicEngine:
|
|||
return EvaluationResult(line, error_msg, "error", False, str(e), is_solve_query=True)
|
||||
|
||||
def _evaluate_assignment(self, line: str) -> EvaluationResult:
|
||||
"""Evalúa una asignación"""
|
||||
"""Evalúa una asignación CON FUNCIONALIDAD DUAL: asignación al contexto + ecuación a sympy"""
|
||||
try:
|
||||
var_name, expression_str = line.split('=', 1)
|
||||
var_name = var_name.strip()
|
||||
|
@ -367,10 +367,30 @@ class PureAlgebraicEngine:
|
|||
eval_context = self._get_complete_context()
|
||||
result_obj = sympify(expression_str, locals=eval_context)
|
||||
|
||||
# Actualizar tabla de símbolos
|
||||
# 1. ASIGNACIÓN AL CONTEXTO (para evaluación directa)
|
||||
self.symbol_table[var_name] = result_obj
|
||||
self.variables.add(var_name)
|
||||
|
||||
# 2. AGREGAR COMO ECUACIÓN A SYMPY (para resolución algebraica)
|
||||
try:
|
||||
# Crear el símbolo de la variable y la ecuación simbólica
|
||||
var_symbol = sp.Symbol(var_name)
|
||||
right_expr = sympify(expression_str, locals=eval_context)
|
||||
equation_obj = Eq(var_symbol, right_expr)
|
||||
|
||||
# Agregar a la lista de ecuaciones para resolución
|
||||
self.equations.append(equation_obj)
|
||||
|
||||
# Registrar símbolos de la ecuación
|
||||
for free_symbol in equation_obj.free_symbols:
|
||||
self.variables.add(str(free_symbol))
|
||||
|
||||
self.logger.debug(f"Asignación dual agregada: {var_name} = {result_obj} (como ecuación: {equation_obj})")
|
||||
|
||||
except Exception as eq_error:
|
||||
# Si falla como ecuación, continuar solo con la asignación
|
||||
self.logger.warning(f"No se pudo agregar '{line}' como ecuación: {eq_error}")
|
||||
|
||||
output = f"{var_name} = {result_obj}"
|
||||
|
||||
# Devolver el resultado de la asignación
|
||||
|
@ -514,32 +534,67 @@ class PureAlgebraicEngine:
|
|||
except Exception as e:
|
||||
return f"Error resolviendo sistema: {e}"
|
||||
elif len(args) == 1 and hasattr(args[0], 'is_Symbol') and args[0].is_Symbol:
|
||||
# solve(variable) - resolver para una variable específica y auto-aplicar
|
||||
# solve(variable) - resolver para una variable específica
|
||||
var_symbol = args[0]
|
||||
solution_value = self._solve_for_variable(var_symbol)
|
||||
|
||||
# Si encontramos una solución, auto-aplicar al sistema
|
||||
# Si encontramos una solución diferente de la variable
|
||||
if solution_value != var_symbol:
|
||||
# Resolver iterativamente para obtener el valor más simplificado
|
||||
final_value = self._resolve_iteratively(solution_value)
|
||||
# Verificar si la solución contiene otras variables
|
||||
free_symbols = solution_value.free_symbols
|
||||
unresolved_vars = free_symbols - {var_symbol}
|
||||
|
||||
# Auto-aplicar la solución al sistema
|
||||
self._auto_apply_solution(var_symbol, final_value)
|
||||
if unresolved_vars:
|
||||
# Hay variables sin resolver, verificar si tienen valores numéricos
|
||||
has_numeric_values = True
|
||||
for var_sym in unresolved_vars:
|
||||
var_name = str(var_sym)
|
||||
if var_name in self.symbol_table:
|
||||
value = self.symbol_table[var_name]
|
||||
# Si el valor es simbólico (no numérico), no podemos resolver completamente
|
||||
if not (hasattr(value, 'is_number') and value.is_number):
|
||||
has_numeric_values = False
|
||||
break
|
||||
else:
|
||||
# Variable no tiene valor asignado
|
||||
has_numeric_values = False
|
||||
break
|
||||
|
||||
# Verificar que el resultado no sea problemático
|
||||
if final_value == var_symbol or str(final_value) in ['True', 'False']:
|
||||
return var_symbol
|
||||
if has_numeric_values:
|
||||
# Todas las variables tienen valores numéricos, resolver iterativamente
|
||||
final_value = self._resolve_iteratively(solution_value)
|
||||
|
||||
return Eq(var_symbol, final_value)
|
||||
# Auto-aplicar la solución numérica al sistema
|
||||
if final_value != var_symbol and not str(final_value) in ['True', 'False']:
|
||||
self._auto_apply_solution(var_symbol, final_value)
|
||||
|
||||
return Eq(var_symbol, final_value)
|
||||
else:
|
||||
# Hay variables con valores simbólicos, mostrar la relación algebraica
|
||||
# Ejemplo: t = x - 5 (donde x = t + 5, es simbólico)
|
||||
result_eq = Eq(var_symbol, solution_value)
|
||||
return result_eq
|
||||
else:
|
||||
# No hay variables sin resolver, intentar resolver completamente
|
||||
final_value = self._resolve_iteratively(solution_value)
|
||||
|
||||
# Auto-aplicar la solución al sistema solo si es un valor específico
|
||||
if final_value != var_symbol and not str(final_value) in ['True', 'False']:
|
||||
self._auto_apply_solution(var_symbol, final_value)
|
||||
|
||||
return Eq(var_symbol, final_value)
|
||||
else:
|
||||
# Si no hay solución en las ecuaciones, verificar en symbol_table
|
||||
var_name = str(var_symbol)
|
||||
if var_name in self.symbol_table:
|
||||
value = self.symbol_table[var_name]
|
||||
final_value = self._resolve_iteratively(value)
|
||||
return Eq(var_symbol, final_value)
|
||||
else:
|
||||
return var_symbol
|
||||
# Si el valor en symbol_table es diferente de la variable, devolverlo
|
||||
if value != var_symbol:
|
||||
final_value = self._resolve_iteratively(value)
|
||||
return Eq(var_symbol, final_value)
|
||||
|
||||
# Si no hay información, devolver la variable tal como está
|
||||
return var_symbol
|
||||
else:
|
||||
# solve() con argumentos específicos (múltiples variables, ecuaciones, etc.)
|
||||
return solve(*args, **kwargs)
|
||||
|
@ -550,13 +605,7 @@ class PureAlgebraicEngine:
|
|||
return var_symbol
|
||||
|
||||
try:
|
||||
# 1. Buscar si la variable tiene asignación directa en symbol_table
|
||||
var_name = str(var_symbol)
|
||||
if var_name in self.symbol_table:
|
||||
# Devolver el valor de la asignación directa
|
||||
return self.symbol_table[var_name]
|
||||
|
||||
# 2. Buscar ecuaciones que contengan esta variable
|
||||
# 1. Buscar ecuaciones que contengan esta variable PRIMERO
|
||||
relevant_eqs = [eq for eq in self.equations if var_symbol in eq.free_symbols]
|
||||
if relevant_eqs:
|
||||
# Estrategia 1: Buscar asignación directa
|
||||
|
@ -585,7 +634,8 @@ class PureAlgebraicEngine:
|
|||
# en términos de otras variables
|
||||
try:
|
||||
# Obtener todas las variables del sistema excepto la que queremos resolver
|
||||
all_vars = list(self.variables)
|
||||
# Convertir todas las variables a símbolos para sympy
|
||||
all_vars = [sp.Symbol(v) if isinstance(v, str) else v for v in self.variables]
|
||||
other_vars = [v for v in all_vars if v != var_symbol]
|
||||
|
||||
if other_vars:
|
||||
|
@ -624,7 +674,15 @@ class PureAlgebraicEngine:
|
|||
except:
|
||||
pass
|
||||
|
||||
# 5. Si nada funciona, devolver la variable tal como está
|
||||
# 5. Si no hay ecuaciones relevantes, buscar en symbol_table como último recurso
|
||||
var_name = str(var_symbol)
|
||||
if var_name in self.symbol_table:
|
||||
value = self.symbol_table[var_name]
|
||||
# Solo devolver si el valor no es la misma variable (evitar bucles)
|
||||
if value != var_symbol:
|
||||
return value
|
||||
|
||||
# 6. Si nada funciona, devolver la variable tal como está
|
||||
return var_symbol
|
||||
|
||||
except Exception as e:
|
||||
|
|
Loading…
Reference in New Issue