Files
MMPS_DZ_1/scripts/optimize.py
T
2026-09-21 17:30:30 +03:00

112 lines
2.6 KiB
Python

import numpy as np
from scipy.optimize import least_squares
REFERENCE_K1 = 0.577
REFERENCE_K2 = 0.422
TIMES = np.linspace(0.0, 10.0, 101)
SUBSTEPS = 10
def analytical(t, k1, k2):
x1 = np.exp(-k1 * t)
if k1 == k2:
x2 = k1 * t * np.exp(-k1 * t)
else:
x2 = k1 / (k2 - k1) * (
np.exp(-k1 * t) - np.exp(-k2 * t)
)
x3 = 1.0 - x1 - x2
return np.column_stack((x1, x2, x3))
def solve_rk4(k1, k2):
def rhs(x):
x1, x2, x3 = x
return np.array([
-k1 * x1,
k1 * x1 - k2 * x2,
k2 * x2,
])
state = np.array([1.0, 0.0, 0.0])
solution = np.empty((len(TIMES), 3))
solution[0] = state
for j in range(1, len(TIMES)):
h = (TIMES[j] - TIMES[j - 1]) / SUBSTEPS
for _ in range(SUBSTEPS):
q1 = rhs(state)
q2 = rhs(state + h * q1 / 2.0)
q3 = rhs(state + h * q2 / 2.0)
q4 = rhs(state + h * q3)
state = state + h / 6.0 * (
q1 + 2.0 * q2 + 2.0 * q3 + q4
)
solution[j] = state
return solution
def residuals(parameters, reference):
k1, k2 = parameters
calculated = solve_rk4(k1, k2)
return (calculated - reference).ravel()
def main():
reference = analytical(TIMES, REFERENCE_K1, REFERENCE_K2)
result = least_squares(
fun=residuals,
x0=[0.3, 0.7],
args=(reference,),
bounds=(
[1e-5, 0.01],
[100.0, 1.0],
),
method="trf",
max_nfev=200,
verbose=1,
)
k1_found, k2_found = result.x
absolute_error_k1 = abs(k1_found - REFERENCE_K1)
absolute_error_k2 = abs(k2_found - REFERENCE_K2)
relative_error_k1 = absolute_error_k1 / REFERENCE_K1 * 100
relative_error_k2 = absolute_error_k2 / REFERENCE_K2 * 100
sum_squared_errors = np.sum(result.fun ** 2)
rmse = np.sqrt(np.mean(result.fun ** 2))
print(f"\nk1 = {k1_found:.4f}")
print(f"k2 = {k2_found:.4f}")
print(f"\nАбсолютное отклонение k1: {absolute_error_k1:.6e}")
print(f"Абсолютное отклонение k2: {absolute_error_k2:.6e}")
print(f"\nОтносительное отклонение k1: {relative_error_k1:.6e}%")
print(f"Относительное отклонение k2: {relative_error_k2:.6e}%")
print(f"\nСумма квадратов отклонений: {sum_squared_errors:.6e}")
print(f"RMSE: {rmse:.6e}")
if not result.success:
print("\nПоиск завершён без подтверждённой сходимости.")
if __name__ == "__main__":
main()