mnspy 0.9.16__tar.gz → 0.9.19__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. mnspy-0.9.19/LICENSE +21 -0
  2. {mnspy-0.9.16 → mnspy-0.9.19}/PKG-INFO +1 -1
  3. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_parciales/mef/mef.py +39 -0
  4. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ra/303/255ces/bisecci/303/263n.py +9 -11
  5. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ra/303/255ces/brent.py +42 -47
  6. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ra/303/255ces/falsa_posicion.py +10 -12
  7. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ra/303/255ces/muller.py +28 -34
  8. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ra/303/255ces/newton_raphson.py +5 -3
  9. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ra/303/255ces/punto_fijo.py +5 -4
  10. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ra/303/255ces/raices.py +35 -19
  11. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ra/303/255ces/secante.py +8 -7
  12. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy.egg-info/PKG-INFO +1 -1
  13. {mnspy-0.9.16 → mnspy-0.9.19}/setup.py +1 -1
  14. mnspy-0.9.16/LICENSE +0 -674
  15. {mnspy-0.9.16 → mnspy-0.9.19}/README.md +0 -0
  16. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/__init__.py +0 -0
  17. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/derivada/__init__.py +0 -0
  18. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/derivada/derivada.py +0 -0
  19. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/derivada/derivada_discreta.py +0 -0
  20. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/derivada/richardson.py +0 -0
  21. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_algebraicas_lineales/__init__.py +0 -0
  22. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_algebraicas_lineales/cramer.py +0 -0
  23. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_algebraicas_lineales/descomposicion_LU.py +0 -0
  24. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_algebraicas_lineales/descomposicion_cholesky.py +0 -0
  25. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_algebraicas_lineales/ecuaciones_algebraicas_lineales.py +0 -0
  26. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_algebraicas_lineales/gauss.py +0 -0
  27. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_algebraicas_lineales/gauss_jordan.py +0 -0
  28. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_algebraicas_lineales/gauss_sediel.py +0 -0
  29. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_algebraicas_lineales/tridiagonal.py +0 -0
  30. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_ordinarias/__init__.py +0 -0
  31. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_ordinarias/ecuaciones_diferenciales_ordinarias.py +0 -0
  32. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_ordinarias/euler.py +0 -0
  33. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_ordinarias/heun.py +0 -0
  34. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_ordinarias/punto_medio.py +0 -0
  35. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_ordinarias/runge_kutta.py +0 -0
  36. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_parciales/__init__.py +0 -0
  37. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_parciales/ecuaciones_diferenciales_parciales.py +0 -0
  38. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_parciales/liebmann.py +0 -0
  39. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_parciales/mdf/__init__.py +0 -0
  40. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_parciales/mdf/mdf.py +0 -0
  41. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_parciales/mef/__init__.py +0 -0
  42. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_parciales/mef/armadura.py +0 -0
  43. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_parciales/mef/barra.py +0 -0
  44. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_parciales/mef/ensamble.py +0 -0
  45. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_parciales/mef/marco.py +0 -0
  46. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_parciales/mef/resorte.py +0 -0
  47. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_parciales/mef/triangular_cst.py +0 -0
  48. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_parciales/mef/viga.py +0 -0
  49. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_parciales/mvf/__init__.py +0 -0
  50. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_parciales/mvf/mvf.py +0 -0
  51. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ecuaciones_diferenciales_parciales/mvf/volumen_finito.py +0 -0
  52. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/integrales/__init__.py +0 -0
  53. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/integrales/cuadratura_adaptativa.py +0 -0
  54. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/integrales/gauss_legendre.py +0 -0
  55. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/integrales/integral.py +0 -0
  56. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/integrales/romberg.py +0 -0
  57. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/integrales/simpson_1_3.py +0 -0
  58. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/integrales/simpson_3_8.py +0 -0
  59. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/integrales/trapezoidal.py +0 -0
  60. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/integrales/trapezoidal_desigual.py +0 -0
  61. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/integrales/trapezoidal_desigual_acumulado.py +0 -0
  62. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/interpolaci/303/263n/__init__.py" +0 -0
  63. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/interpolaci/303/263n/inter_Lagrange.py" +0 -0
  64. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/interpolaci/303/263n/inter_Newton.py" +0 -0
  65. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/interpolaci/303/263n/inter_spline_cubica.py" +0 -0
  66. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/interpolaci/303/263n/inter_spline_lineal.py" +0 -0
  67. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/interpolaci/303/263n/interpolacion.py" +0 -0
  68. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ra/303/255ces/__init__.py" +0 -0
  69. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ra/303/255ces/secante_modificada.py" +0 -0
  70. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/ra/303/255ces/wegstein.py" +0 -0
  71. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy/utilidades.py +0 -0
  72. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy.egg-info/SOURCES.txt +0 -0
  73. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy.egg-info/dependency_links.txt +0 -0
  74. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy.egg-info/requires.txt +0 -0
  75. {mnspy-0.9.16 → mnspy-0.9.19}/mnspy.egg-info/top_level.txt +0 -0
  76. {mnspy-0.9.16 → mnspy-0.9.19}/pyproject.toml +0 -0
  77. {mnspy-0.9.16 → mnspy-0.9.19}/setup.cfg +0 -0
mnspy-0.9.19/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Edwin Córdoba
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mnspy
3
- Version: 0.9.16
3
+ Version: 0.9.19
4
4
  Summary: Paquete didáctico para métodos numéricos
5
5
  Home-page: https://github.com/EdwinSoft/mnspy
6
6
  Author: Edwin Córdoba
@@ -178,9 +178,48 @@ class Nodo:
178
178
  self._tipo_soporte = []
179
179
 
180
180
  def get_soporte(self):
181
+ """Obtiene la información del tipo de soporte asignado al nodo.
182
+
183
+ Esta información solo se utiliza para la representación gráfica en el
184
+ diagrama de cargas y no afecta los cálculos del análisis estructural.
185
+
186
+ Returns
187
+ -------
188
+ list[int]
189
+ Una lista de dos elementos que define el tipo y estilo del soporte.
190
+ """
181
191
  return self._tipo_soporte
182
192
 
183
193
  def set_soporte(self, sop: list[int]):
194
+ """Establece el tipo de soporte para el nodo.
195
+
196
+ Esta asignación es puramente para fines de visualización en el diagrama
197
+ de cargas y no interviene en los cálculos de la matriz de rigidez ni
198
+ en la resolución del sistema.
199
+
200
+ Parameters
201
+ ----------
202
+ sop : list[int]
203
+ Una lista de dos enteros que define el soporte:
204
+ - ``sop[0]``: Tipo de Apoyo
205
+ - 0: Pivotado
206
+ - 1: Empotrado
207
+ - ``sop[1]``: Estilo del Apoyo
208
+ - Si Tipo Apoyo es 0 (Pivotado):
209
+ - 0: inferior Móvil
210
+ - 1: inferior Fijo
211
+ - 2: superior Móvil
212
+ - 3: superior Fijo
213
+ - 4: izquierda Móvil
214
+ - 5: izquierda Fijo
215
+ - 6: derecha Móvil
216
+ - 7: derecha Fijo
217
+ - Si Tipo Apoyo es 1 (Empotrado):
218
+ - 0: fijo izquierdo
219
+ - 1: fijo derecha
220
+ - 2: fijo inferior
221
+ - 3: fijo superior
222
+ """
184
223
  self._tipo_soporte = sop
185
224
 
186
225
  def agregar_fuerza_externa(self, carga: float, gl: str) -> None:
@@ -88,17 +88,15 @@ class Biseccion(Raices):
88
88
  print("La raíz no está dentro de este rango, pruebe con otro rango de datos")
89
89
  sys.exit()
90
90
 
91
- # Bucle de iteración para evitar recursión profunda
92
- while True:
93
- self.x = (self._x_min + self._x_max) / 2
94
-
95
- if self._fin_iteracion():
96
- break # Convergencia o máximo de iteraciones alcanzado
97
-
98
- if np.sign(self._f(self._x_min)) == np.sign(self._f(self.x)):
99
- self._x_min = self.x
100
- else:
101
- self._x_max = self.x
91
+ self.x = (self._x_min + self._x_max) / 2
92
+ if self._fin_iteracion():
93
+ return
94
+ elif np.sign(self._f(self._x_min)) == np.sign(self._f(self.x)):
95
+ self._x_min = self.x
96
+ self._calcular()
97
+ elif np.sign(self._f(self._x_max)) == np.sign(self._f(self.x)):
98
+ self._x_max = self.x
99
+ self._calcular()
102
100
 
103
101
  def graficar(self, mostrar_sol: bool = True, mostrar_iter: bool = True, mostrar_lin_iter: bool = True,
104
102
  n_puntos: int = 100):
@@ -99,53 +99,48 @@ class Brent(Raices):
99
99
  "signos diferentes")
100
100
  sys.exit()
101
101
 
102
- # Bucle de iteración para evitar recursión profunda
103
- while True:
104
- x_a, x_b, x_c = self._val
105
- y_a, y_b, y_c = self._val_f
106
- x_d = 0 # No se usa en la lógica actual, pero se mantiene por si se reimplementa una condición
107
-
108
- self._x_min = min([x_a, x_b])
109
- self._x_max = max([x_a, x_b])
110
-
111
- if len(self._val_f) == len(set(self._val_f)):
112
- # Si los valores de y son distintos, se usa interpolación cuadrática inversa
113
- self.x = (x_a * y_b * y_c / ((y_a - y_b) * (y_a - y_c)) +
114
- x_b * y_a * y_c / ((y_b - y_a) * (y_b - y_c)) +
115
- x_c * y_a * y_b / ((y_c - y_a) * (y_c - y_b)))
116
- else:
117
- # Si hay valores de y repetidos, se usa el método de la secante (falsa posición)
118
- self.x = (y_a * x_b - y_b * x_a) / (y_a - y_b)
119
-
120
- # Se verifica si el paso de interpolación es aceptable, si no, se usa bisección
121
- cond1 = (self.x - (3 * x_a + x_b) / 4) * (self.x - x_b) >= 0
122
- cond2 = self._biseccion_usada and abs(self.x - x_b) >= abs(x_b - x_c) / 2
123
- cond3 = not self._biseccion_usada and abs(self.x - x_b) >= abs(x_c - x_d) / 2
124
-
125
- if cond1 or cond2 or cond3:
126
- self.x = (x_a + x_b) / 2
127
- self._biseccion_usada = True
128
- else:
129
- self._biseccion_usada = False
130
-
131
- if self._fin_iteracion():
132
- break
133
-
134
- y_x = self._f(self.x)
135
- x_c, y_c = x_b, y_b # Actualizar el punto previo
136
-
137
- if np.sign(y_a) == np.sign(y_x):
138
- x_a, y_a = self.x, y_x
139
- else:
140
- x_b, y_b = self.x, y_x
141
-
142
- # Se asegura de nuevo que |f(a)| > |f(b)| para la siguiente iteración
143
- if abs(y_a) < abs(y_b):
144
- x_a, x_b = x_b, x_a
145
- y_a, y_b = y_b, y_a
146
-
147
- self._val = x_a, x_b, x_c
148
- self._val_f = y_a, y_b, y_c
102
+ x_a, x_b, x_c = self._val
103
+ y_a, y_b, y_c = self._val_f
104
+ x_d = 0
105
+ self._x_min = min([x_a, x_b])
106
+ self._x_max = max([x_a, x_b])
107
+ if len(self._val_f) == len(set(self._val_f)):
108
+ # si los y son diferentes se usa el método de la cuadrática inversa
109
+ self.x = x_a * y_b * y_c / ((y_a - y_b) * (y_a - y_c)) + x_b * y_a * y_c / (
110
+ (y_b - y_a) * (y_b - y_c)) + x_c * y_a * y_b / ((y_c - y_a) * (y_c - y_b))
111
+ else:
112
+ # Se usa el método de la falsa posición
113
+ self.x = (y_a * x_b - y_b * x_a) / (y_a - y_b)
114
+ if (self.x - (3 * x_a + x_b) / 4) * (self.x - x_b) >= 0 or (
115
+ self._biseccion_usada and abs(self.x - x_b) >= abs(x_b - x_c) / 2) or (
116
+ not self._biseccion_usada and abs(self.x - x_b) >= abs(x_c - x_d) / 2):
117
+ self.x = (x_a + x_b) / 2
118
+ self._biseccion_usada = True
119
+ else:
120
+ self._biseccion_usada = False
121
+ y_x = self._f(self.x)
122
+ # x_d = x_c # TODO Revisar el código esta variable porque no se usa
123
+ x_c = x_b
124
+ y_c = y_b
125
+ if np.sign(y_a) == np.sign(y_x):
126
+ x_a = self.x
127
+ y_a = y_x
128
+ else:
129
+ x_b = self.x
130
+ y_b = y_x
131
+ if abs(y_a) < abs(y_b):
132
+ x_t = x_a
133
+ y_t = y_a
134
+ x_a = x_b
135
+ y_a = y_b
136
+ x_b = x_t
137
+ y_b = y_t
138
+ self._val = x_a, x_b, x_c
139
+ self._val_f = y_a, y_b, y_c
140
+ if self._fin_iteracion():
141
+ return
142
+ else:
143
+ self._calcular()
149
144
 
150
145
  def graficar(self, mostrar_sol: bool = True, mostrar_iter: bool = True, mostrar_lin_iter: bool = False,
151
146
  n_puntos: int = 100):
@@ -86,18 +86,16 @@ class FalsaPosicion(Raices):
86
86
  print("La raíz no está dentro de este rango, pruebe con otro rango de datos")
87
87
  sys.exit()
88
88
 
89
- # Bucle de iteración para evitar recursión profunda
90
- while True:
91
- self.x = self._x_max - (self._f(self._x_max) * (self._x_min - self._x_max)) / (
92
- self._f(self._x_min) - self._f(self._x_max))
93
-
94
- if self._fin_iteracion():
95
- break # Convergencia o máximo de iteraciones alcanzado
96
-
97
- if np.sign(self._f(self._x_min)) == np.sign(self._f(self.x)):
98
- self._x_min = self.x
99
- else:
100
- self._x_max = self.x
89
+ self.x = self._x_max - (self._f(self._x_max) * (self._x_min - self._x_max)) / (
90
+ self._f(self._x_min) - self._f(self._x_max))
91
+ if self._fin_iteracion():
92
+ return
93
+ elif np.sign(self._f(self._x_min)) == np.sign(self._f(self.x)):
94
+ self._x_min = self.x
95
+ self._calcular()
96
+ elif np.sign(self._f(self._x_max)) == np.sign(self._f(self.x)):
97
+ self._x_max = self.x
98
+ self._calcular()
101
99
 
102
100
  def graficar(self, mostrar_sol: bool = True, mostrar_iter: bool = True, mostrar_lin_iter: bool = True,
103
101
  n_puntos: int = 100):
@@ -88,40 +88,34 @@ class Muller(Raices):
88
88
  -------
89
89
  None
90
90
  """
91
- # Bucle de iteración para evitar recursión profunda
92
- while True:
93
- h_0 = self._x_1_i - self._x_0_i
94
- h_1 = self._x_2_i - self._x_1_i
95
- d_0 = (self._f(self._x_1_i) - self._f(self._x_0_i)) / h_0
96
- d_1 = (self._f(self._x_2_i) - self._f(self._x_1_i)) / h_1
97
-
98
- # Coeficientes de la parábola a*x^2 + b*x + c
99
- a = (d_1 - d_0) / (h_1 + h_0)
100
- b = a * h_1 + d_1
101
- c = self._f(self._x_2_i)
102
-
103
- # Guardar coeficientes para graficar
104
- self._a_2.append(a)
105
- self._a_1.append(d_0)
106
- self._a_0.append(self._f(self._x_0_i))
107
- self._list_x_0.append(self._x_0_i)
108
- self._list_x_1.append(self._x_1_i)
109
- self._list_x_2.append(self._x_2_i)
110
-
111
- # Fórmula cuadrática, se elige el denominador más grande para evitar restas catastróficas.
112
- rad = np.sqrt(b ** 2 - 4 * a * c)
113
- if abs(b + rad) > abs(b - rad):
114
- den = b + rad
115
- else:
116
- den = b - rad
117
-
118
- self.x = self._x_2_i - (2 * c / den)
119
-
120
- if self._fin_iteracion():
121
- break # Convergencia o máximo de iteraciones alcanzado
122
-
123
- # Actualizar los puntos para la siguiente iteración
124
- self._x_0_i, self._x_1_i, self._x_2_i = self._x_1_i, self._x_2_i, self.x
91
+ h_0 = self._x_1_i - self._x_0_i
92
+ h_1 = self._x_2_i - self._x_1_i
93
+ d_0 = (self._f(self._x_1_i) - self._f(self._x_0_i)) / h_0
94
+ d_1 = (self._f(self._x_2_i) - self._f(self._x_1_i)) / h_1
95
+ a = (d_1 - d_0) / (h_1 + h_0)
96
+ b = a * h_1 + d_1
97
+ c = self._f(self._x_2_i)
98
+ # ***
99
+ self._a_2 += [a]
100
+ self._a_1 += [d_0]
101
+ self._a_0 += [self._f(self._x_0_i)]
102
+ self._list_x_0 += [self._x_0_i]
103
+ self._list_x_1 += [self._x_1_i]
104
+ self._list_x_2 += [self._x_2_i]
105
+ # ***
106
+ rad = np.sqrt(b ** 2 - 4 * a * c)
107
+ if abs(b + rad) > abs(b - rad):
108
+ den = b + rad
109
+ else:
110
+ den = b - rad
111
+ self.x = self._x_2_i - 2 * c / den
112
+ if self._fin_iteracion():
113
+ return
114
+ else:
115
+ self._x_0_i = self._x_1_i
116
+ self._x_1_i = self._x_2_i
117
+ self._x_2_i = self.x
118
+ self._calcular()
125
119
 
126
120
  def graficar(self, mostrar_sol: bool = True, mostrar_iter: bool = True, mostrar_lin_iter: bool = True,
127
121
  n_puntos: int = 100):
@@ -117,9 +117,11 @@ class NewtonRaphson(Raices):
117
117
  -------
118
118
  None
119
119
  """
120
- # Bucle de iteración para evitar recursión profunda
121
- while not self._fin_iteracion():
122
- self.x -= self._f(self.x) / self._df(self.x)
120
+ self.x -= self._f(self.x) / self._df(self.x)
121
+ if self._fin_iteracion():
122
+ return
123
+ else:
124
+ self._calcular()
123
125
 
124
126
  def graficar(self, mostrar_sol: bool = True, mostrar_iter: bool = True, mostrar_lin_iter: bool = True,
125
127
  n_puntos: int = 100):
@@ -74,10 +74,11 @@ class PuntoFijo(Raices):
74
74
  -------
75
75
  None
76
76
  """
77
- # Bucle de iteración para evitar recursión profunda
78
- while not self._fin_iteracion():
79
- # self.x = self._f(self.x) # La función f es en realidad g(x)
80
- self.x = self._f(self.x)
77
+ self.x += self._f(self.x) - self.x
78
+ if self._fin_iteracion():
79
+ return
80
+ else:
81
+ self._calcular()
81
82
 
82
83
  def graficar(self, mostrar_sol: bool = True, mostrar_iter: bool = True, mostrar_lin_iter: bool = True,
83
84
  n_puntos: int = 100):
@@ -4,7 +4,6 @@ from mnspy.utilidades import es_notebook
4
4
  from tabulate import tabulate
5
5
  import math
6
6
  import sys
7
- plt.rcParams.update(plt.rcParamsDefault)
8
7
 
9
8
  class Raices:
10
9
  """
@@ -82,11 +81,13 @@ class Raices:
82
81
  Tipo de error a utilizar para la convergencia:
83
82
  - ``'%'``: Error relativo porcentual (por defecto).
84
83
  - ``'/'``: Error relativo.
85
- - ``'n'``: Número de cifras significativas.
84
+ - ``'n'``: Número de cifras significativas. εs = (0.5 * 10^(2-n))% [Scarborough, 1966]
85
+ - ``'t'``: Tolerancia. tol = |b - a|/2 (Solo aplica en los métodos cerrados)
86
86
  """
87
87
  self._f = f
88
88
  self._tol = tol
89
- # tipo de error es '%' , '/' o 'n'
89
+ # tipo de error es '%' , '/' , 'n' ó 't'
90
+ self._error_tolerancia = False # Solo se puede usar en métodos cerrados
90
91
  match tipo_error:
91
92
  case "%":
92
93
  self._error_porcentual = True
@@ -95,8 +96,11 @@ class Raices:
95
96
  case "n":
96
97
  self._tol = 0.5 * 10 ** (2 - tol)
97
98
  self._error_porcentual = True
99
+ case "t":
100
+ self._error_porcentual = False
101
+ self._error_tolerancia = True
98
102
  case _:
99
- print("Tipo de error no valido, las opciones son: '%', '/', 'n'")
103
+ print("Tipo de error no valido, las opciones son: '%', '/', 'n', 't'")
100
104
  sys.exit()
101
105
  self._max_iter = max_iter
102
106
  self._x_min = x_min
@@ -105,7 +109,7 @@ class Raices:
105
109
  self._x_0 = None
106
110
  self._x_1 = None
107
111
  self._tabla = {'x_min': [], 'x_max': [], 'x': [], 'Ea': []}
108
- self._fmt = {'iter': 'd', 'x_l': '.5f', 'x_u': '.5f', 'x': '.10f', 'f': '.8f', 'E_a': '0.5%', 'E_t': '0.5%'}
112
+ self._fmt = {'iter': 'd', 'x_l': '.5f', 'x_u': '.5f', 'x': '.10f', 'f': '.8f', 'E_a': '0.5%', 'E_t': '0.5%' , 'tol': '0.8f'}
109
113
  self._converge = False
110
114
  self._rango = x_min, x_max
111
115
  plt.ioff() # deshabilitada interactividad matplotlib
@@ -115,7 +119,7 @@ class Raices:
115
119
  Ajusta el formato de presentación de los datos en las tablas.
116
120
 
117
121
  Por defecto el formato es
118
- {'iter': 'd', 'x_l': '.5f', 'x_u': '.5f', 'x': '.10f', 'f': '.8f', 'E_a': '0.5%', 'E_t': '0.5%'}
122
+ {'iter': 'd', 'x_l': '.5f', 'x_u': '.5f', 'x': '.10f', 'f': '.8f', 'E_a': '0.5%', 'E_t': '0.5%', 'tol': '0.8f'}
119
123
 
120
124
  Parameters
121
125
  ----------
@@ -128,8 +132,8 @@ class Raices:
128
132
  -------
129
133
  None
130
134
  """
131
- if col == 'x_r' or col == 'x_i':
132
- col = 'x'
135
+ # if col == 'x_r' or col == 'x_i':
136
+ # col = 'x'
133
137
  self._fmt[col] = fmt
134
138
 
135
139
  def generar_tabla(self, valor_real: float = None, tablefmt=None):
@@ -160,41 +164,41 @@ class Raices:
160
164
  if self._x_min is not None:
161
165
  valores = np.array(
162
166
  [self._tabla['x_min'], self._tabla['x_max'], self._tabla['x'], [self._f(val) for val in self._tabla['x']],
163
- self._tabla['Ea']]).transpose()
167
+ self._tabla['Ea'], list(np.abs(np.array(self._tabla['x_max']) -np.array(self._tabla['x_min']))/2.0)]).transpose()
164
168
  if es_notebook() and (tablefmt is None or tablefmt in render_notebook):
165
169
  if tablefmt is None:
166
170
  tablefmt = 'html'
167
171
  if valor_real is None:
168
172
  return tabulate(valores, ['Iteración', '$x_{l}$', '$x_{u}$', '$x_{r}$', r'$f\left(x_{r}\right)$',
169
- r'$\varepsilon_{a}$'], showindex=list(range(1, len(self._tabla['x']) + 1)),
173
+ r'$\varepsilon_{a}$', 'Tolerancia'], showindex=list(range(1, len(self._tabla['x']) + 1)),
170
174
  tablefmt=tablefmt, floatfmt=(
171
175
  self._fmt['iter'], self._fmt['x_l'], self._fmt['x_u'], self._fmt['x'], self._fmt['f'],
172
- self._fmt['E_a']), colalign=("center",))
176
+ self._fmt['E_a'], self._fmt['tol']), colalign=("center",))
173
177
  else:
174
178
  e_t = abs((np.array([self._tabla['x']]).transpose() - valor_real) / valor_real)
175
179
  valores = np.hstack((valores, e_t))
176
180
  return tabulate(valores, ['Iteración', '$x_{l}$', '$x_{u}$', '$x_{r}$', r'$f\left(x_{r}\right)$',
177
- r'$\varepsilon_{a}$', r'$\varepsilon_{t}$'],
181
+ r'$\varepsilon_{a}$', 'Tolerancia' , r'$\varepsilon_{t}$'],
178
182
  showindex=list(range(1, len(self._tabla['x']) + 1)), tablefmt=tablefmt, floatfmt=(
179
183
  self._fmt['iter'], self._fmt['x_l'], self._fmt['x_u'], self._fmt['x'], self._fmt['f'],
180
- self._fmt['E_a'], self._fmt['E_t']), colalign=("center",))
184
+ self._fmt['E_a'], self._fmt['tol'], self._fmt['E_t']), colalign=("center",))
181
185
  else:
182
186
  if tablefmt is None:
183
187
  tablefmt = 'simple'
184
188
  if valor_real is None:
185
- print(tabulate(valores, ['Iteración', 'x_l', 'x_u', 'x_r', 'f(x_r)', 'E_a'],
189
+ print(tabulate(valores, ['Iteración', 'x_l', 'x_u', 'x_r', 'f(x_r)', 'E_a', 'tol'],
186
190
  showindex=list(range(1, len(self._tabla['x']) + 1)), tablefmt=tablefmt,
187
191
  floatfmt=(
188
- self._fmt['iter'], self._fmt['x_l'], self._fmt['x_u'], self._fmt['x'], self._fmt['f'],
189
- self._fmt['E_a']), colalign=("center",)))
192
+ self._fmt['iter'], self._fmt['x_l'], self._fmt['x_u'], self._fmt['x'], self._fmt['f'] ,
193
+ self._fmt['E_a'], self._fmt['tol']), colalign=("center",)))
190
194
  else:
191
195
  e_t = abs((np.array([self._tabla['x']]).transpose() - valor_real) / valor_real)
192
196
  valores = np.hstack((valores, e_t))
193
- print(tabulate(valores, ['Iteración', 'x_l', 'x_u', 'x_r', 'f(x_r)', 'E_a', 'E_t'],
197
+ print(tabulate(valores, ['Iteración', 'x_l', 'x_u', 'x_r', 'f(x_r)', 'E_a', 'tol','E_t'],
194
198
  showindex=list(range(1, len(self._tabla['x']) + 1)), tablefmt=tablefmt,
195
199
  floatfmt=(
196
200
  self._fmt['iter'], self._fmt['x_l'], self._fmt['x_u'], self._fmt['x'], self._fmt['f'],
197
- self._fmt['E_a'], self._fmt['E_t']), colalign=("center",)))
201
+ self._fmt['E_a'], self._fmt['tol'], self._fmt['E_t']), colalign=("center",)))
198
202
  else:
199
203
  valores = np.array([self._tabla['x'], self._f(np.array(self._tabla['x'])), self._tabla['Ea']]).transpose()
200
204
  if es_notebook() and (tablefmt is None or tablefmt in render_notebook):
@@ -275,6 +279,16 @@ class Raices:
275
279
  return False
276
280
  else:
277
281
  return False
282
+ elif self._error_tolerancia:
283
+ if self._rango == (None, None):
284
+ print('El tipo de error ''t'' solo aplica a los métodos cerrados')
285
+ return False
286
+ else:
287
+ if abs(self._tabla['x_max'][-1]-self._tabla['x_min'][-1])/2.0 < self._tol:
288
+ self._converge = True
289
+ return True
290
+ else:
291
+ return False
278
292
  else:
279
293
  lon = len(self._tabla['x'])
280
294
  if lon > 1:
@@ -370,6 +384,9 @@ class Raices:
370
384
  -------
371
385
  Tabla con los resultados finales de la iteración.
372
386
  """
387
+ if type(self) is Raices: # Si la clase es Raíces, no tiene método asociado y solo sirve para graficar
388
+ print('No se generó solución')
389
+ return None
373
390
  if self._converge:
374
391
  if es_notebook():
375
392
  valores = [['$x$:', self.x], ['$f(x)$:', self._f(self.x)],
@@ -400,6 +417,5 @@ def main():
400
417
  graf = Raices(z, 0, 5)
401
418
  graf.graficar()
402
419
 
403
-
404
420
  if __name__ == '__main__':
405
421
  main()
@@ -80,13 +80,14 @@ class Secante(Raices):
80
80
  -------
81
81
  None
82
82
  """
83
- # Bucle de iteración para evitar recursión profunda
84
- while not self._fin_iteracion():
85
- # Fórmula del método de la secante
86
- self.x = self._x_1_i - (self._f(self._x_1_i) * (self._x_1_i - self._x_0_i)) / (
87
- self._f(self._x_1_i) - self._f(self._x_0_i))
88
- # Actualizar los puntos para la siguiente iteración
89
- self._x_0_i, self._x_1_i = self._x_1_i, self.x
83
+ self.x -= (self._f(self._x_1_i) * (self._x_1_i - self._x_0_i)) / (
84
+ self._f(self._x_1_i) - self._f(self._x_0_i))
85
+ self._x_0_i = self._x_1_i
86
+ self._x_1_i = self.x
87
+ if self._fin_iteracion():
88
+ return
89
+ else:
90
+ self._calcular()
90
91
 
91
92
  def graficar(self, mostrar_sol: bool = True, mostrar_iter: bool = True, mostrar_lin_iter: bool = True,
92
93
  n_puntos: int = 100):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mnspy
3
- Version: 0.9.16
3
+ Version: 0.9.19
4
4
  Summary: Paquete didáctico para métodos numéricos
5
5
  Home-page: https://github.com/EdwinSoft/mnspy
6
6
  Author: Edwin Córdoba
@@ -2,7 +2,7 @@ from setuptools import setup
2
2
 
3
3
  setup(
4
4
  name='mnspy',
5
- version='0.9.16',
5
+ version='0.9.19',
6
6
  packages=['mnspy', 'mnspy.raíces', 'mnspy.derivada', 'mnspy.integrales', 'mnspy.interpolación',
7
7
  'mnspy.ecuaciones_algebraicas_lineales', 'mnspy.ecuaciones_diferenciales_ordinarias',
8
8
  'mnspy.ecuaciones_diferenciales_parciales', 'mnspy.ecuaciones_diferenciales_parciales.mdf',