Initial Refactoring of yoshi_otter and Test Implementation
This commit is contained in:
21
yoshi_otter/__init__.py
Normal file
21
yoshi_otter/__init__.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# Otter - Program made for educational intent, can be freely distributed
|
||||
# and can be used for economical intent. I will not take legal actions
|
||||
# unless my intelectual propperty, the code, is stolen or change without permission.
|
||||
|
||||
# Copyright (C) 2020 VItor Hideyoshi Nakazone Batista
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as published by
|
||||
# the Free Software Foundation.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from yoshi_otter.algebra import Algebra
|
||||
from yoshi_otter.interpolation import Interpolation
|
||||
52
yoshi_otter/algebra/__algebra.py
Normal file
52
yoshi_otter/algebra/__algebra.py
Normal file
@@ -0,0 +1,52 @@
|
||||
# Otter - Program made for educational intent, can be freely distributed
|
||||
# and can be used for economical intent. I will not take legal actions
|
||||
# unless my intelectual propperty, the code, is stolen or change without permission.
|
||||
#
|
||||
# Copyright (C) 2020 VItor Hideyoshi Nakazone Batista
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as published by
|
||||
# the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from yoshi_otter.algebra.integral.double import Double
|
||||
from yoshi_otter.algebra.integral.simple import Simple
|
||||
from yoshi_otter.algebra.roots import Roots
|
||||
from yoshi_otter.algebra.edo import Edo
|
||||
|
||||
from typing import Callable, Union
|
||||
from inspect import signature
|
||||
|
||||
from yoshi_otter.shared import InvalidFunctionSignature
|
||||
|
||||
|
||||
class Algebra:
|
||||
|
||||
def __init__(self, function: Callable[[float], float] | Callable[[float, float], float]) -> None:
|
||||
self.f = function
|
||||
|
||||
self.integral = self.__Integral(self.f)
|
||||
self.roots = Roots(self.f)
|
||||
self.edo = Edo(self.f)
|
||||
|
||||
def d(self, x: float, e: float = 10 ** -4) -> float:
|
||||
if len(signature(self.f).parameters) == 1:
|
||||
return (self.f(x + e) - self.f(x - e)) / (2 * e)
|
||||
else:
|
||||
raise InvalidFunctionSignature("This method is only valid for one dimensional functions.")
|
||||
|
||||
class __Integral:
|
||||
|
||||
def __init__(self, function: Union[Callable[[float], float], Callable[[float, float], float]]) -> None:
|
||||
self.f = function
|
||||
|
||||
self.simple = Simple(self.f)
|
||||
self.double = Double(self.f)
|
||||
1
yoshi_otter/algebra/__init__.py
Normal file
1
yoshi_otter/algebra/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .__algebra import Algebra
|
||||
51
yoshi_otter/algebra/edo/__edo.py
Normal file
51
yoshi_otter/algebra/edo/__edo.py
Normal file
@@ -0,0 +1,51 @@
|
||||
from typing import Callable
|
||||
|
||||
|
||||
class Edo:
|
||||
|
||||
def __init__(self, function: Callable[[float], float]) -> None:
|
||||
self.F = function
|
||||
|
||||
def euler(self, a: float, y: float, b: float, n: int = 10**6) -> float:
|
||||
|
||||
dx = (b - a) / n
|
||||
|
||||
def x(i):
|
||||
return a + i * dx
|
||||
|
||||
for i in range(n):
|
||||
y = y + (self.F(x(i), y)) * dx
|
||||
|
||||
return y
|
||||
|
||||
def runge(self, a: float, y: float, b: float, n: int = 10**6) -> float:
|
||||
|
||||
dx = (b - a) / n
|
||||
|
||||
def x(i):
|
||||
return a + i * dx
|
||||
|
||||
for i in range(n):
|
||||
y = y + (dx / 2) * (self.F(x(i), y) + self.F(x(i + 1), (y + (dx * self.F(x(i), y)))))
|
||||
|
||||
return y
|
||||
|
||||
def adams(self, a: float, y: float, b: float, n: int = None
|
||||
) -> float:
|
||||
|
||||
if n is None:
|
||||
n = 10 ** 6
|
||||
|
||||
dx = (b - a) / n
|
||||
|
||||
def x(i):
|
||||
return a + i * dx
|
||||
|
||||
for i in range(n):
|
||||
f0 = self.F(x(i), y)
|
||||
f1 = self.F(x(i + 1), y + dx * self.F(x(i) + (dx / 2), y + (dx / 2) * self.F(x(i), y)))
|
||||
f2 = self.F(x(i + 2), y + (dx / 2) * (3 * f1 - f0))
|
||||
|
||||
y += (dx / 12) * (5 * f2 + 8 * f1 - f0)
|
||||
|
||||
return y
|
||||
1
yoshi_otter/algebra/edo/__init__.py
Normal file
1
yoshi_otter/algebra/edo/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .__edo import Edo
|
||||
0
yoshi_otter/algebra/integral/__init__.py
Normal file
0
yoshi_otter/algebra/integral/__init__.py
Normal file
79
yoshi_otter/algebra/integral/double.py
Normal file
79
yoshi_otter/algebra/integral/double.py
Normal file
@@ -0,0 +1,79 @@
|
||||
from typing import Callable
|
||||
|
||||
|
||||
class Double:
|
||||
|
||||
def __init__(self, function: Callable[[float, float], float]):
|
||||
self.f = function
|
||||
|
||||
def riemann(self, a: float, b: float, c: float, d: float,
|
||||
n: int = 10 ** 4, m: int = None) -> float:
|
||||
|
||||
if m is None:
|
||||
m = n
|
||||
|
||||
dx = (b - a) / n
|
||||
dy = (d - c) / m
|
||||
kappa = a
|
||||
psi = c
|
||||
theta = 0
|
||||
|
||||
while (psi + dy) < d:
|
||||
|
||||
while (kappa + dx) < b:
|
||||
theta = theta + self.f(kappa, psi)
|
||||
kappa = kappa + dx
|
||||
|
||||
psi = psi + dy
|
||||
kappa = a
|
||||
|
||||
return theta * dx * dy
|
||||
|
||||
def simpson(self, a: float, b: float, c: float, d: float,
|
||||
n: int = 10 ** 4, m: int = None) -> float:
|
||||
|
||||
if m is None:
|
||||
m = n
|
||||
|
||||
dx = (b - a) / n
|
||||
dy = (d - c) / m
|
||||
|
||||
def x(i):
|
||||
return a + i * dx
|
||||
|
||||
def y(i):
|
||||
return c + i * dy
|
||||
|
||||
def g(i):
|
||||
|
||||
sigma = 0
|
||||
upsilon = 0
|
||||
|
||||
zeta = 1
|
||||
csi = 1
|
||||
|
||||
while zeta <= (m / 2):
|
||||
sigma += self.f(x(i), y(2 * zeta - 1))
|
||||
zeta += 1
|
||||
|
||||
while csi <= ((m / 2) - 1):
|
||||
upsilon += self.f(x(i), y(2 * csi))
|
||||
csi += 1
|
||||
|
||||
return (dy / 3) * (self.f(x(i), y(0)) + self.f(x(i), y(m)) + 4 * sigma + 2 * upsilon)
|
||||
|
||||
eta = 0
|
||||
theta = 0
|
||||
|
||||
psi = 1
|
||||
kappa = 1
|
||||
|
||||
while psi <= (n / 2):
|
||||
eta += g(2 * psi - 1)
|
||||
psi += 1
|
||||
|
||||
while kappa <= ((n / 2) - 1):
|
||||
theta += g(2 * kappa)
|
||||
kappa += 1
|
||||
|
||||
return (dx / 3) * (g(0) + g(n) + 4 * eta + 2 * theta)
|
||||
44
yoshi_otter/algebra/integral/simple.py
Normal file
44
yoshi_otter/algebra/integral/simple.py
Normal file
@@ -0,0 +1,44 @@
|
||||
from typing import Callable
|
||||
|
||||
|
||||
class Simple:
|
||||
def __init__(self, function: Callable[[float], float]) -> None:
|
||||
self.f = function
|
||||
|
||||
def riemann(self, a: float, b: float, n: int = 10 ** 6) -> float:
|
||||
|
||||
delta = (b - a) / n
|
||||
|
||||
psi = a
|
||||
theta = 0
|
||||
|
||||
while (psi + delta) <= b:
|
||||
theta += (self.f(psi) + self.f(psi + delta)) / 2
|
||||
psi += delta
|
||||
|
||||
integral = delta * theta
|
||||
|
||||
return integral
|
||||
|
||||
def simpson(self, a: float, b: float, n: int = 10 ** 6) -> float:
|
||||
|
||||
def x(i):
|
||||
return a + i * h
|
||||
|
||||
h = (b - a) / n
|
||||
|
||||
eta = 0
|
||||
theta = 0
|
||||
|
||||
psi = 1
|
||||
kappa = 1
|
||||
|
||||
while psi <= (n / 2):
|
||||
eta = eta + self.f(x(2 * psi - 1))
|
||||
psi = psi + 1
|
||||
|
||||
while kappa <= ((n / 2) - 1):
|
||||
theta = theta + self.f(x(2 * kappa))
|
||||
kappa = kappa + 1
|
||||
|
||||
return (h / 3) * (self.f(x(0)) + self.f(x(n)) + 4 * eta + 2 * theta)
|
||||
1
yoshi_otter/algebra/roots/__init__.py
Normal file
1
yoshi_otter/algebra/roots/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .__roots import Roots
|
||||
80
yoshi_otter/algebra/roots/__roots.py
Normal file
80
yoshi_otter/algebra/roots/__roots.py
Normal file
@@ -0,0 +1,80 @@
|
||||
from typing import Callable
|
||||
|
||||
|
||||
class Roots:
|
||||
|
||||
def __init__(self, function: Callable[[float], float] = None
|
||||
) -> float:
|
||||
if function is not None:
|
||||
self.f = function
|
||||
|
||||
def bissec(self, a: float, b: float, e: float = 10**-6) -> float:
|
||||
|
||||
fa = self.f(a)
|
||||
|
||||
while abs(a - b) > e:
|
||||
|
||||
c = (a + b) / 2
|
||||
fc = self.f(c)
|
||||
|
||||
if (fa * fc) < 0:
|
||||
|
||||
b = c
|
||||
|
||||
else:
|
||||
|
||||
a = c
|
||||
|
||||
c = (a + b) / 2
|
||||
|
||||
return c
|
||||
|
||||
def __d(self, x: float, e: float) -> float:
|
||||
return (self.f(x + e) - self.f(x - e)) / (2 * e)
|
||||
|
||||
def newton(self, a: float, e: float = 10**-6) -> float:
|
||||
|
||||
fa = self.f(a)
|
||||
da = self.__d(a, e)
|
||||
b = a - fa / da
|
||||
|
||||
while abs(a - b) > e:
|
||||
b = a
|
||||
a -= (fa / da)
|
||||
fa = self.f(a)
|
||||
da = self.__d(a, e)
|
||||
|
||||
return a
|
||||
|
||||
def bissec_newton(self, a: float, b: float, e: float = 10**-6) -> float:
|
||||
|
||||
fa = self.f(a)
|
||||
|
||||
c = (a + b) / 2 # 'c' é a raiz calculada
|
||||
|
||||
while abs(a - b) > 0.1:
|
||||
|
||||
fc = self.f(c)
|
||||
|
||||
if fa * fc < 0:
|
||||
|
||||
b = c
|
||||
|
||||
else:
|
||||
|
||||
a = c
|
||||
fa = self.f(a)
|
||||
|
||||
c = (a + b) / 2
|
||||
|
||||
fc = self.f(c)
|
||||
dc = self.__d(c, e)
|
||||
h = c - fc / dc # 'h' é uma variável de controle
|
||||
|
||||
while abs(c - h) > e:
|
||||
h = c
|
||||
c -= (fc / dc)
|
||||
fc = self.f(c)
|
||||
dc = self.__d(c, e)
|
||||
|
||||
return c
|
||||
1
yoshi_otter/interpolation/__init__.py
Normal file
1
yoshi_otter/interpolation/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .__interpolation import Interpolation
|
||||
183
yoshi_otter/interpolation/__interpolation.py
Normal file
183
yoshi_otter/interpolation/__interpolation.py
Normal file
@@ -0,0 +1,183 @@
|
||||
from typing import Callable, Any
|
||||
|
||||
from yoshi_seals import process as sl
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
class Interpolation:
|
||||
"""
|
||||
Data should be organized in a dataframe of two columns: X and Y
|
||||
"""
|
||||
|
||||
def __init__(self, data) -> None:
|
||||
|
||||
self.data = data
|
||||
self.polynomial = self.Polynomial(self.data)
|
||||
|
||||
def minimums(self) -> Callable[[Any], float]:
|
||||
|
||||
theta = 0
|
||||
# somatorio de x
|
||||
for i in range(self.data.shape[0]):
|
||||
theta += self.data.X[i]
|
||||
|
||||
eta = 0
|
||||
# somatorio de y
|
||||
for i in range(self.data.shape[0]):
|
||||
eta += self.data.Y[i]
|
||||
|
||||
sigma = 0
|
||||
# somatorio de xy
|
||||
for i in range(self.data.shape[0]):
|
||||
sigma += self.data.X[i] * self.data.Y[i]
|
||||
|
||||
omega = 0
|
||||
# somatorio de x^2self.dself.dself.d
|
||||
for i in range(self.data.shape[0]):
|
||||
omega += self.data.X[i] ** 2
|
||||
|
||||
a = (self.data.shape[0] * sigma - theta * eta) / (self.data.shape[0] * omega - (theta ** 2))
|
||||
|
||||
b = (theta * sigma - eta * omega) / ((theta ** 2) - self.data.shape[0] * omega)
|
||||
|
||||
ym = 0
|
||||
|
||||
for i in range(self.data.shape[0]):
|
||||
ym += self.data.Y[i] / self.data.shape[0]
|
||||
|
||||
sqreq = 0
|
||||
|
||||
for i in range(self.data.shape[0]):
|
||||
sqreq += ((a * self.data.X[i] + b) - ym) ** 2
|
||||
|
||||
sqtot = 0
|
||||
|
||||
for i in range(self.data.shape[0]):
|
||||
sqtot += (self.data.Y[i] - ym) ** 2
|
||||
|
||||
r2 = sqreq / sqtot
|
||||
|
||||
return lambda x: a * x + b, r2
|
||||
|
||||
class Polynomial:
|
||||
|
||||
def __init__(self, data) -> None:
|
||||
self.data = data
|
||||
|
||||
def vandermonde(self) -> Callable[[Any], float]:
|
||||
|
||||
matrix = np.zeros((self.data.shape[0], self.data.shape[0]))
|
||||
|
||||
for k in range(0, self.data.shape[0]):
|
||||
matrix[:, k] = self.data.X[:] ** k
|
||||
|
||||
array = np.array(self.data.Y.tolist()).reshape(self.data.shape[0], 1)
|
||||
A = sl.gauss(matrix, array)
|
||||
|
||||
def f(coefficient_matrix, x):
|
||||
|
||||
y = 0
|
||||
|
||||
for i in range(0, A.shape[0]):
|
||||
y += coefficient_matrix[1][i] * (x ** i)
|
||||
|
||||
return y
|
||||
|
||||
return lambda x: f(A, x)
|
||||
|
||||
def lagrange(self, x: float) -> float:
|
||||
|
||||
def L(k, x):
|
||||
|
||||
up = 1
|
||||
down = 1
|
||||
|
||||
for i in [x for x in range(self.data.X.shape[0]) if x != k]:
|
||||
up = up * (x - self.data.X[i])
|
||||
|
||||
for i in [x for x in range(self.data.X.shape[0]) if x != k]:
|
||||
down = down * (self.data.X[k] - self.data.X[i])
|
||||
|
||||
return up / down
|
||||
|
||||
y = 0
|
||||
|
||||
for i in range(self.data.X.shape[0]):
|
||||
y += self.data.Y[i] * L(i, x)
|
||||
|
||||
return y
|
||||
|
||||
def newton(self, x: float) -> float:
|
||||
|
||||
d = np.array(np.zeros((self.data.shape[0], self.data.shape[0])))
|
||||
|
||||
d[0] = self.data.Y
|
||||
|
||||
i = j = 0
|
||||
|
||||
while i < self.data.shape[0]:
|
||||
|
||||
while j < (self.data.shape[0] - (i + 1)):
|
||||
d[i + 1][j] = (d[i][j + 1] - d[i][j]) / (self.data.X[(i + 1) + j] - self.data.X[j])
|
||||
j += 1
|
||||
|
||||
i += 1
|
||||
j = 0
|
||||
|
||||
def f(x):
|
||||
|
||||
y = d[0][0]
|
||||
i = 0
|
||||
|
||||
while (i + 1) < self.data.shape[0]:
|
||||
|
||||
mult = 1
|
||||
k = 0
|
||||
while k <= i:
|
||||
mult = mult * (x - self.data.X[k])
|
||||
k += 1
|
||||
|
||||
y += d[i + 1][0] * mult
|
||||
i += 1
|
||||
|
||||
return y
|
||||
|
||||
self.f = f
|
||||
|
||||
return f(x)
|
||||
|
||||
def gregory(self, x: float) -> float:
|
||||
|
||||
h = self.data.X[0] - self.data.X[1]
|
||||
|
||||
d = np.array(np.zeros((self.data.shape[0], self.data.shape[0])))
|
||||
|
||||
d[0] = self.data.Y
|
||||
|
||||
i = j = 0
|
||||
|
||||
while i < self.data.shape[0]:
|
||||
|
||||
while j < (self.data.shape[0] - (i + 1)):
|
||||
d[i + 1][j] = (d[i][j + 1] - d[i][j]) / ((i + 1) * h)
|
||||
j += 1
|
||||
|
||||
i += 1
|
||||
j = 0
|
||||
|
||||
y = d[0][0]
|
||||
i = 0
|
||||
|
||||
while (i + 1) < self.data.shape[0]:
|
||||
|
||||
mult = 1
|
||||
k = 0
|
||||
while k <= i:
|
||||
mult = mult * (x - self.data.X[k])
|
||||
k += 1
|
||||
|
||||
y += d[i + 1][0] * mult
|
||||
i += 1
|
||||
|
||||
return y
|
||||
1
yoshi_otter/shared/__init__.py
Normal file
1
yoshi_otter/shared/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .invalid_function_signature import InvalidFunctionSignature
|
||||
2
yoshi_otter/shared/invalid_function_signature.py
Normal file
2
yoshi_otter/shared/invalid_function_signature.py
Normal file
@@ -0,0 +1,2 @@
|
||||
class InvalidFunctionSignature(Exception):
|
||||
pass
|
||||
Reference in New Issue
Block a user