Merge pull request 'lab2' (#1) from lab2 into main

Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
2025-05-05 11:42:51 +04:00
15 changed files with 912 additions and 0 deletions

2
lab2/.flake8 Normal file
View File

@@ -0,0 +1,2 @@
[flake8]
max-line-length = 110

View File

@@ -0,0 +1,34 @@
def get_accuracy(x):
x_str = str(x)
acc = 0
if "." in x_str:
acc = len(x_str) - x_str.find(".") - 1
return acc
def get_error(x):
acc = get_accuracy(x)
return 1 / 10**acc / 2
def sum_error(*values):
return sum([get_error(value) for value in values])
def product_error(*values):
p = 1
s = 0
for value in values:
p *= value
s += get_error(value) / abs(value)
return p * s
def frac_error(a, b):
return abs(a / b) * (get_error(a) / abs(a) + get_error(b) / abs(b))
if __name__ == "__main__":
get_error(1)

236
lab2/HookJeeves.py Normal file
View File

@@ -0,0 +1,236 @@
# HookJeeves.py
import numpy as np
import AbsoluteMeasurementErrors as abserror
from itertools import product
result_log = ""
def log(*values, sep=" ", end="\n"):
global result_log
result_log += sep.join(list(map(str, values))) + end
# print(*values, sep=sep, end=end)
def get_errors_vector(x):
return np.array(list(map(abserror.get_error, x)))
def sum_errors_vector(a, b):
return np.array([abserror.sum_error(a[i], b[i]) for i in range(len(a))])
def frac_errors_vector(a, b):
return np.array([abserror.frac_error(a[i], b) for i in range(len(a))])
def point_info(x, f, x_err):
return f"x = {x}, x_err = {x_err}, f(x) = {f(x)}"
def hooke_jeeves(
f,
x0,
delta0,
epsilon,
alpha,
r=lambda x: True,
fit=lambda a, b: a < b,
x_err=None,
delta_err=None,
):
x = np.array(x0)
delta = np.array(delta0)
if x_err is None:
x_err = get_errors_vector(x)
if delta_err is None:
delta_err = get_errors_vector(delta)
iteration = 0
while np.linalg.norm(delta) > epsilon:
iteration += 1
log()
log("=" * 40)
log("Итерация", iteration)
log("Текущая базовая точка", point_info(x, f, x_err))
sample_x, sample_x_err = exploratory_search(
f, x, delta, r=r, fit=fit, x_err=x_err, delta_err=delta_err
)
if fit(f(sample_x), f(x)):
log("Исследующий поиск УДАЧНЫЙ")
x_p, x_p_err = sample_search(
f, x, sample_x, r=r, fit=fit, x1_err=x_err, x2_err=sample_x_err
)
if fit(f(x_p), f(x)):
log("Поиск по образцу УДАЧНЫЙ")
x, x_err = x_p, x_p_err
else:
log("Поиск по образцу ПРОВАЛЕН")
x, x_err = sample_x, sample_x_err
log()
log("Новая базовая точка", point_info(x, f, x_err))
else:
log("Исследующий поиск ПРОВАЛЕН")
log("Уменьшаем шаг", delta, "->", delta / alpha)
delta = delta / alpha
delta_err = frac_errors_vector(delta, alpha)
log("ε =", np.linalg.norm(delta))
return x, f(x), x_err
def exploratory_search(
f, x, delta, r=lambda x: True, fit=lambda a, b: a < b, x_err=None, delta_err=None
):
log()
log("Выполняем исследующий поиск")
if x_err is None:
x_err = get_errors_vector(x)
if delta_err is None:
delta_err = get_errors_vector(delta)
dxs = product(*[[d, -d] for d in delta])
x = np.array(x)
t_x_err = None
t_f = f(x)
t_x = None
for dx in dxs:
if fit(f(x + dx), t_f) and r(x + dx):
t_f = f(x + dx)
t_x = x + dx
t_x_err = x_err + delta_err
if t_x is not None:
log("Найдена точка", t_x, t_f)
return t_x, t_x_err
return x, x_err
def sample_search(
f, x1, x2, r=lambda x: True, fit=lambda a, b: a < b, x1_err=None, x2_err=None
):
log()
log("Выполняем поиск по образцу")
if x1_err is None:
x1_err = get_errors_vector(x1)
if x2_err is None:
x2_err = get_errors_vector(x2)
x2_last = x2.copy()
x2_last_err = x2_err.copy()
error_growth_coeff = 0.05 # КОЭФФИЦИЕНТ РОСТА ОШИБКИ
while fit(f(x2), f(x1)):
x2_last = x2.copy()
x2_last_err = x2_err.copy()
step = x2 - x1
if not r(x2 + step):
log("Ограничение ОДЗ")
break
x2, x1 = x2 + step, x2
# Новая погрешность
step_error = error_growth_coeff * np.abs(step)
x2_err = x2_err + step_error
x1_err = x2_err.copy()
log("Найдена точка", x2_last, f(x2_last))
return x2_last, x2_last_err
class TARGET:
MIN = 0
MAX = 1
def example():
# начальная базовая точка
x0 = [100, 100]
# начальное значение приращения
delta0 = [10, 10]
# коэффициент приращения
alpha = 2
# условие окончания поиска
epsilon = 0.0001
# коэффициенты при неизвестных (внутри списков порядок обратный)
c = [[1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1]]
x1r = [-10000, 10000]
x2r = [-10000, 10000]
target = TARGET.MIN
def fit(a, b):
"""
Функция сравнения значений оптимизируемой функции
> - ищем максимум
< - ищем минимум
"""
if target == TARGET.MIN:
return a < b
elif target == TARGET.MAX:
return a > b
def r(x):
"""
Функция, описывающая область допустимых значений.
Должна возвращать истину, если точка находится в ОДЗ.
"""
return x1r[0] <= x[0] <= x1r[1] and x2r[0] <= x[1] <= x2r[1]
def f(x):
"""
Функция, которую мы должны оптимизировать
"""
return sum(
[
sum([c[i][j] * x[i] ** j for j in range(len(c[i]))])
for i in range(len(c))
]
)
x, val, x_err = hooke_jeeves(f, x0, delta0, epsilon, alpha, r=r, fit=fit)
log()
log("=" * 40)
log("Точка экстремумв:", x)
log("Абсолютная погрешность:", x_err)
log("Максимальное значение функции:", val)
with open("result.log", "w", encoding="utf-8") as file:
file.write(result_log)
def main():
example()
if __name__ == "__main__":
main()

94
lab2/README.md Normal file
View File

@@ -0,0 +1,94 @@
# Лабораторная работа по вычислительной математике "Нелинейное программирование"
## Запуск
Склонировать проект и перейти в директорию проекта
> Для запуска проекта используется менеджер пакетов [poetry](https://python-poetry.org/docs/#installation)
```shell
git clone ... project
cd project
poetry install
poetry run flask run
```
После запуска перейти по ссылке <http://127.0.0.1:5000>
![Главная страница с формой ввода данных](docs/mainform.png)
![Вывод результатов](docs/results.png)
Пример файла `example.json` с исходными данными
```json
{
"x0": [
100,
100
],
"delta0": [
10,
10
],
"epsilon": 0.0001,
"alpha": 2,
"target": "min",
"x1r": [
-10000,
10000
],
"x2r": [
-10000,
10000
],
"x1c": [
1,
1,
1,
1,
1,
1,
1
],
"x2c": [
1,
1,
1,
1,
1,
1,
1
]
}
```
## Организация работы
1. Лабораторная работа выполняется индивидуально.
2. Лабораторная работа состоит из двух частей, основная часть и дополнительные задания в зависимости от качества выполнения работы.
3. Выбрать можно любой из предложенных вариантов, которые отличаются уровнем сложности и, как следствием, максимальным числом баллов, которое можно получить за выполнение.
4. Оценивается результат выполнения, а не качество написанного кода. Допускается реализация на любом языке программирования или среде разработки позволяющей решить задачу (1С, Excel, MatLAB, Maple и тд). Например, можно использовать макросы в Excel, но нельзя использовать готовый плагин для решения задач.
5. Допускается использование математических библиотек и пакетов реализующих вспомогательные функции, такие как операции с векторами и матрицами, вычисление градиента и Гессиана, основные математические функции. Использование готовых методов оптимизации не допускается.
## Общее задание
1. Необходимо составить программную реализацию одного из изученных методов оптимизации полиномиальной функции с оценкой абсолютной погрешности работы данного метода.
2. Программа должна позволять ввести произвольные значения в заранее подготовленный файл, с клавиатуры или другим общепринятым способом. Генерация случайных данных не допускается.
3. Количество ненулевых коэффициентов в проверочных примерах должно быть не менее 10.
4. Результатом работы программы должны быть:
- Значения неизвестных (массив X) для минимума и максимума функции на заданном отрезке.
- Результаты подстановки неизвестных целевую функцию
- Оценки абсолютных погрешностей для найденных значений
- Поощряется вывод промежуточных вычислений и графиков функции.
5. Полученные абсолютные погрешности вычислений должны быть допустимыми, то есть не превышать половины единицы измерения искомых величин (не превышать 5%).
## Пояснения по расчету погрешностей
1. Для расчета погрешностей необходимо использовать формулы из соответствующей лекции со слайдов 7 и 8. Так как все алгоритмы подразумевают только выполнения базовых математических операций, то формулы со слайда 9, вам скорее всего не пригодятся.
2. Погрешности исходных данных считаются по умолчанию и равны половине последнего введенного знака. То есть для числа 48 абсолютная погрешность равна 0.5, а для числа 48.01 абсолютная погрешность равна 0.005. Отдельно вводить погрешности для входных данных не требуется. Таким образом для достижения требуемого результата значения на входе должны иметь достаточно малые абсолютные погрешности.
3. Для косвенной само-проверки расчета погрешностей разумно подсчитывать общее количество операций сложения, вычитания, умножения и деления. Это позволит понять где идет наибольшее накопление погрешностей и исправить ошибку.
## Вариант задания
![Вариант задания](docs/zadanie.png)

114
lab2/app.py Normal file
View File

@@ -0,0 +1,114 @@
from flask import Flask, render_template, request
import HookJeeves
import os
import json
app = Flask(__name__)
app.config["UPLOAD_FOLDER"] = "uploads/"
os.makedirs(app.config["UPLOAD_FOLDER"], exist_ok=True)
def parse_uploaded_data(file):
data = json.load(file)
return data
def to_str(arr):
return ",".join(list(map(str, arr)))
def to_normal_numb(numb):
str_numb = str(numb)
index_point = str_numb.find(".")
end_num = ""
if index_point == -1:
index_point = len(str_numb)
else:
end_num = str_numb[index_point:]
normal_numb = ""
count = 0
for i in range(index_point - 1, -1, -1):
normal_numb = str_numb[i] + normal_numb
count += 1
if count % 3 == 0:
normal_numb = " " + normal_numb
return normal_numb + end_num
@app.route("/", methods=["GET", "POST"])
def index():
if request.method == "POST":
if "datafile" in request.files and request.files["datafile"].filename != "":
file = request.files["datafile"]
data = parse_uploaded_data(file)
else:
try:
data = {
"x0": list(map(float, request.form["x0"].split(","))),
"delta0": list(map(float, request.form["delta0"].split(","))),
"epsilon": float(request.form["epsilon"]),
"alpha": float(request.form["alpha"]),
"target": request.form["target"],
"x1c": list(map(float, request.form["x1c"].split(","))),
"x2c": list(map(float, request.form["x2c"].split(","))),
"x1r": list(map(float, request.form["x1r"].split(","))),
"x2r": list(map(float, request.form["x2r"].split(","))),
}
except (KeyError, ValueError, json.JSONDecodeError):
return render_template(
"index.html",
error="Ошибка в данных формы. Заполните все поля корректно.",
)
# Инициализация функций
c = [data["x1c"][::-1], data["x2c"][::-1]]
x1r = data["x1r"]
x2r = data["x2r"]
target = data["target"]
def f(x):
return sum(
[
sum([c[i][j] * x[i] ** j for j in range(len(c[i]))])
for i in range(len(c))
]
)
def fit(a, b):
return a < b if target == "min" else a > b
def r(x):
return x1r[0] <= x[0] <= x1r[1] and x2r[0] <= x[1] <= x2r[1]
# Запуск метода
x, val, x_err = HookJeeves.hooke_jeeves(
f, data["x0"], data["delta0"], data["epsilon"], data["alpha"], r=r, fit=fit
)
return render_template(
"index.html",
result=True,
log=HookJeeves.result_log,
extreme={
"x": x,
"val": to_normal_numb(val),
"x_err": x_err,
"type": target,
},
form_data={
"x0": to_str(data["x0"]),
"delta0": to_str(data["delta0"]),
"epsilon": str(data["epsilon"]),
"alpha": str(data["alpha"]),
"target": data["target"],
"x1c": to_str(data["x1c"]),
"x2c": to_str(data["x2c"]),
"x1r": to_str(data["x1r"]),
"x2r": to_str(data["x2r"]),
},
)
return render_template("index.html")

BIN
lab2/docs/mainform.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

BIN
lab2/docs/results.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

BIN
lab2/docs/zadanie.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

39
lab2/example.json Normal file
View File

@@ -0,0 +1,39 @@
{
"x0": [
100,
100
],
"delta0": [
10,
10
],
"epsilon": 0.0001,
"alpha": 2,
"target": "min",
"x1r": [
-10000,
10000
],
"x2r": [
-10000,
10000
],
"x1c": [
1,
1,
1,
1,
1,
1,
1
],
"x2c": [
1,
1,
1,
1,
1,
1,
1
]
}

9
lab2/main.py Normal file
View File

@@ -0,0 +1,9 @@
import HookJeeves
def main():
HookJeeves.main()
if __name__ == "__main__":
main()

253
lab2/poetry.lock generated Normal file
View File

@@ -0,0 +1,253 @@
# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand.
[[package]]
name = "blinker"
version = "1.9.0"
description = "Fast, simple object-to-object and broadcast signaling"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc"},
{file = "blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf"},
]
[[package]]
name = "click"
version = "8.1.8"
description = "Composable command line interface toolkit"
optional = false
python-versions = ">=3.7"
groups = ["main"]
files = [
{file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"},
{file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"},
]
[package.dependencies]
colorama = {version = "*", markers = "platform_system == \"Windows\""}
[[package]]
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
groups = ["main"]
markers = "platform_system == \"Windows\""
files = [
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
]
[[package]]
name = "flask"
version = "3.1.0"
description = "A simple framework for building complex web applications."
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "flask-3.1.0-py3-none-any.whl", hash = "sha256:d667207822eb83f1c4b50949b1623c8fc8d51f2341d65f72e1a1815397551136"},
{file = "flask-3.1.0.tar.gz", hash = "sha256:5f873c5184c897c8d9d1b05df1e3d01b14910ce69607a117bd3277098a5836ac"},
]
[package.dependencies]
blinker = ">=1.9"
click = ">=8.1.3"
itsdangerous = ">=2.2"
Jinja2 = ">=3.1.2"
Werkzeug = ">=3.1"
[package.extras]
async = ["asgiref (>=3.2)"]
dotenv = ["python-dotenv"]
[[package]]
name = "itsdangerous"
version = "2.2.0"
description = "Safely pass data to untrusted environments and back."
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef"},
{file = "itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"},
]
[[package]]
name = "jinja2"
version = "3.1.6"
description = "A very fast and expressive template engine."
optional = false
python-versions = ">=3.7"
groups = ["main"]
files = [
{file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"},
{file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"},
]
[package.dependencies]
MarkupSafe = ">=2.0"
[package.extras]
i18n = ["Babel (>=2.7)"]
[[package]]
name = "markupsafe"
version = "3.0.2"
description = "Safely add untrusted strings to HTML/XML markup."
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"},
{file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"},
{file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"},
{file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"},
{file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"},
{file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"},
{file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"},
{file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"},
{file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"},
{file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"},
{file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"},
{file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"},
{file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"},
{file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"},
{file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"},
{file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"},
{file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"},
{file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"},
{file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"},
{file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"},
{file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"},
{file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"},
{file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"},
{file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"},
{file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"},
{file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"},
{file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"},
{file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"},
{file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"},
{file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"},
{file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"},
{file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"},
{file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"},
{file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"},
{file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"},
{file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"},
{file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"},
{file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"},
{file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"},
{file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"},
{file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"},
{file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"},
{file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"},
{file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"},
{file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"},
{file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"},
{file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"},
{file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"},
{file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"},
{file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"},
{file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"},
{file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"},
]
[[package]]
name = "numpy"
version = "2.2.5"
description = "Fundamental package for array computing in Python"
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
{file = "numpy-2.2.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f4a922da1729f4c40932b2af4fe84909c7a6e167e6e99f71838ce3a29f3fe26"},
{file = "numpy-2.2.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b6f91524d31b34f4a5fee24f5bc16dcd1491b668798b6d85585d836c1e633a6a"},
{file = "numpy-2.2.5-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:19f4718c9012e3baea91a7dba661dcab2451cda2550678dc30d53acb91a7290f"},
{file = "numpy-2.2.5-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:eb7fd5b184e5d277afa9ec0ad5e4eb562ecff541e7f60e69ee69c8d59e9aeaba"},
{file = "numpy-2.2.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6413d48a9be53e183eb06495d8e3b006ef8f87c324af68241bbe7a39e8ff54c3"},
{file = "numpy-2.2.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7451f92eddf8503c9b8aa4fe6aa7e87fd51a29c2cfc5f7dbd72efde6c65acf57"},
{file = "numpy-2.2.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0bcb1d057b7571334139129b7f941588f69ce7c4ed15a9d6162b2ea54ded700c"},
{file = "numpy-2.2.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:36ab5b23915887543441efd0417e6a3baa08634308894316f446027611b53bf1"},
{file = "numpy-2.2.5-cp310-cp310-win32.whl", hash = "sha256:422cc684f17bc963da5f59a31530b3936f57c95a29743056ef7a7903a5dbdf88"},
{file = "numpy-2.2.5-cp310-cp310-win_amd64.whl", hash = "sha256:e4f0b035d9d0ed519c813ee23e0a733db81ec37d2e9503afbb6e54ccfdee0fa7"},
{file = "numpy-2.2.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c42365005c7a6c42436a54d28c43fe0e01ca11eb2ac3cefe796c25a5f98e5e9b"},
{file = "numpy-2.2.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:498815b96f67dc347e03b719ef49c772589fb74b8ee9ea2c37feae915ad6ebda"},
{file = "numpy-2.2.5-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:6411f744f7f20081b1b4e7112e0f4c9c5b08f94b9f086e6f0adf3645f85d3a4d"},
{file = "numpy-2.2.5-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:9de6832228f617c9ef45d948ec1cd8949c482238d68b2477e6f642c33a7b0a54"},
{file = "numpy-2.2.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:369e0d4647c17c9363244f3468f2227d557a74b6781cb62ce57cf3ef5cc7c610"},
{file = "numpy-2.2.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:262d23f383170f99cd9191a7c85b9a50970fe9069b2f8ab5d786eca8a675d60b"},
{file = "numpy-2.2.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:aa70fdbdc3b169d69e8c59e65c07a1c9351ceb438e627f0fdcd471015cd956be"},
{file = "numpy-2.2.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37e32e985f03c06206582a7323ef926b4e78bdaa6915095ef08070471865b906"},
{file = "numpy-2.2.5-cp311-cp311-win32.whl", hash = "sha256:f5045039100ed58fa817a6227a356240ea1b9a1bc141018864c306c1a16d4175"},
{file = "numpy-2.2.5-cp311-cp311-win_amd64.whl", hash = "sha256:b13f04968b46ad705f7c8a80122a42ae8f620536ea38cf4bdd374302926424dd"},
{file = "numpy-2.2.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ee461a4eaab4f165b68780a6a1af95fb23a29932be7569b9fab666c407969051"},
{file = "numpy-2.2.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ec31367fd6a255dc8de4772bd1658c3e926d8e860a0b6e922b615e532d320ddc"},
{file = "numpy-2.2.5-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:47834cde750d3c9f4e52c6ca28a7361859fcaf52695c7dc3cc1a720b8922683e"},
{file = "numpy-2.2.5-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:2c1a1c6ccce4022383583a6ded7bbcda22fc635eb4eb1e0a053336425ed36dfa"},
{file = "numpy-2.2.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d75f338f5f79ee23548b03d801d28a505198297534f62416391857ea0479571"},
{file = "numpy-2.2.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a801fef99668f309b88640e28d261991bfad9617c27beda4a3aec4f217ea073"},
{file = "numpy-2.2.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:abe38cd8381245a7f49967a6010e77dbf3680bd3627c0fe4362dd693b404c7f8"},
{file = "numpy-2.2.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5a0ac90e46fdb5649ab6369d1ab6104bfe5854ab19b645bf5cda0127a13034ae"},
{file = "numpy-2.2.5-cp312-cp312-win32.whl", hash = "sha256:0cd48122a6b7eab8f06404805b1bd5856200e3ed6f8a1b9a194f9d9054631beb"},
{file = "numpy-2.2.5-cp312-cp312-win_amd64.whl", hash = "sha256:ced69262a8278547e63409b2653b372bf4baff0870c57efa76c5703fd6543282"},
{file = "numpy-2.2.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:059b51b658f4414fff78c6d7b1b4e18283ab5fa56d270ff212d5ba0c561846f4"},
{file = "numpy-2.2.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:47f9ed103af0bc63182609044b0490747e03bd20a67e391192dde119bf43d52f"},
{file = "numpy-2.2.5-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:261a1ef047751bb02f29dfe337230b5882b54521ca121fc7f62668133cb119c9"},
{file = "numpy-2.2.5-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:4520caa3807c1ceb005d125a75e715567806fed67e315cea619d5ec6e75a4191"},
{file = "numpy-2.2.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d14b17b9be5f9c9301f43d2e2a4886a33b53f4e6fdf9ca2f4cc60aeeee76372"},
{file = "numpy-2.2.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ba321813a00e508d5421104464510cc962a6f791aa2fca1c97b1e65027da80d"},
{file = "numpy-2.2.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4cbdef3ddf777423060c6f81b5694bad2dc9675f110c4b2a60dc0181543fac7"},
{file = "numpy-2.2.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:54088a5a147ab71a8e7fdfd8c3601972751ded0739c6b696ad9cb0343e21ab73"},
{file = "numpy-2.2.5-cp313-cp313-win32.whl", hash = "sha256:c8b82a55ef86a2d8e81b63da85e55f5537d2157165be1cb2ce7cfa57b6aef38b"},
{file = "numpy-2.2.5-cp313-cp313-win_amd64.whl", hash = "sha256:d8882a829fd779f0f43998e931c466802a77ca1ee0fe25a3abe50278616b1471"},
{file = "numpy-2.2.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:e8b025c351b9f0e8b5436cf28a07fa4ac0204d67b38f01433ac7f9b870fa38c6"},
{file = "numpy-2.2.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8dfa94b6a4374e7851bbb6f35e6ded2120b752b063e6acdd3157e4d2bb922eba"},
{file = "numpy-2.2.5-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:97c8425d4e26437e65e1d189d22dff4a079b747ff9c2788057bfb8114ce1e133"},
{file = "numpy-2.2.5-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:352d330048c055ea6db701130abc48a21bec690a8d38f8284e00fab256dc1376"},
{file = "numpy-2.2.5-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b4c0773b6ada798f51f0f8e30c054d32304ccc6e9c5d93d46cb26f3d385ab19"},
{file = "numpy-2.2.5-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55f09e00d4dccd76b179c0f18a44f041e5332fd0e022886ba1c0bbf3ea4a18d0"},
{file = "numpy-2.2.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:02f226baeefa68f7d579e213d0f3493496397d8f1cff5e2b222af274c86a552a"},
{file = "numpy-2.2.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c26843fd58f65da9491165072da2cccc372530681de481ef670dcc8e27cfb066"},
{file = "numpy-2.2.5-cp313-cp313t-win32.whl", hash = "sha256:1a161c2c79ab30fe4501d5a2bbfe8b162490757cf90b7f05be8b80bc02f7bb8e"},
{file = "numpy-2.2.5-cp313-cp313t-win_amd64.whl", hash = "sha256:d403c84991b5ad291d3809bace5e85f4bbf44a04bdc9a88ed2bb1807b3360bb8"},
{file = "numpy-2.2.5-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b4ea7e1cff6784e58fe281ce7e7f05036b3e1c89c6f922a6bfbc0a7e8768adbe"},
{file = "numpy-2.2.5-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:d7543263084a85fbc09c704b515395398d31d6395518446237eac219eab9e55e"},
{file = "numpy-2.2.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0255732338c4fdd00996c0421884ea8a3651eea555c3a56b84892b66f696eb70"},
{file = "numpy-2.2.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d2e3bdadaba0e040d1e7ab39db73e0afe2c74ae277f5614dad53eadbecbbb169"},
{file = "numpy-2.2.5.tar.gz", hash = "sha256:a9c0d994680cd991b1cb772e8b297340085466a6fe964bc9d4e80f5e2f43c291"},
]
[[package]]
name = "werkzeug"
version = "3.1.3"
description = "The comprehensive WSGI web application library."
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e"},
{file = "werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746"},
]
[package.dependencies]
MarkupSafe = ">=2.1.1"
[package.extras]
watchdog = ["watchdog (>=2.3)"]
[metadata]
lock-version = "2.1"
python-versions = ">=3.13"
content-hash = "e79fa5194de439ac19f30a7b4183d2c032849069c480531d402389348b2a8162"

21
lab2/pyproject.toml Normal file
View File

@@ -0,0 +1,21 @@
[project]
name = "lab2"
version = "0.1.0"
description = ""
authors = [
{name = "Никита Потапов",email = "ns.potapov@yandex.ru"}
]
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"numpy (>=2.2.5,<3.0.0)",
"flask (>=3.1.0,<4.0.0)"
]
[tool.poetry]
package-mode = false
[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"

1
lab2/requirements.txt Normal file
View File

@@ -0,0 +1 @@
numpy==2.2.5

0
lab2/static/style.css Normal file
View File

109
lab2/templates/index.html Normal file
View File

@@ -0,0 +1,109 @@
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Метод Хука-Дживса</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="bg-light">
<div class="container mt-5">
<h1 class="mb-4">Метод Хука-Дживса</h1>
{% if error %}
<div class="alert alert-danger">{{ error }}</div>
{% endif %}
<form method="post" enctype="multipart/form-data" class="mb-4">
<div class="row g-3">
<div class="col-md-6">
<label class="form-label">Координаты начальной базовой точки x0</label>
<input type="text" name="x0" class="form-control" placeholder="100,100"
value='{{form_data["x0"] if form_data else ""}}'>
</div>
<div class="col-md-6">
<label class="form-label">Начальные приращения &Delta;x</label>
<input type="text" name="delta0" class="form-control" placeholder="100,100"
value='{{form_data["delta0"] if form_data else ""}}'>
</div>
<div class="col-md-4">
<label class="form-label">Требуемая точность &epsilon;</label>
<input type="text" name="epsilon" class="form-control" placeholder="0.0001"
value='{{form_data["epsilon"] if form_data else ""}}'>
</div>
<div class="col-md-4">
<label class="form-label">Коэффициент &alpha;</label>
<input type="text" name="alpha" class="form-control" placeholder="2"
value='{{form_data["alpha"] if form_data else ""}}'>
</div>
<div class="col-md-4">
<label class="form-label">Цель:</label>
<select name="target" class="form-select">
{% for k, v in {"min": "Минимум", "max": "Максимум"}.items() %}
{% if form_data and form_data["target"] == k %}
<option selected value="{{k}}">{{v}}</option>
{% else %}
<option value="{{k}}">{{v}}</option>
{% endif %}
{% endfor %}
</select>
</div>
<div class="col-md-6">
<label class="form-label">Ограничения x1:</label>
<input type="text" name="x1r" class="form-control" placeholder="-1000,100000"
value='{{form_data["x1r"] if form_data else ""}}'>
</div>
<div class="col-md-6">
<label class="form-label">Ограничения x2:</label>
<input type="text" name="x2r" class="form-control" placeholder="-1000,100000"
value='{{form_data["x2r"] if form_data else ""}}'>
</div>
<div class="col-12">
<label class="form-label">Коэффициенты при x1 (через запятую)</label>
<textarea name="x1c" class="form-control" rows="3"
placeholder='1,1,1,1,1,1,1'>{{form_data["x1c"] if form_data else ""}}</textarea>
</div>
<div class="col-12">
<label class="form-label">Коэффициенты при x2 (через запятую)</label>
<textarea name="x2c" class="form-control" rows="3"
placeholder='1,1,1,1,1,1,1'>{{form_data["x2c"] if form_data else ""}}</textarea>
</div>
<div class="col-12">
<label class="form-label">ИЛИ загрузите JSON-файл с данными:</label>
<input type="file" name="datafile" class="form-control">
</div>
<div class="col-12 mt-3">
<button type="submit" class="btn btn-primary">Рассчитать</button>
</div>
</div>
</form>
{% if result %}
<h4>Найденный экстремум ({{extreme.type}}):</h4>
<ul>
<li><strong>x:</strong> {{ extreme.x }}</li>
<li><strong>f(x):</strong> {{ extreme.val }}</li>
<li><strong>Погрешности:</strong> {{ extreme.x_err }}</li>
</ul>
<hr>
<h2>Промежуточные вычисления</h2>
<pre class="bg-white p-3 border">{{ log }}</pre>
<h4>Найденный экстремум ({{extreme.type}}):</h4>
<ul>
<li><strong>x:</strong> {{ extreme.x }}</li>
<li><strong>f(x):</strong> {{ extreme.val }}</li>
<li><strong>Погрешности:</strong> {{ extreme.x_err }}</li>
</ul>
{% endif %}
</div>
</body>
</html>