feat(cm): update lab#3

This commit is contained in:
maxbarsukov 2024-04-02 02:54:26 +03:00
parent 7db320f11a
commit baa7ab39fe
9 changed files with 213 additions and 492 deletions

View File

@ -0,0 +1,44 @@
from sympy import *
x = symbols('x')
f = -3*x**3 - 5*x**2 + 4*x - 2
a, b = -3, -1
n = 10
h = (b-a) / n
sum_midpoint = 0
for i in range(n):
x_i = a + (i + 0.5) * h
sum_midpoint += f.subs(x, x_i)
integral_midpoint = h * sum_midpoint
sum_trapezoid = 0
for i in range(1, n):
x_i = a + i * h
sum_trapezoid += f.subs(x, x_i)
integral_trapezoid = h / 2 * (f.subs(x, a) + 2*sum_trapezoid + f.subs(x, b))
sum_simpson = 0
for i in range(1, n//2):
x_i = a + (2*i) * h
sum_simpson += f.subs(x, x_i)
sum_simpson_2 = 0
for i in range(1, n//2 + 1):
x_i = a + (2*i - 1) * h
sum_simpson_2 += f.subs(x, x_i)
integral_simpson = h / 3 * (f.subs(x, a) + 4*sum_simpson + 2*sum_simpson_2 + f.subs(x, b))
print(integral_midpoint)
print(integral_trapezoid)
print(integral_simpson)

View File

@ -0,0 +1,22 @@
from sympy import *
x = symbols('x')
f = -3*x**3 - 5*x**2 + 4*x - 2
a, b = -3, -1
n = 5
h = (b - a) / n
fa = f.subs(x, a)
f1 = f.subs(x, a + h)
f2 = f.subs(x, a + 2*h)
f3 = f.subs(x, a + 3*h)
f4 = f.subs(x, a + 4*h)
fb = f.subs(x, b)
integral = (b-a)/n * ((7/90)*fa + (32/90)*f1 + (12/90)*f2 + (32/90)*f3 + (7/90)*fb)
integral.evalf()
print(integral)

View File

@ -1,10 +0,0 @@
PURPLE = "\033[95m"
CYAN = "\033[96m"
DARKCYAN = "\033[36m"
BLUE = "\033[94m"
GREEN = "\033[92m"
YELLOW = "\033[93m"
RED = "\033[91m"
BOLD = "\033[1m"
UNDERLINE = "\033[4m"
END = "\033[0m"

View File

@ -1,54 +0,0 @@
import math
def function(type_equation, x):
try:
if type_equation == 1:
return math.pow(x, 2) - 3
elif type_equation == 2:
return 5 / x - 2 * x
elif type_equation == 3:
return math.exp(2 * x) - 2
elif type_equation == 4:
return 2 * math.pow(x, 3) - 3 * math.pow(x, 2) + 5 * x - 9
except ZeroDivisionError:
raise TypeError
def first_derivative(type_equation, x):
try:
if type_equation == 1:
return 2 * x
elif type_equation == 2:
return -5 / math.pow(x, 2) - 2
elif type_equation == 3:
return 2 * math.exp(2 * x)
elif type_equation == 4:
return 6 * math.pow(x, 2) - 6 * x + 5
except ZeroDivisionError:
return first_derivative(x + 1e-8)
def second_derivative(type_equation, x):
try:
if type_equation == 1:
return 2
elif type_equation == 2:
return 10 / math.pow(x, 3)
elif type_equation == 3:
return 4 * math.exp(2 * x)
elif type_equation == 4:
return 12 * x - 6
except ZeroDivisionError:
return second_derivative(x + 1e-8)
def fourth_derivative(type_equation, x):
try:
if type_equation == 1:
return 0
elif type_equation == 2:
return 120 / math.pow(x, 5)
elif type_equation == 3:
return 16 * math.exp(2 * x)
elif type_equation == 4:
return 0
except ZeroDivisionError:
return fourth_derivative(x + 1e-8)

View File

@ -1,34 +1,154 @@
import colors as color
import selector as select
import math
def f1(x):
return x**2
def f2(x):
return math.sin(x)
def f3(x):
return math.exp(x)
def f4(x):
return 1 / x**2
def f5(x):
return 1 / x
def f6(x):
return 1 / math.sqrt(x)
def f7(x):
return -3*x**3 - 5*x**2 + 4*x - 2
functions = [f1, f2, f3, f4, f5, f6, f7]
def rectangle_rule(func, a, b, n, mode="middle"):
h = (b - a) / n
result = 0
if mode == "left":
for i in range(n):
result += func(a + i * h)
elif mode == "right":
for i in range(1, n + 1):
result += func(a + i * h)
else:
for i in range(n):
result += func(a + (i + 0.5) * h)
result *= h
return result
def trapezoid_rule(func, a, b, n):
h = (b - a) / n
result = (func(a) + func(b)) / 2
for i in range(1, n):
result += func(a + i * h)
result *= h
return result
def simpson_rule(func, a, b, n):
h = (b - a) / n
result = func(a) + func(b)
for i in range(1, n):
coef = 3 + (-1)**(i + 1)
result += coef * func(a + i * h)
result *= h / 3
return result
methods = {
"rectangle_left": lambda func, a, b, n: rectangle_rule(func, a, b, n, mode="left"),
"rectangle_right": lambda func, a, b, n: rectangle_rule(func, a, b, n, mode="right"),
"rectangle_middle": rectangle_rule,
"trapezoid": trapezoid_rule,
"simpson": simpson_rule
}
def compute_integral(func, a, b, epsilon, method):
n = 4
runge_coef = {"rectangle_left": 2, "rectangle_right": 2, "rectangle_middle": 2, "trapezoid": 2, "simpson": 15}
coef = runge_coef[method]
result = methods[method](func, a, b, n)
error = math.inf
while error > epsilon:
n *= 2
new_result = methods[method](func, a, b, n)
error = abs(new_result - result) / coef
result = new_result
return result, n
def check_convergence(func, a, b):
if func == f4 and ((a >= -math.inf and b <= 0) or (a >= 0 and b <= math.inf)):
return True
elif func == f5 and ((a >= -math.inf and b <= 0) or (a >= 0 and b <= math.inf)):
return False
elif func == f6 and (a >= 0 and b <= math.inf):
return True
elif func == f1 or func == f2 or func == f3 or func == f7:
return True
else:
return False
def check_discontinuity(func, a, b):
try:
func(a)
func(b)
return False
except (ZeroDivisionError, OverflowError, ValueError):
return True
def compute_integral_modified(func, a, b, epsilon, method):
if check_discontinuity(func, a, b):
print("Интеграл не существует: функция имеет разрыв.")
return None, None
if not check_convergence(func, a, b):
print("Интеграл не существует: интеграл не сходится.")
return None, None
return compute_integral(func, a, b, epsilon, method)
if __name__ == "__main__":
print(color.BOLD + color.RED + "Решатель интегралов. " + color.CYAN + "Барсуков М.А." + color.END)
print("Выберите функцию:")
print("1. x^2")
print("2. sin(x)")
print("3. e^x")
print("4. 1/x^2")
print("5. 1/x")
print("6. 1/sqrt(x)")
print("7. -3x^3 - 5x^2 + 4x - 2")
while True:
try:
print('\n', color.UNDERLINE + color.YELLOW + "Выберите функцию:" + color.END)
print(color.GREEN,
'\t', "1: x^2 - 3", '\n',
'\t', "2: 5/x - 2x", '\n',
'\t', "3: e^(2x) - 2", '\n',
'\t', "4: 2x^3 - 3x^2 + 5x - 9", '\n',
'\t', "5: Выход", color.END)
func = functions[int(input("Ваш выбор: ")) - 1]
choice = int(input("Ввод: ").strip())
a = float(input("Введите начальный предел интегрирования: "))
b = float(input("Введите конечный предел интегрирования: "))
if choice in [1, 2, 3, 4]:
select.Input(choice)
continue
elif choice == 5:
print(color.BOLD + color.PURPLE, 'Спасибо за использование программы!', color.END)
break
else:
print(color.BOLD + color.RED, "Неправильный ввод!", color.END)
continue
print("Выберите метод интегрирования:")
for i, method in enumerate(methods, 1):
print(f"{i}. {method}")
except TypeError:
print(color.BOLD + color.RED, "Неправильный ввод!", color.END)
continue
method = list(methods.keys())[int(input("Ваш выбор: ")) - 1]
epsilon = float(input("Введите требуемую точность вычислений: "))
except ValueError:
continue
result, n = compute_integral_modified(func, a, b, epsilon, method)
if result is not None and n is not None:
print(f"Значение интеграла: {result}")
print(f"Число разбиений интервала интегрирования для достижения требуемой точности: {n}")

View File

@ -1,126 +0,0 @@
import math
import numpy as np
from tabulate import tabulate
import functions
class Rectangles:
type_equation = 0
start = 0
a = 0
b = 0
steps = 0
accuracy = 0
previous_count = 0
n = 4
h = 0
result = [0, 0, 0]
inaccuracy = [0, 0, 0]
xy = []
xy_avg = []
table = []
def __init__(self, a, b, accuracy, type_equation):
self.a = a
self.b = b
self.start = a
self.previous_count = 0
self.result = [0, 0, 0]
self.accuracy = math.pow(10, -1 * accuracy)
self.type_equation = type_equation
def calc(self):
self.table = []
self.xy = []
self.xy_avg = []
self.steps = 0
self.n = self.check_n()
y_left = 0
y_right = 0
y_mid = 0
self.h = (self.b - self.a) / self.n
while self.steps != self.n + 1:
self.xy.append([self.a, functions.function(self.type_equation, self.a)])
if self.steps > 0:
avg_x = (self.previous_count + self.a) / 2
self.xy_avg.append([avg_x, functions.function(self.type_equation, avg_x)])
self.table.append([self.steps, self.xy[self.steps][0], self.xy[self.steps][1],
self.xy_avg[self.steps - 1][0], self.xy_avg[self.steps - 1][1]])
else:
self.table.append([self.steps, self.xy[self.steps][0], self.xy[self.steps][1], "-", "-"])
self.previous_count = self.a
if 0 <= self.steps < self.n:
y_left += self.xy[self.steps][1]
if 0 < self.steps <= self.n:
y_right += self.xy[self.steps][1]
y_mid += self.xy_avg[self.steps - 1][1]
self.a += self.h
self.steps += 1
if self.steps > 25_000:
break
self.result[0] = self.h * y_left
self.result[1] = self.h * y_mid
self.result[2] = self.h * y_right
self.inaccuracy[0] = abs(self.max_value_fun_first() * math.pow(self.b - self.start, 2) / (2 * self.n))
self.inaccuracy[1] = abs(self.max_value_fun_second() * math.pow(self.b - self.start, 3) / (24 * math.pow(self.n, 2)))
self.inaccuracy[2] = abs(self.max_value_fun_first() * math.pow(self.b - self.start, 2) / (2 * self.n))
print('\t', "Метод прямоугольников:")
if self.steps > 25_000:
self.print_result()
print("Число вычислений привысило 25 000 шагов, интеграл вычислен от " + str(self.start)
+ " до " + str(self.xy[-1][0]) + "!")
raise ValueError
else:
self.print_table()
self.print_result()
def check_n(self):
n = abs(math.pow(self.max_value_fun_second() * math.pow(self.b - self.a, 3) / 24 / self.accuracy, 0.5)) // 1
if n % 2 == 1:
n += 1
else:
n += 2
return max(int(n), 4)
def max_value_fun_second(self):
x = np.linspace(self.start, self.b, 100000)
maximum = [abs(functions.second_derivative(self.type_equation, i)) for i in x]
return max(maximum)
def max_value_fun_first(self):
x = np.linspace(self.start, self.b, 100000)
maximum = [abs(functions.first_derivative(self.type_equation, i)) for i in x]
return max(maximum)
def print_table(self):
print(tabulate(self.table, headers=["№ шага", "x", "y", "x(i-0.5)", "y(i-0.5)"], tablefmt="grid", floatfmt="2.5f"))
def print_result(self, n=0):
print("I(left):", self.result[0])
print("I(mid):", self.result[1])
print("I(right):", self.result[2])
if n == 0:
print("R(n) left: ", self.inaccuracy[0])
print("R(n) mid: ", self.inaccuracy[1])
print("R(n) right: ", self.inaccuracy[2])
else:
print("R(" + str(n) + ") left:", self.inaccuracy[0])
print("R(" + str(n) + ") mid:", self.inaccuracy[1])
print("R(" + str(n) + ") right:", self.inaccuracy[2])
print("Число разбиений:", self.n)

View File

@ -1,92 +0,0 @@
import math
import numpy as np
from tabulate import tabulate
import functions
class Simpson:
type_equation = 0
start = 0
a = 0
b = 0
steps = 0
accuracy = 0
n = 4
h = 0
result = 0
inaccuracy = 0
xy = []
table = []
def __init__(self, a, b, accuracy, type_equation):
self.a = a
self.b = b
self.start = a
self.accuracy = math.pow(10, -1 * accuracy)
self.type_equation = type_equation
def calc(self):
self.table = []
self.xy = []
self.steps = 0
self.n = self.check_n()
y_even = 0
y_odd = 0
self.h = (self.b - self.a) / self.n
while self.steps != self.n + 1:
self.xy.append([self.a, functions.function(self.type_equation, self.a)])
self.table.append([self.steps, self.xy[self.steps][0], self.xy[self.steps][1]])
if self.steps % 2 == 1 and 0 < self.steps < self.n:
y_odd += self.xy[self.steps][1]
elif self.steps % 2 == 0 and 1 < self.steps < self.n - 1:
y_even += self.xy[self.steps][1]
self.a += self.h
self.steps += 1
if self.steps > 25_000:
break
self.result = self.h / 3 * (self.xy[0][1] + self.xy[-1][1] + 4 * y_odd + 2 * y_even)
self.inaccuracy = abs(self.max_value_fun() * (math.pow(self.b - self.start, 5) / (180 * math.pow(self.n, 4))))
print('\t', "Метод Симпсона:")
if self.steps > 25_000:
self.print_result()
print("Число вычислений привысило 25 000 шагов, интеграл вычислен от " + str(self.start)
+ " до " + str(self.xy[-1][0]) + "!")
raise ValueError
else:
self.print_table()
self.print_result()
def check_n(self):
n = abs(math.pow(self.max_value_fun() * math.pow(self.b - self.a, 5) / 180 / self.accuracy, 0.25)) // 1
if n % 2 == 1:
n += 1
else:
n += 2
return max(int(n), 4)
def max_value_fun(self):
x = np.linspace(self.start, self.b, 100000)
maximum = [abs(functions.fourth_derivative(self.type_equation, i)) for i in x]
return max(maximum)
def print_table(self):
print(tabulate(self.table, headers=["№ шага", "x", "y"], tablefmt="grid", floatfmt="2.5f"))
def print_result(self, n=0):
print("I:", self.result)
if n == 0:
print("R(n): ", self.inaccuracy)
else:
print("R(" + str(n) + "):", self.inaccuracy)
print("Число разбиений:", self.n)

View File

@ -1,89 +0,0 @@
import math
import numpy as np
from tabulate import tabulate
import functions
class Trapezoid:
type_equation = 0
start = 0
a = 0
b = 0
steps = 0
accuracy = 0
n = 4
h = 0
result = 0
inaccuracy = 0
xy = []
table = []
def __init__(self, a, b, accuracy, type_equation):
self.a = a
self.b = b
self.start = a
self.accuracy = math.pow(10, -1 * accuracy)
self.type_equation = type_equation
def calc(self):
self.table = []
self.xy = []
self.steps = 0
self.n = self.check_n()
y_sum = 0
self.h = (self.b - self.a) / self.n
while self.steps != self.n + 1:
self.xy.append([self.a, functions.function(self.type_equation, self.a)])
self.table.append([self.steps, self.xy[self.steps][0], self.xy[self.steps][1]])
if 0 < self.steps < self.n:
y_sum += self.xy[self.steps][1]
self.a += self.h
self.steps += 1
if self.steps > 25_000:
break
self.result = self.h * ((self.xy[0][1] + self.xy[-1][1]) / 2 + y_sum)
self.inaccuracy = abs(self.max_value_fun() * (math.pow(self.b - self.start, 3) / (12 * math.pow(self.n, 2))))
print('\t', "Метод трапеций:")
if self.steps > 25_000:
self.print_result()
print("Число вычислений привысило 25 000 шагов, интеграл вычислен от " + str(self.start)
+ " до " + str(self.xy[-1][0]) + "!")
raise ValueError
else:
self.print_table()
self.print_result()
def check_n(self):
n = abs(math.pow(self.max_value_fun() * math.pow(self.b - self.a, 3) / 12 / self.accuracy, 0.5)) // 1
if n % 2 == 1:
n += 1
else:
n += 2
return max(int(n), 4)
def max_value_fun(self):
x = np.linspace(self.start, self.b, 100000)
maximum = [abs(functions.second_derivative(self.type_equation, i)) for i in x]
return max(maximum)
def print_table(self):
print(tabulate(self.table, headers=["№ шага", "x", "y"], tablefmt="grid", floatfmt="2.5f"))
def print_result(self, n=0):
print("I:", self.result)
if n == 0:
print("R(n): ", self.inaccuracy)
else:
print("R(" + str(n) + "):", self.inaccuracy)
print("Число разбиений:", self.n)

View File

@ -1,94 +0,0 @@
import colors as color
from methods.rectangles import Rectangles
from methods.trapezoid import Trapezoid
from methods.simpson import Simpson
class Input:
type_equation = 0
type_method = 0
a = 0
b = 0
accuracy = 0
def __init__(self, type_equation):
self.type_equation = type_equation
self.choose_boundaries()
self.choose_accuracy()
self.calculation()
def choose_boundaries(self):
print(color.UNDERLINE + color.YELLOW, "Выбор границы интегрирования.", color.END)
while True:
try:
print(color.BOLD + color.YELLOW, "Формат ввода границ, например: -10 10", color.END)
segment = list(input("Введите границы: ").split())
if len(segment) == 2 and float(segment[0].strip()) < float(segment[1].strip()):
self.a = float(segment[0].strip())
self.b = float(segment[1].strip())
break
else:
get_ready_answer(1)
continue
except TypeError:
get_ready_answer(1)
continue
def choose_accuracy(self):
print(color.UNDERLINE + color.YELLOW, "Выбор точности вычисления.", color.END)
while True:
try:
print(color.BOLD + color.YELLOW, "Введите кол-во знаков после запятой, для вычисления.", color.END)
accuracy = float(input("Количество знаков: ").strip())
if accuracy % 1 != 0 or accuracy <= 0:
get_ready_answer(2)
continue
else:
self.accuracy = accuracy
break
except TypeError:
get_ready_answer(2)
continue
def calculation(self):
while True:
try:
print(color.BOLD + color.YELLOW, "Выберите метод решения:", color.END)
while True:
print('\t', "1. Метод прямоугольников (левые, средние, правые)", '\n',
'\t', "2. Метод трапеций", '\n',
'\t', "3. Метод Симпсона")
self.type_method = int(input("Тип метода (цифра): ").strip())
if self.type_method == 1:
calculator = Rectangles(self.a, self.b, self.accuracy, self.type_equation)
calculator.calc()
break
elif self.type_method == 2:
calculator = Trapezoid(self.a, self.b, self.accuracy, self.type_equation)
calculator.calc()
break
elif self.type_method == 3:
calculator = Simpson(self.a, self.b, self.accuracy, self.type_equation)
calculator.calc()
break
else:
get_ready_answer(3)
continue
del calculator
break
except TypeError:
get_ready_answer(4)
break
except ValueError:
break
def get_ready_answer(type_answer):
answers = {
1: color.BOLD + color.RED + "Неправильный ввод границ!" + color.END,
2: color.BOLD + color.RED + "Неправильный ввод точности!" + color.END,
3: color.BOLD + color.RED + "Неправильный ввод!" + color.END,
4: color.BOLD + color.RED + "Интеграл расходится на выбранном промежутке!" + color.END
}
print(answers.get(type_answer, color.BOLD + color.RED + "Неправильный выбор готового ответа!" + color.END))