задача оптимизации линейного программирования на Python

Вопрос или проблема

У меня есть следующий DataFrame pandas, который представляет потребление за 7 дней (day_0 — это сегодня, day_-1 — это вчера и т.д.) 10 людей (ids):

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randint(8, 15, size=(10, 7)))
df.columns = ['day_0', 'day_-1', 'day_-2', 'day_-3', 'day_-4', 'day_-5', 'day_-6']
df.index.name="id"

print(df.reset_index())

   id  day_0  day_-1  day_-2  day_-3  day_-4  day_-5  day_-6
0   0    10      10      14       8      14      14      14
1   1    10      13      11      11       8      10      10
2   2    10      12       9      12       9      10      10
3   3    12      12       9      11       9      12      13
4   4    12      13       8      12       8      11       9
5   5    13       9       8      13       9      12      10
6   6     8       9       8      14       8      13      14
7   7    13      10      14      12       8       9      11
8   8     8       8      10      12      11      14      14
9   9    14      13      13       9      11      14      13

Я хотел бы найти ежедневные веса (всего 7 весов: w_0, w_-1, w_-2, w_-3, w_-4, w_-5, w_-6), которые должны иметь следующие свойства:

  1. w_0 > w_-1 > w_-2 > … > w_-6 > 0
  2. w_0 + w_-1 + w_-2 + … + w_-6 = 7
  3. взвешенная средняя для точно k из 10 ids должна быть строго выше порога (например, 11)

Я могу удовлетворить условия 1 и 2, используя функцию экспоненциального затухания и затем нормализуя:

import numpy as np

n = 7

_lambda = 0.5

# Рассчитаем веса, используя экспоненциальное затухание
weights = np.exp(-_lambda * np.arange(n))

# Нормализуем веса так, чтобы их сумма равнялась длине временного ряда
weights *= n / np.sum(weights)

Но я не знаю, как я мог бы также применить условие 3.

Это возможно? Как я могу это сделать на python?

Ответ или решение

Для решения задачи оптимизации линейного программирования в Python с использованием библиотеки pandas и дополнительной библиотеки для линейного программирования, такой как scipy.optimize, нам необходимо учитывать три требования для весов:

  1. Веса должны быть строго положительными и убывающими.
  2. Сумма весов должна равняться 7.
  3. Взвешенное среднее должно превышать заданный порог для ровно k идентификаторов.

Шаги для решения задачи

  1. Создание данных: Мы начнем с создания DataFrame с данными о потреблении.

  2. Формулировка оптимизационной задачи: Мы определим переменные (веса) и ограничения для оптимизации.

  3. Решение проблем с использованием scipy.optimize: Применим инструмент для решения заданной линейной задачи.

Пример кода

Здесь представлен подробный пример кода, который демонстрирует, как можно решать эту задачу:

import pandas as pd
import numpy as np
from scipy.optimize import linprog

# Шаг 1: Создание DataFrame с рандомными данными
np.random.seed(0)
df = pd.DataFrame(np.random.randint(8, 15, size=(10, 7)))
df.columns = ['day_0', 'day_-1', 'day_-2', 'day_-3', 'day_-4', 'day_-5', 'day_-6']
df.index.name = "id"

# Шаг 2: Определение переменных
n_days = 7
threshold = 11
k = 3  # Количество 'id', для которых среднее должно быть больше порога

# Оптимизационная задача
c = np.zeros(n_days)  # Целевая функция (можно изменить по необходимости)
A_eq = np.ones((1, n_days))  # Сумма весов = 7
b_eq = [7]

# Границы для весов: w_i должно быть больше 0
bounds = [(0, None) for _ in range(n_days)]

# Шаг 3: Решение задачи с учетом весов
# Используем линейное программирование
opt_result = linprog(c, A_eq=A_eq, b_eq=b_eq, bounds=bounds, method='highs')

if opt_result.success:
    weights = opt_result.x
    print("Оптимальные веса:", weights)

    # Шаг 4: Вычисление взвешенного среднего
    weighted_averages = df.values @ weights
    count_above_threshold = np.sum(weighted_averages > threshold)

    if count_above_threshold == k:
        print(f"Количество 'id' с взвешенными средними больше {threshold}: {count_above_threshold}")
    else:
        print(f"Не удается достичь ровно {k} 'id' с взвешенными средними больше {threshold}.")
else:
    print("Не удалось найти оптимальные веса.")

Объяснение кода

  1. Создание DataFrame: Мы создаем DataFrame с использованием случайных целых чисел для симуляции потребления.

  2. Определение весов: Переменные для весов создаются, и мы определяем целевую функцию, в которой можно установливать различные условия.

  3. Линейное программирование: Мы используем linprog из scipy.optimize для нахождения весов. Указываем ограничения на сумму весов и границы.

  4. Вывод результатов: Проверяем, выполнены ли условия для количества идентификаторов, чьи взвешенные средние превышают заданный порог.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...