Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion conditions/sem02/lesson04/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
Теперь мы готовы реализовывать фильтр размытия. Размытие изображения работает достаточно просто:

- Сначала задается размер окна размытия - $l_w$, которое можно интерпретировать, как степень размытия. Чем больше окно размытия, тем сильнее результирующая картинка будет размыта. Обычно в качестве размеров окна размытия используются нечетные целые числа.
- Следующий шаг - это применение паддинга к входному изображению размеров $ N \times M $, причем ширина паддинга соответствует следующему выражению: $\lfloor\frac{l_w}{2}\rfloor$.
- Следующий шаг - это применение паддинга к входному изображению размеров $N \times M$, причем ширина паддинга соответствует следующему выражению: $\lfloor\frac{l_w}{2}\rfloor$.
- Затем, по всему изображению с паддингом запускается обход скользящим окном размеров $l_w \times l_w$, причем центр окна всегда находится в пикселях, соответствующих пикселям исходного изображения. Т.е. центр окна размытия проходит пиксели из области $[l_w, l_w + N] \times [l_w, l_w + M]$
- В каждом положении окна размытия вычисляется среднее значений пикселей, попавших в окно. Результат записывается в новый массив, тех же размеров, что и исходное изображение.

Expand Down
80 changes: 80 additions & 0 deletions conditions/sem02/lesson05/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
## Задача 1. Оптимальное распределение ресурсов

Некоторая компания производит $N$ типов товаров, используя $M$ типов ресурсов. Для учета производственных стоимостей в компании заведена таблица `costs`, которая представляет собой матрицу размеров $M \times N$. Элемент данной матрицы `costs[i][j]` показывает, сколько единиц i-ого ресурса требуется для производства одной единицы j-ого товара. Для учета доступных ресурсов в компании также определен одномерный массив `resource_amounts`, длины $M$. i-ый элемент массива `resource_amounts` соответствует количеству i-ого ресурса, доступного для использования в производстве.

Каждый месяц аналитики компании, на основании данных анализа рынка, озвучивают ожидаемый спрос на производимые товары. Ожидаемый спрос характеризуется одномерным массивом `demand_expected`, состоящим из $N$ элементов. i-ому элементу массива `demand_expected` соответствует число товаров, которое необходимо произвести для удовлетворения ожидаемого спроса.

Ваша задача - разработать функцию, которая позволяет определить, сможет ли компания удовлетворить ожидаемый спрос, учитывая текущее количество ресурсов и текущие производственные стоимости, или нет.

Допишите код функции `can_satisfy_demand` в файле [task1](../../../solutions/sem02/lesson05/task1.py).

**Входные данные**:
- `costs` - двумерный массив чисел с плавающей точкой - количества ресурсов, требуемых для производства товаров (размерность $M \times N$);
- `resource_amounts` - одномерный массив чисел с плавающей точкой - доступное количество ресурсов (длина $M$);
- `demand_expected` - одномерный массив целых чисел - необходимое число товаров для удовлетворения ожидаемого спроса (длина $N$);

**Выходные данные**:
- Булево значение: `True`, если компания сможет удовлетворить ожидаемый спрос, иначе - `False`.

*Сторонние эффекты*:
- Если размеры входных массивов не согласованы, необходимо возбудить исключение `ShapeMismatchError`.

## Задача 2. Без базиса не выйдет

Дана квадратная матрица $A$. В строках матрицы $A$ записаны векторы N-мерного пространства. Также дан вектор $\vec{a}$. Ваша задача - реализовать функцию, которая бы выполняла следующие вычисления:
- проверяла, являются ли вектора матрицы $A$ базисом в N-мерном пространстве;
- вычисляла бы ортогональные проекции $\vec{a}$ на базисные вектора, а также вычисляла бы ортогональные составляющие каждой проекции, если матрица $A$ задает базис.

Допишите код функции `get_projections_components` в файле [task2](../../../solutions/sem02/lesson05/task2.py).

**Входные данные**:
- `matrix` - двумерный массив `np.ndarray` - описание потенциального базиса;
- `vector` - одномерный массив `np.ndarray` - вектор, проекции которого необходимо вычислить;

**Выходные данные**:
- Кортеж (`tuple`) двумерных массивов. Первый элемент кортежа - ортогональные проекции вектора на базис, второй элемент - ортогональные составляющие проекций вектора на базис. В случае, если входная матрица не задает базис, элементы кортежа - `None`.

*Сторонние эффекты*:
- Если матрица $A$ не является квадратной, необходимо возбудить исключение `ShapeMismatchError`;
- Если количество столбцов матрицы $A$ отлично от количества элементов входного вектора, необходимо возбудить исключение `ShapeMismatchError`.

*Замечания*:
- Гарантируется, что `vector` - не нулевой вектор.

## Задача 3. Адаптивная фильтрация

Фильтрация нужна для того, чтобы отделить полезный сигнал от шума или помех. Адаптивная фильтрация — это более умный способ фильтрации, который используется, когда шум или сигнал меняются со временем. Адаптивный фильтр сам подстраивается под изменения, чтобы всегда эффективно убирать шум или выделять нужный сигнал.

В данной задаче рассматривается формула адаптивной фильтрации, которая основана на использовании корреляционной матрицы и обучающей выборки для настройки фильтра. Формула имеет вид:

$$ y = R^{-1} V_s $$

где:
- $y$ — выходной сигнал после фильтрации (матрица размером $M \times N$)
- $R^{-1}$ — обратная корреляционная матрица (матрица размером $M \times M$)
- $V_s$ — обрабатываемая выборка сигнала (матрица размером $M \times N$)

Обратная корреляционная матрица $R^{-1}$ вычисляется следующим образом:

$$ R^{-1} = (I + V_j A V_j^H)^{-1} = I - V_j (I + V_j^H V_j A)^{-1} V_j^H $$

где:
- $I$ — единичная матрица
- $V_j$ — обучающая выборка (матрица комплексных чисел размером $M \times K$)
- $A$ — диагональная матрица комплексных чисел (размером $K \times K$), которая определяет мощность подавления
- $V_j^H$ — матрица, которая получается поэлементным сопряжением матрицы $V_j$ и транспонированием результата (эрмитово сопряженная матрица)

Напишите функцию, которая вычисляет выходной сигнал $y$ по формуле адаптивной фильтрации, используя предоставленные матрицы $V_s$, $V_j$ и $A$.

Допишите код функции `adaptive_filter` в файле [task3](../../../solutions/sem02/lesson05/task3.py).

**Входные данные**:
- `Vs` — матрица обрабатываемой выборки сигнала (тип: `numpy.ndarray`, размерность: $M \times N$)
- `Vj` — матрица обучающей выборки (тип: `numpy.ndarray`, размерность: $M \times K$)
- `diag_A` — диагональ матрицы A (тип: `numpy.ndarray`, размерность: $K$)

**Выходные данные**:
- `y` — выходной сигнал после фильтрации (тип: `numpy.ndarray`, размерность: $M \times N$)

*Сторонние эффекты*:
- Если размеры входных массивов не согласованы, необходимо возбудить исключение `ShapeMismatchError`.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from solutions.sem02.lesson04.task1 import blur_image, pad_image
from solutions.sem02.lesson04.task2 import get_dominant_color_info

DATA_PATH = os.path.join("tests", "test_data", "lesson04")
DATA_PATH = os.path.join("test_data", "lesson04")


class TestTask1:
Expand Down Expand Up @@ -44,7 +44,10 @@ class TestTask1:
pytest.param(
np.array([[1, 2], [3, 4]], dtype=np.uint8),
1,
np.array([[0, 0, 0, 0], [0, 1, 2, 0], [0, 3, 4, 0], [0, 0, 0, 0]], dtype=np.uint8),
np.array(
[[0, 0, 0, 0], [0, 1, 2, 0], [0, 3, 4, 0], [0, 0, 0, 0]],
dtype=np.uint8,
),
id="2d_pad_1",
),
pytest.param(
Expand Down Expand Up @@ -112,18 +115,56 @@ class TestTask1:
2,
np.array(
[
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [10, 20, 30], [40, 50, 60], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]],
[
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
],
[
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
],
[
[0, 0, 0],
[0, 0, 0],
[10, 20, 30],
[40, 50, 60],
[0, 0, 0],
[0, 0, 0],
],
[
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
],
[
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
],
],
dtype=np.uint8,
),
id="3d_rgb_pad_2",
),
pytest.param(
np.zeros((2, 3), dtype=int), 1, np.zeros((4, 5), dtype=int), id="2d_zeros_pad_1"
np.zeros((2, 3), dtype=int),
1,
np.zeros((4, 5), dtype=int),
id="2d_zeros_pad_1",
),
pytest.param(
np.arange(4095 * 4095).reshape(4095, 4095) % 256,
Expand Down Expand Up @@ -182,7 +223,8 @@ def test_pad_size_validate(self):
),
3,
np.array(
[[[39, 28, 82], [39, 28, 82]], [[39, 28, 82], [39, 28, 82]]], dtype=np.uint8
[[[39, 28, 82], [39, 28, 82]], [[39, 28, 82], [39, 28, 82]]],
dtype=np.uint8,
),
id="3d_blur_3",
),
Expand Down Expand Up @@ -262,13 +304,25 @@ class TestTask2:
id="chain_within_threshold",
),
pytest.param(
np.array([[255, 0, 0]], dtype=np.uint8), 20, [0], 2 / 3, id="marginal_values_1"
np.array([[255, 0, 0]], dtype=np.uint8),
20,
[0],
2 / 3,
id="marginal_values_1",
),
pytest.param(
np.array([[0, 255, 0]], dtype=np.uint8), 20, [0], 2 / 3, id="marginal_values_2"
np.array([[0, 255, 0]], dtype=np.uint8),
20,
[0],
2 / 3,
id="marginal_values_2",
),
pytest.param(
np.array([[0, 0, 255]], dtype=np.uint8), 20, [0], 2 / 3, id="marginal_values_3"
np.array([[0, 0, 255]], dtype=np.uint8),
20,
[0],
2 / 3,
id="marginal_values_3",
),
pytest.param(
np.load(os.path.join(DATA_PATH, "test_task2_data1.npy")),
Expand All @@ -279,8 +333,12 @@ class TestTask2:
),
],
)
def test_get_dominant_color_info(self, image, threshold, expected_color, expected_ratio):
color, ratio_percent = get_dominant_color_info(image.astype(np.uint8), threshold)
def test_get_dominant_color_info(
self, image, threshold, expected_color, expected_ratio
):
color, ratio_percent = get_dominant_color_info(
image.astype(np.uint8), threshold
)

assert color in expected_color
assert (abs(ratio_percent - expected_ratio * 100) < 1e-6) or (
Expand Down
12 changes: 12 additions & 0 deletions solutions/sem02/lesson05/task1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import numpy as np


class ShapeMismatchError(Exception):
pass


def can_satisfy_demand(
costs: np.ndarray,
resource_amounts: np.ndarray,
demand_expected: np.ndarray,
) -> bool: ...
11 changes: 11 additions & 0 deletions solutions/sem02/lesson05/task2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import numpy as np


class ShapeMismatchError(Exception):
pass


def get_projections_components(
matrix: np.ndarray,
vector: np.ndarray,
) -> tuple[np.ndarray | None, np.ndarray | None]: ...
12 changes: 12 additions & 0 deletions solutions/sem02/lesson05/task3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import numpy as np


class ShapeMismatchError(Exception):
pass


def adaptive_filter(
Vs: np.ndarray,
Vj: np.ndarray,
diag_A: np.ndarray,
) -> np.ndarray: ...
Binary file added tests/test_data/lesson05/Vj_data.npy
Binary file not shown.
Binary file added tests/test_data/lesson05/Vs_data.npy
Binary file not shown.
Binary file added tests/test_data/lesson05/diag_A_data.npy
Binary file not shown.
Binary file added tests/test_data/lesson05/y_data.npy
Binary file not shown.
Loading
Loading