From 556c63ad31d4cceb6e81272c5865a53eff7cbf9a Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 6 Jun 2025 09:09:39 +0200 Subject: [PATCH] =?UTF-8?q?Mejora=20del=20motor=20de=20evaluaci=C3=B3n=20c?= =?UTF-8?q?on=20la=20adici=C3=B3n=20de=20funciones=20de=20plotting=20y=20c?= =?UTF-8?q?ompatibilidad=20con=20tipos=20SymPy=20en=20las=20clases=20IP4?= =?UTF-8?q?=20y=20FourBytes.=20Se=20actualiza=20el=20contexto=20base=20par?= =?UTF-8?q?a=20incluir=20nuevas=20funciones=20matem=C3=A1ticas=20y=20se=20?= =?UTF-8?q?implementa=20la=20verificaci=C3=B3n=20de=20clases=20requeridas?= =?UTF-8?q?=20en=20el=20contexto.=20Se=20optimiza=20el=20manejo=20de=20err?= =?UTF-8?q?ores=20y=20se=20mejora=20la=20conversi=C3=B3n=20de=20tipos=20Sy?= =?UTF-8?q?mPy=20a=20nativos.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- custom_types/fourbytes_type.py | 2 ++ custom_types/ip4_type.py | 50 ++++++++++++++++++++++++++++++++-- main_evaluation_puro.py | 35 +++++++++++++++++++++++- 3 files changed, 83 insertions(+), 4 deletions(-) diff --git a/custom_types/fourbytes_type.py b/custom_types/fourbytes_type.py index 592366e..d7b2794 100644 --- a/custom_types/fourbytes_type.py +++ b/custom_types/fourbytes_type.py @@ -24,6 +24,7 @@ class FourBytes(ClassBase): # Modo algebraico: mantener símbolos INTERNAMENTE, no convertir a SymPy aún self._symbols = self._extract_symbols() self._numeric_value = None # No hay valor numérico directo + self._symbolic_value = self.to_sympy() # AÑADIDO: compatibilidad con IP4 super().__init__(self.original, self.original) # ClassBase, NO SympyClassBase else: # Modo numérico: validar rangos y convertir @@ -43,6 +44,7 @@ class FourBytes(ClassBase): self._numeric_elements[2] << 8 | self._numeric_elements[3]) self._symbols = [] + self._symbolic_value = self._numeric_value # AÑADIDO: compatibilidad con IP4 super().__init__(self._numeric_value, self.original) # ClassBase def _extract_symbols(self): diff --git a/custom_types/ip4_type.py b/custom_types/ip4_type.py index 1a6f37c..5ed01e2 100644 --- a/custom_types/ip4_type.py +++ b/custom_types/ip4_type.py @@ -59,6 +59,14 @@ class IP4Mask(ClassBase): def _parse_mask(self, mask_input: Union[int, str]) -> int: """Helper to parse mask_input and return prefix.""" prefix_val: int + + # Manejar tipos SymPy (convirtiendo a int nativo) + if hasattr(mask_input, '__int__'): # SymPy Integer, etc. + try: + mask_input = int(mask_input) + except (ValueError, TypeError): + pass + if isinstance(mask_input, int): if not (0 <= mask_input <= 32): raise ValueError(f"Invalid prefix length: {mask_input}. Must be between 0 and 32.") @@ -361,7 +369,16 @@ class Class_IP4(SympyClassBase): # Obtener clases dinámicamente IntBase, FourBytes = get_base_classes() - # Procesar dirección + # Procesar dirección (con compatibilidad SymPy) + + # Convertir objetos SymPy de vuelta a strings si es necesario + if hasattr(address, '__str__') and not isinstance(address, (str, int, float)): + # Probablemente es un objeto SymPy - convertir a string + address_str = str(address) + if '.' in address_str and len(address_str.split('.')) == 4: + # Parece una IP, usar el string + address = address_str + if FourBytes and isinstance(address, FourBytes): # address es FourBytes (ya tokenizado desde x.x.x.x) self.address = address @@ -407,12 +424,39 @@ class Class_IP4(SympyClassBase): else: self._ip_int = self.address._numeric_value self._has_symbols = False + + elif hasattr(address, '__int__'): # SymPy Integer u otros números + # Convertir número a IP string (asumiendo formato de 32 bits) + try: + addr_int = int(address) + self._ip_str = f"{(addr_int >> 24) & 0xFF}.{(addr_int >> 16) & 0xFF}.{(addr_int >> 8) & 0xFF}.{addr_int & 0xFF}" + + if FourBytes: + self.address = FourBytes(self._ip_str) + else: + self.address = type('MockFourBytes', (), { + 'original': self._ip_str, + 'has_symbols': False, + '_numeric_value': addr_int + })() + + self._ip_int = addr_int + self._has_symbols = False + except (ValueError, TypeError): + raise TypeError(f"No se pudo convertir {address} (tipo: {type(address)}) a dirección IP") else: - raise TypeError(f"address debe ser FourBytes o string, recibido: {type(address)}") + raise TypeError(f"address debe ser FourBytes, string, o número, recibido: {type(address)}") # Procesar máscara if mask is not None: + # Convertir tipos SymPy a tipos nativos + if hasattr(mask, '__int__'): # SymPy Integer, etc. + try: + mask = int(mask) + except (ValueError, TypeError): + pass + if isinstance(mask, IP4Mask): self._mask_obj = mask elif isinstance(mask, (int, str)): @@ -424,7 +468,7 @@ class Class_IP4(SympyClassBase): # Máscara desde hex (ej: 16#ffffff00) self._mask_obj = IP4Mask(mask) else: - raise TypeError(f"mask debe ser int, str, IP4Mask, FourBytes, o IntBase") + raise TypeError(f"mask debe ser int, str, IP4Mask, FourBytes, o IntBase, recibido: {type(mask)}") else: self._mask_obj = None diff --git a/main_evaluation_puro.py b/main_evaluation_puro.py index 499d64c..19741c5 100644 --- a/main_evaluation_puro.py +++ b/main_evaluation_puro.py @@ -61,9 +61,11 @@ class PureAlgebraicEngine: def _load_base_context(self): """Carga el contexto base con funciones y tipos""" try: - # Contexto de SymPy + # Contexto de SymPy básico self.context.update({ 'sin': sp.sin, 'cos': sp.cos, 'tan': sp.tan, + 'asin': sp.asin, 'acos': sp.acos, 'atan': sp.atan, + 'sinh': sp.sinh, 'cosh': sp.cosh, 'tanh': sp.tanh, 'log': sp.log, 'ln': sp.ln, 'exp': sp.exp, 'sqrt': sp.sqrt, 'abs': sp.Abs, 'pi': sp.pi, 'e': sp.E, 'I': sp.I, @@ -73,12 +75,43 @@ class PureAlgebraicEngine: 'expand': sp.expand, 'factor': sp.factor, 'diff': sp.diff, 'integrate': sp.integrate, 'Matrix': sp.Matrix, 'symbols': sp.symbols, + 'Symbol': sp.Symbol, 'Rational': sp.Rational, + 'Float': sp.Float, 'Integer': sp.Integer, + 'limit': sp.limit, 'series': sp.series, + 'summation': sp.summation, 'product': sp.product, + 'binomial': sp.binomial, 'factorial': sp.factorial, + 'gcd': sp.gcd, 'lcm': sp.lcm, + 'ceiling': sp.ceiling, 'floor': sp.floor, + 'Piecewise': sp.Piecewise, }) + # Funciones de plotting + try: + from sympy.plotting import plot, plot3d, plot_parametric, plot3d_parametric_line + self.context.update({ + 'plot': plot, + 'plot3d': plot3d, + 'plot_parametric': plot_parametric, + 'plot3d_parametric_line': plot3d_parametric_line, + }) + self.logger.debug("Funciones de plotting cargadas") + except Exception as e: + self.logger.warning(f"Error cargando funciones de plotting: {e}") + # Contexto dinámico de tipos personalizados dynamic_context = get_registered_base_context() self.context.update(dynamic_context) + # Verificar que las clases principales estén disponibles + required_classes = ['IP4', 'IP4Mask', 'FourBytes', 'IntBase', 'Hex', 'Bin', 'Dec', 'Chr', 'LaTeX'] + missing_classes = [] + for cls_name in required_classes: + if cls_name not in self.context: + missing_classes.append(cls_name) + + if missing_classes: + self.logger.warning(f"Clases faltantes en contexto: {missing_classes}") + self.logger.debug(f"Contexto cargado: {len(self.context)} elementos") except Exception as e: