diff --git a/hybrid_calc_history.txt b/hybrid_calc_history.txt index f51deb8..cf02f25 100644 --- a/hybrid_calc_history.txt +++ b/hybrid_calc_history.txt @@ -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) diff --git a/main_evaluation_puro.py b/main_evaluation_puro.py index 6e20822..70a7c9f 100644 --- a/main_evaluation_puro.py +++ b/main_evaluation_puro.py @@ -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) - - # Verificar que el resultado no sea problemático - if final_value == var_symbol or str(final_value) in ['True', 'False']: - return var_symbol - - return Eq(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 + + if has_numeric_values: + # Todas las variables tienen valores numéricos, resolver iterativamente + final_value = self._resolve_iteratively(solution_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: