23 KiB
Guía de Desarrollo - Calculadora MAV CAS Híbrido
Visión General
Este documento describe el estado actual y los objetivos de desarrollo para la Calculadora MAV, un Sistema de Álgebra Computacional (CAS) híbrido. El proyecto busca combinar la potencia de SymPy como motor algebraico central con capacidades especializadas (IP4, Hex, etc.) integradas de forma nativa.
Objetivos Principales
1. SymPy como Motor Central
- Integrar todas las funciones de SymPy directamente
- SymPy maneja toda la evaluación algebraica y ecuaciones
- Cada linea de ingreso corresponde a una sola linea de resultados
- La interfaz de usuario se divide en 2 columnas, a la izquierda el area de ingreso de datos y equaciones a ser evaluadas, a la derecha el area de resultados que se colorean segun cada tipo de respuesta.
2. Sintaxis Simplificada con Corchetes (Única)
- Usar exclusivamente
Class[args]
en lugar deClass("args")
. Cuando se usan los corchetes los parametros se separan por;
- Los corchetes indican parsing especial (agregar comillas automáticamente)
- Mantiene sintaxis limpia y reduce errores de tipeo
3. Detección Automática y Manejo de Ecuaciones
- Ecuaciones ingresadas directamente (ej.
3+b=5+c
) se detectan y añaden al sistema interno de SymPy. - Soporte para comparaciones SymPy (ej.
x > 5
,a == b
,x <= 10
) como expresiones evaluables. - Sintaxis de atajo para solve:
variable=?
equivale asolve(variable)
4. Evaluación Híbrida con Variables SymPy Puras
- Resultado simbólico (siempre disponible)
- Evaluación numérica con
.evalf()
(cuando sea aplicable y las variables estén definidas). Esta evaluacion se muestra a la derecha del resultado simbolico. - Las asignaciones son siempre simbolicas, solo los resultados se muestra la evaluacion numerica.
- Todas las variables son símbolos SymPy: Sin variables Python tradicionales
- Sin eval/exec por defecto: Solo SymPy, a menos que se indique sintaxis especial
4. Resultados Interactivos
- Tags clickeables en el widget Text para resultados complejos que necesitan mas de una linea de resultado como Plot, Matrices y Listas.
- Detección automática de tipos que requieren visualización especial:
- Plots de SymPy → "📊 Ver Plot" (abre ventana matplotlib).
- Matrices → "📋 Ver Matriz" (muestra matriz formateada).
- Listas largas → "📋 Ver Lista" (muestra contenido expandido).
- Objetos complejos → "🔍 Ver Detalles" (representación completa).
- Implementación simple: Usar
text.tag_bind()
en widget existente - Ventanas popup para contenido que no cabe en línea.
- Actualización automática: Las ventanas de plot, listas y matrices deben tener la capacidad de actualizarse automáticamente si los datos subyacentes cambian y la ventana permanece abierta.
- Posicionamiento inteligente:
- Cuando no hay otras ventanas de resultados (plot, lista, matriz) abiertas, la primera que se abra debe tener su altura igual a la de la ventana principal de la aplicación.
- Esta primera ventana se posicionará automáticamente a la derecha de la ventana principal de la aplicación.
5. Clases Especializadas como Objetos SymPy
- Todas las clases (IP4, Hex, Bin, etc.) heredan de
sympy.Basic
- Participan en manipulación algebraica:
solve()
,diff()
,integrate()
- Mantienen funcionalidad especializada (métodos
.NetworkAddress()
,.toHex()
, etc.)
Arquitectura Propuesta
Estructura de archivos
- Subcarperta de log "/.log"
- Subcarpeta de documentos md de ayuda y documentacion tecnica "/.doc"
- Aplicacion principal launcher: main_calc.py
- Aplicacion principal app: main_calc_app.py
- Motor de evaluacion: main_evaluation.py
- Motor de ventanas emergentes: tl_popup.py
- Objetos especiales: [nombre objeto]_type.py . Ejemplo ip4_type.py
- Tools del motor: tl_[nombre tool].py . Ejemplo: tl_bracket_parser.py
Flujo de Procesamiento
Entrada Usuario → [Bracket Parser] → [SymPy Evaluation] → {
1. Resultado Simbólico (siempre)
2. evalf() (si variables definidas)
3. Métodos especializados disponibles
}
Transformación de Sintaxis
# Clases con corchetes:
IP4[192.168.1.1/24].NetworkAddress[] → IP4("192.168.1.1/24").NetworkAddress()
# Detección contextual de ecuaciones:
3+b=5+c → Se detecta como ecuación standalone (agregar al sistema SymPy)
"x > 5" → Se procesa como desigualdad SymPy
x**2 + 2*x == 0 → Se detecta como igualdad lógica standalone
# NO se detectan como ecuaciones (parsing contextual):
solve(x + 2 = 5, x) → "=" es argumento de función, no ecuación
result = solve(a + b = 10, a) → "=" izquierdo es asignación Python
IP4[192.168.1.1].Mask() == "255.255.255.0" → Expresión de comparación
# Sintaxis de atajo para solve:
x=? → solve(x)
Componentes Técnicos
1. Bracket Parser y Detección Contextual de Ecuaciones
- Preprocesador que convierte
Class[args]
→Class("args")
- La separacion de argumentos se hace con el ";"
- Soporte para clases:
IP4
,Hex
,Bin
,Date
,Dec
,Chr
- Detección contextual inteligente de ecuaciones:
- Ecuaciones standalone:
3+b=5+c
(detectar como ecuación) - Strings con ecuaciones:
"expresión = expresión"
(detectar como ecuación) - NO detectar cuando
=
,==
,>
, etc. están dentro de llamadas a funciones:solve(x=5, y)
- NO detectar asignaciones Python:
result = solve(...)
- Ecuaciones standalone:
- Conversión de atajo:
variable=?
→solve(variable)
- Usa AST parsing para distinguir contexto sintáctico
- Extensible para futuras transformaciones más complejas
2. Clases Híbridas
class IP4(BaseCalcType, sympy.Basic):
def __new__(cls, address, mask=None):
# Crear objeto SymPy válido
obj = sympy.Basic.__new__(cls)
# Inicializar funcionalidad IP4
obj._init_ip4(address, mask)
return obj
def _sympystr(self, printer):
return f"IP4({self.address})"
3. Sistema de Evaluación y Detección Contextual
def detect_equation_context(code_line):
"""
Usa AST para determinar si una línea contiene una ecuación standalone
vs. comparaciones dentro de funciones o asignaciones Python
"""
tree = ast.parse(code_line)
# Casos que NO son ecuaciones:
# - Asignaciones: result = solve(...)
# - Argumentos de función: solve(x = 5, y)
# - Expresiones dentro de llamadas: func(a == b)
# Casos que SÍ son ecuaciones:
# - Comparaciones standalone: x + 2 == 5
# - Strings con ecuaciones: "a = b"
return is_standalone_equation
def evaluate_expression(expr):
# 1. Detección contextual de ecuaciones
if detect_equation_context(expr):
add_to_equation_system(expr)
return "Ecuación agregada al sistema"
# 2. Evaluación simbólica (SymPy)
symbolic_result = sympy.sympify(expr)
# 3. Intentar evaluación numérica
try:
if all_variables_defined(symbolic_result):
numeric_result = symbolic_result.evalf()
else:
numeric_result = None
except:
numeric_result = None
return {
'symbolic': symbolic_result,
'numeric': numeric_result
}
Capacidades Expandidas
1. Funciones SymPy Completas
# Todas disponibles directamente:
diff(IP4[192.168.x.1] + offset, x)
integrate(Hex[x] * sin(x), x)
solve([IP4[192.168.x.y] == IP4[192.168.1.10]], [x, y])
limit(Dec[x]/x, x, 0)
series(exp(Hex[x]), x, 0, 5)
2. Plotting Integrado con Interface Interactiva
# SymPy plotting nativo:
plot(sin(Hex[x]), (x, 0, 255)) # Muestra: "📊 Ver Plot" (clickeable)
plot3d(IP4[192.168.x.y].to_decimal(), (x, 1, 254), (y, 1, 254))
# Resultados complejos interactivos:
Matrix([[1, 2], [3, 4]]) # Muestra: "📋 Ver Matriz" (clickeable)
solve(x**2 + 2*x + 1, x) # Lista: "📋 Ver Soluciones" (clickeable)
3. Manipulación Algebraica de Objetos Especializados
# Objetos especializados en expresiones algebraicas:
network = IP4[192.168.x.0/24]
solve(network.NetworkAddress() == IP4[192.168.5.0/24], x)
# Resultado: x = 5
Ejemplos de Uso Objetivo
# Evaluación directa con SymPy:
solve(x + 10 - 15, x) # Resultado: [5]
# Detección automática de ecuaciones:
3+b=5+c # Se agrega automáticamente al sistema
x > 5 # Desigualdad procesada por SymPy
a == b # Igualdad lógica procesada por SymPy
# Sintaxis de atajo:
x=? # Equivale a solve(x)
# Solo sintaxis con corchetes:
IP4[192.168.1.1/24].NetworkAddress[] # Resultado: 192.168.1.0/24
# Variables puras SymPy:
x = 5 # x es Symbol('x') con valor 5, no variable Python
y = x + 2 # y es expresión simbólica: Symbol('x') + 2
# Álgebra con objetos especializados:
base_ip = IP4[10.0.x.1]
solve(base_ip + 255 == IP4[10.0.5.0], x) # Resultado: x = 4
# Funciones avanzadas con resultados interactivos:
diff(Hex[x**2], x) # Derivada: 2*x*log(16)
plot(sin(2*pi*Hex[x]/256), (x, 0, 255)) # Resultado: "📊 Ver Plot"
# Matrices y estructuras complejas:
Matrix([[1, 2, 3], [4, 5, 6]]) # Resultado: "📋 Ver Matriz"
solve([x + y == 10, x - y == 2], [x, y]) # Resultado: "📋 Ver Soluciones"
# eval/exec opcional con sintaxis especial:
@eval: import os; os.getcwd() # Solo cuando se necesite Python puro
Beneficios Esperados
1. Usabilidad
- Sintaxis más limpia (sin comillas constantes)
- Acceso completo a capacidades de CAS
- Evaluación automática simbólica + numérica
2. Potencia Matemática
- Todas las funciones de SymPy disponibles
- Objetos especializados participan en álgebra
- Capacidades de plotting integradas
3. Extensibilidad
- Parser extensible para futuras sintaxis
- Fácil agregar nuevas clases especializadas
- Compatible con ecosystem SymPy completo
4. Consistencia
- Un solo motor de evaluación (SymPy)
- Reglas algebraicas consistentes
- Manejo unificado de errores
Fases de Implementación
Fase 1: Foundation
- Implementar bracket parser básico
- Convertir clases existentes a
sympy.Basic
- Sistema de evaluación híbrida
Fase 2: Integration
- Remover clase
solve
separada - Integrar todas las funciones SymPy
- Testing de manipulación algebraica
Fase 3: Enhancement
- Capacidades de plotting
- Sintaxis extendida del parser
- Optimizaciones de performance
Fase 4: Polish
- Documentación completa
- Ejemplos avanzados
- UI/UX improvements
Consideraciones Adicionales
Performance y Caching (Crítico)
- Caching de líneas precedentes: Las líneas anteriores no se recalculan
- Incremental evaluation: Solo evaluar líneas nuevas/modificadas
- Caching de parsing: Bracket parsing se cachea para expresiones repetidas
- Lazy evalf(): Solo evaluar numéricamente cuando se solicite mostrar
- Optimización SymPy: Configurar para performance en contexto interactivo
Manejo Robusto de Errores y Logging
- Logging centralizado enfocado en errores: El sistema de logging (
main_launcher.py
) debe registrar principalmente errores para facilitar la depuración, evitando logs informativos excesivos en producción. Los logs detallados (DEBUG) pueden activarse con un flag. Solo crear un archivo de log bajo la carpeta "/.logs" - Errores de SymPy y del Motor CAS: Priorizar mensajes de error claros provenientes de SymPy o del motor de evaluación.
- Errores contextuales: Mensajes específicos para errores de parsing vs evaluación
- Sugerencias automáticas: "¿Quisiste decir...?" para funciones mal escritas
- eval/exec explícito: Solo disponible con sintaxis especial cuando sea necesario
Extensibilidad del Parser
- Arquitectura modular: Fácil agregar nuevas transformaciones sintácticas
- Plugin system: Permitir extensiones de terceros
- Configurabilidad: Usuario puede habilitar/deshabilitar transformaciones
Sistema de Ayuda Avanzado
- Autocompletado SymPy: Funciones y métodos disponibles según contexto o cuando se presiona el "."
- Help integrado:
help(diff)
muestra documentación SymPy completa - Ejemplos interactivos: Templates para operaciones comunes
- Cheat sheet: Referencia rápida de sintaxis nueva vs antigua
Sistema de Autocompletado y Ayuda Contextual (Helpers)
Objetivo
Proveer al usuario de una experiencia de ayuda y autocompletado inteligente, no invasiva y extensible, que facilite el uso de funciones avanzadas y objetos personalizados, integrando tanto métodos propios como todas las funciones de SymPy.
1. Helpers: Ayuda Contextual por Tipo
Cada tipo de objeto (por ejemplo, IP4
, Hex
, etc.) debe definir una función Helper(input_str)
que:
- Recibe el string de entrada del usuario.
- Decide, usando su propia lógica (por ejemplo, expresiones regulares), si puede ofrecer una ayuda relevante.
- Devuelve un string de ayuda (ejemplo de uso, sintaxis, sugerencia) o
None
si no aplica. - Las respuestas no pueden tener mas de una linea nunca.
Ejemplo:
# En ip4_type.py
def Helper(input_str):
if re.match(r"^\s*IP4(\b|\s*\[.*)?", input_str, re.IGNORECASE):
return 'Ej: IP4[192.168.1.1/24], IP4[10.0.0.1, 8], o IP4[172.16.0.5, 255.255.0.0]'
return None
Ventajas:
- Cada Helper es autocontenido y puede evolucionar de forma independiente.
- Permite personalizar la ayuda para cada tipo de objeto o función.
2. Helper para SymPy
Dado que ahora todas las funciones de SymPy están disponibles, se debe agregar un Helper general para SymPy que:
- Detecte si el usuario está comenzando a escribir el nombre de una función de SymPy (por ejemplo,
diff
,integrate
,solve
,limit
, etc.). - Sugiera la sintaxis básica y ejemplos de uso para la función detectada.
- Puede usar una lista de funciones comunes de SymPy y sus descripciones.
Ejemplo:
# En sympy_helper.py
def Helper(input_str):
sympy_funcs = {
"diff": "Derivada: diff(expr, var). Ej: diff(sin(x), x)",
"integrate": "Integral: integrate(expr, var). Ej: integrate(x**2, x)",
"solve": "Resolver ecuaciones: solve(expr, var). Ej: solve(x**2-1, x)",
"limit": "Límite: limit(expr, var, valor). Ej: limit(sin(x)/x, x, 0)",
# ...agregar más funciones comunes
}
for func, ayuda in sympy_funcs.items():
if input_str.strip().startswith(func):
return ayuda
return None
3. Manejo Centralizado de Helpers
En el motor principal de la aplicación, se debe mantener una lista de todas las funciones Helper disponibles (incluyendo la de SymPy).
Al evaluar la línea de entrada y esta da error de evaluacion entonces:
- Se llama a cada Helper en orden.
- Si alguna Helper retorna una ayuda, se muestra esa ayuda al usuario (en la línea de resultado, tooltip, etc.).
- Si ninguna Helper ayuda, se muestra el mensaje de error real.
Ejemplo:
HELPERS = [
IP4.Helper,
Hex.Helper,
SympyHelper.Helper,
# ...otros helpers
]
def obtener_ayuda(input_str):
for helper in HELPERS:
ayuda = helper(input_str)
if ayuda:
return ayuda
return None
4. Autocompletado de Métodos y Funciones (Popup tras el punto)
- Cuando el usuario escribe un punto (
.
) después de un objeto válido, se evalúa el objeto y se obtiene la lista de métodos disponibles. - Se muestra un popup de autocompletado con los métodos relevantes (filtrando los no útiles). La lista de funciones se debe obtener de una funcione de cada objeto llamada PopupFunctionList() esta funcion en cada objeto mantendra la lista de las funciones disponibles y una explicacion corta tipo hint. Esta funcion retorna una lista de tuplas con el nombre de la funcion y el hint.
- El usuario puede seleccionar un método con el teclado o mouse, y se inserta automáticamente (con paréntesis si corresponde).
- El popup solo aparece tras el punto, no en cada pulsación de tecla, para no ser invasivo.
Puntos clave:
- Priorizar métodos útiles y públicos.
- Permitir que cada tipo defina una lista de métodos sugeridos.
- Cerrar el popup fácilmente (Escape, clic fuera, etc.).
5. Flujo de Evaluación y Ayuda
- El usuario escribe una línea.
- Si presiona
.
, se muestra el popup de autocompletado de métodos. - Si la línea tiene error:
- Se consulta a los Helpers para mostrar ayuda contextual.
- Si ninguna Helper ayuda, se muestra el mensaje de error real.
- Si la línea es válida, se evalúa normalmente.
6. Extensibilidad
- Para agregar ayuda para un nuevo tipo, solo se debe definir un nuevo Helper y registrarlo en la lista central.
- El Helper de SymPy puede expandirse para cubrir más funciones y ejemplos.
- El sistema de autocompletado puede ampliarse para sugerir funciones de SymPy al escribir el nombre de la función (no solo tras el punto).
7. Resumen de Beneficios
- No invasivo: El autocompletado solo aparece cuando el usuario lo solicita (tras el punto).
- Ayuda contextual: Los Helpers ofrecen ayuda específica y relevante según el contexto.
- Extensible: Fácil de agregar nuevos tipos y funciones de ayuda.
- Consistente: El usuario recibe ayuda o autocompletado solo cuando es útil, no en cada pulsación.
8. Ejemplo de Integración
# En el motor principal:
ayuda = obtener_ayuda(linea_usuario)
if ayuda:
mostrar_ayuda(ayuda)
elif error:
mostrar_error(error)
else:
mostrar_resultado(resultado)
Este sistema permite que la ayuda y el autocompletado evolucionen de forma incremental, mejorando la experiencia del usuario sin ser molestos ni invasivos.
Gestión de Variables Puras SymPy
- Solo símbolos SymPy: Todas las variables son
Symbol()
automáticamente - Sin variables Python: Eliminación de
eval()
como mecanismo por defecto - Evaluación consistente:
x = 5
creaSymbol('x')
con valor 5 en contexto - eval/exec opcional: Solo disponible con sintaxis especial (ej:
@eval: código_python
) - Contexto unificado: Un solo namespace SymPy para toda la sesión
Métricas de Éxito
- Sintaxis
Class[args]
funciona consistentemente (bracket_parser.py
,hybrid_base_types.py
). - [+] Detección contextual inteligente de ecuaciones (Motor CAS/Parser):
- [+] Ecuaciones standalone:
3+b=5+c
,x**2 == 0
se detectan y añaden al sistema (bracket_parser.py
,hybrid_evaluation_engine.py
).x**2==0
se evalúa como expresión booleana, no se añade como ecuación al sistema automáticamente. - (Parser) Strings con ecuaciones:
"a=b"
,"x>5"
se procesan como ecuaciones (actualmente el parser manejaa=b
directo, no como string literal). - [+] NO detectar comparaciones en argumentos:
solve(x=5, y)
,func(a==b)
(AST enbracket_parser.py
ayuda,EquationDetector
es un prototipo). - NO detectar asignaciones Python:
result = solve(...)
(bracket_parser.py
lo maneja).
- [+] Ecuaciones standalone:
- Sintaxis de atajo
variable=?
funciona comosolve(variable)
(bracket_parser.py
). - [+] Todas las funciones SymPy disponibles en interfaz (
hybrid_evaluation_engine.py
tiene contexto base amplio;hybrid_calc_app.py
expone algunas en menús). - [+] Objetos especializados participan en
solve()
,diff()
, etc. (hybrid_base_types.py
heredan desympy.Basic
; la profundidad de integración en operaciones aritméticas necesita revisión para preservar el tipo). - Evaluación híbrida (simbólica + numérica) automática (
hybrid_evaluation_engine.py
). - [+] Plotting funcional con objetos especializados (Infraestructura en
hybrid_evaluation_engine.py
yinteractive_results.py
; depende de la convertibilidad del objeto a datos ploteables). - [+] Resultados interactivos funcionando:
- Implementación de ventanas popup (Toplevel) para mostrar información detallada (ej. diálogo de error, plots, matrices, listas en
main_launcher.py
,interactive_results.py
). - Tags clickeables en el widget Text para resultados complejos (
hybrid_calc_app.py
,interactive_results.py
). - [+] Detección automática de tipos para visualización especial:
- Plots de SymPy → "📊 Ver Plot" (
interactive_results.py
). - Matrices → "📋 Ver Matriz" (
interactive_results.py
). - Listas largas → "📋 Ver Lista" (
interactive_results.py
). - (UI/Engine) Objetos complejos → "🔍 Ver Detalles" (Infraestructura parcial, no implementado genéricamente).
- Plots de SymPy → "📊 Ver Plot" (
- (UI) Ventanas de plot/lista/matriz con actualización automática si se mantienen abiertas.
- [+] (UI) Posicionamiento y dimensionamiento inteligente de la primera ventana de plot/lista/matriz (
interactive_results.py
tiene base, necesita lógica de "solo si no hay otras abiertas" y ajuste de altura).
- Implementación de ventanas popup (Toplevel) para mostrar información detallada (ej. diálogo de error, plots, matrices, listas en
- [+] Performance aceptable para uso interactivo (Debounce en
hybrid_calc_app.py
ayuda). - [+] Sistema de ayuda avanzado:
- Ayuda básica por línea de comandos (
main_launcher.py
). - (UI) Autocompletado para funciones SymPy y métodos de objetos (
hybrid_calc_app.py
tiene TODO). - [+] (Engine/UI)
help()
integrado con documentación SymPy (hybrid_evaluation_engine.py
tiene base,hybrid_calc_app.py
tiene menús estáticos). - [+] (UI) Ejemplos y templates interactivos (
hybrid_calc_app.py
tieneinsert_example
).
- Ayuda básica por línea de comandos (
- Manejo robusto de errores y logging (Launcher):
- Logging centralizado de errores (
main_launcher.py
, configurable para ser error-only). - Presentación de errores al usuario en ventana dedicada (
main_launcher.py
). - Verificación de dependencias y archivos de la aplicación al inicio (
main_launcher.py
). - Intento de instalación automática de dependencias (
main_launcher.py
). - Provisión de comandos para troubleshooting (
main_launcher.py
).
- Logging centralizado de errores (
- [+] Manejo robusto de errores (Motor CAS):
- [+] Solo errores de SymPy, sin fallbacks automáticos a eval/exec (Motor (
hybrid_evaluation_engine.py
) usaeval
ysympify
; se busca minimizareval
directo de input de usuario). - [+] Errores contextuales: mensajes específicos para errores de parsing vs. evaluación (
EvaluationResult
tiene campo de error). - (Engine) Sugerencias automáticas: "¿Quisiste decir...?" para funciones mal escritas.
- (Engine/Parser)
eval/exec
explícito: solo disponible con sintaxis especial (ej.@eval:
) (Planeado, no implementado).
- [+] Solo errores de SymPy, sin fallbacks automáticos a eval/exec (Motor (
- Performance optimizada (Motor CAS):
- Caching de expresiones repetidas
- Evaluación lazy de
evalf()
- Tiempo de respuesta < 200ms para operaciones comunes
- [+] Parser extensible con arquitectura modular (
bracket_parser.py
es un buen inicio). - [+] Documentación y ejemplos completos:
- Docstrings en el código (
main_launcher.py
,hybrid_evaluation_engine.py
, etc.). - Guía de Desarrollo (este documento).
- Splash screen eliminado (
main_launcher.py
). - [+] Documentación de usuario final completa (
comprehensive_documentation.md
es una base sólida). - [+] Ejemplos de uso avanzados en la documentación (
comprehensive_documentation.md
).
- Docstrings en el código (