Задачи оптимального управления python

Как решать простые задачи оптимизации на питоне с помощью cvxpy

Всем доброго времени суток! Простым поиском я не сумел обнаружить упоминание модуля cvxpy и потому решил написать обучающий материал по нему – просто примеры кода, по которым в дальнейшем новичку будет проще использовать этот модуль для своих задач. cvxpy предназначен для решения задач оптимизации – нахождения минимумов/максимумов функций при определённых ограничениях. Если вам интересна эта тема – прошу под кат.

Общая постановка задачи

Здесь x – независимая переменная (в общем случае вектор), f(x)
целевая функция, которую нужно оптимизировать. Ограничения на область определения f(x) могут быть заданы при помощи равенств и неравенств.

Пример задачи

Давайте рассмотрим следующую задачу линейного программирования:

Если посмотреть на область, заданную неравенством с модулем, то можно увидеть что эта область легко может быть задана при помощи линейных неравенств:

В нашем случае ограничения будут следующими:

Решение задачи посредством cvxpy

О установке модуля подробно рассказано на сайте модуля. Давайте напишем простой код, который позволит нам решить нашу тестовую задачу оптимизации:

import numpy as np import cvxpy as cvx # наши независимые переменные x = cvx.Variable(2) A = np.array([[1, 1], [1, -1], [-1, 1], [-1, -1]]) b = np.array([8, 2, 12, 6]) c = np.array([7, -3]) # ограничения constraints = [A * x 

Наше текущее решение нецелое и выходит за ограничения, однако видно что оно лежит рядом с оптимальным решением (-9, 3). В cvxpy можно использовать разные решатели для решения задачи, подбирая лучший. Давайте попробуем GLPK:

prob.solve(solver = "GLPK") print(prob.status) # optimal print(prob.value) # -72.0 print(x.value) # [[-9.] [ 3.]]

Список доступных решателей возвращает функция installed_solvers() .

Другие примеры

Можно решать не только задачи линейного программирования. Давайте рассмотрим исходную формулировку задачи:

# ограничения constraints = [cvx.abs(x[0] + 2) + cvx.abs(x[1] - 3) 

Также можно искать решение для метода наименьших квадратов:

# целевая функция и что с ней делать obj = cvx.Minimize(cvx.norm(A * x - b)) # по умолчанию используется вторая норма # формулируем задачу и решаем prob = cvx.Problem(obj) prob.solve() print(prob.status) # optimal print(prob.value) # 13.9999999869 print(x.value) # [[-2.] [ 3.]]

Конечно, некоторые задачи могут иметь тривиальное решение:

A = np.array([[1, 1], [1, -1], [-1, 1]]) b = np.array([8, 2, 12]) c = np.array([7, -3]) # ограничения constraints = [A * x 

А некоторые могут не иметь решения вовсе:

A = np.array([[1, 1], [1, -1], [-1, 1], [-1, -1]]) b = np.array([-6, -12, -2, -8]) # ограничения constraints = [A * x 

Источник

Решаем задачу сетевого планирования с помощью Python

Приветствую, меня зовут Алёна. Недавно на математический основах информатики в университете мы проходили задачу сетевого планирования, с помощью которой можно смоделировать процесс производства изделий. Мне была интересна данная тема и я решила поделиться с вами, как решить задачу сетевого планирования с использованием языка Python.

Определения

Сетевая модель — сетевой график, элементами которого (вершинами / дугами / и тем и другим) поставлены в соответствие некоторые величины, называемые весами.

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

Суть задачи: требуется определить минимально возможное время, за которое можно выполнить все работы.

Работы сетевого планирования связаны между собой, у каждой работы есть время выполнения.

Терминология

  • i - номер работы
  • t(i) - длительность выполнения работы i
  • K(i) — множество работ, предшествующих работе с номером i

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

К таким характеристикам относятся:

  • t(rn, i) - время самого раннего начала выполнения работы с номером i
  • t(rk, i) - время самого раннего окончания выполнения работы с номером i
  • t(pn, i) - время самого позднего начала выполнения работы с номером i
  • t(pk, i) - время самого позднего окончания выполнения работы с номером i
  • r(i) - резерв времени работы с номером i , т.е. время, на которое не в ущерб времени общего окончания выполнения всех работ, можно задерживать выполнение работы с номером i
  • T(k) - время выполнения всех работ изделия. T(k) - длина критического пути, а критическим путём называют путь, соединяющий некоторую начальную работу - не имеющую предшествующих работ, и некоторую конечную работу - не имеющую последующих, т.е. от неё зависящих работ, суммарное время выполнения всех работ которого максимально.

Формулы

Для расчета временных характеристик будем пользоваться следующими формулами:

  • t(rn,i) = 0, если K(i) - пустое множество.
  • t(rk,i) = t(rn,i) + t(i)t(rn,i)= max t(rk,j), где максимум берется по всем работам j из множества K(i).
  • t(pk,i) = t(rk,i), если работа i не имеет последующих.
  • t(pn,i) = t(pk,i) - t(i)t(pk,i) = min t(pn,j), где минимум берется по тем работам j, которые принадлежат множеству K(i), т.е. по тем работам, от которых зависит работа с номером i.
  • r(i) = t(pn,i) - t(rn,i) = t(pk,i) - t(rk,i). Работы критического пути — это те работы, резервы времени которых нулевые (r(i) = 0).

Условия

  • Граф должен быть без петель и контуров, т.е. антирефлексивным бинарным отношением.
  • Вы должны знать конечную работу. Значение времени критического пути смотрится у конечной работы в столбце t(pk, i).

Пример задачи

Сетевая схема.

i - номер работы, t(i) - время выполнения работы, K(i) - множество работ, от которых зависит работа (для первой работы - это пустое множество).

Итоговая таблица с вычисленными значениями примет вид:

Стоит отметить, что задача решается по алгоритму с тактами и поэтому вы сможете найти +/-1 в решении. Вычисления начинаются с 1.

Конечная работа с номером 12. Смотрим у неё значение столбца t(pk, i). Время, за которое гарантированно можно выполнить все работы = 22.

Пишем алгоритм на Python

Начнём с создания модели, которая будет поступать на вход и второй модели, которая будет заполнять нашу таблицу для планирования. Для удобства использую namedtuple (почитать про него можно тут: https://habr.com/ru/articles/438162/):

from collections import namedtuple input_model = namedtuple("input_model", ["time", "set_k"]) row = namedtuple("row", ["i", "time", "set_k", "rn", "rk", "pn", "pk", "r"])

Считаем количество работ, которое нужно будет обработать:

По введённым данным начинаем решать задачу сетевого планирования:

  • Если у работы нет предшествующих работ (длина множества K(i) = 0), значит это первая работа, с которой начнёт работать наш завод.
  • Иначе - определяем максимальное значение раннего окончания зависимых работ.
  • Обновляем таблицу.
for number, model in models.items(): time = model.time set_k = model.set_k if len(set_k) == 0: rn = 1 else: rn = max([table[s].rk for s in set_k]) + 1 rk = rn + model.time - 1 table[number] = row(i=number, time=time, set_k=set_k, rn=rn, rk=rk, pn=None, pk=None, r=None) 

При подсчётах можно увидеть прибавление или убавление единицы. Это дополнительный такт времени, в принципе решать задачу можно без него.

Продолжаем решать задачу сетевого планирования. Проходимся с конца таблицы (последней работы) для подсчётов:

  • Ищем все посещённые работы с помощью функции search_next_numbers .
  • t(pk, i) - времени самого позднего окончания выполнения работы, считается как минимальное значение выполненных работ.
  • t(pn, i) - времени самого позднего начала выполнения работы, считается как t(pk, i) минус время выполнения работы.
  • r - резерв времени, считается как t(pn, i) минус t(rn, i).
  • В конце можно увидеть assert: проверка на корректность решения задачи (резерв времени должен быть всегда равен времени позднего окончания - времени раннего окончания). Эта строка необязательна, так как использование assert’ов в коде можно отключить и лучше использовать вызовы ошибок с помощью raise Error :).
  • Обновляем данные в таблице.
for number, model in list(models.items())[::-1]: visited = search_next_numbers(number) current_row = table[number] if visited: k = min(visited, key=lambda num: table[num].pn if table[num].pn is not None else 10000000000) pk = table[k].pn - 1 else: pk = current_row.rk pn = pk - current_row.time + 1 r = pn - current_row.rn assert r == pk - current_row.rk and r >= 0, print(f", r=, ") table[number] = table[number]._replace(pk=pk, pn=pn, r=r) 

Для вывода таблицы я использовала библиотеку prettytable. Написала функцию, которая по созданному словарику с табличными данными, будет выводить таблицу:

from prettytable import PrettyTable def print_table(data: dict[int, row]): pretty_table = PrettyTable() pretty_table.field_names = ["i", "t(i)", "K(i)", "t(rn, i)", "t(rk, i)", "t(pn, i)", "t(pk, i)", "r(i)"] for line in data.values(): pretty_set = line.set_k if len(line.set_k) > 0 else "<>" pretty_table.add_row([line.i, line.time, pretty_set, line.rn, line.rk, line.pn, line.pk, line.r]) print(pretty_table) print_table(table) 

Заключение

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

Спасибо за просмотр! Делитесь в комментарии своими мыслями по поводу алгоритма и самой задачи сетевого планирования. До встречи в новых статьях.

Источник

Читайте также:  Css in customer management
Оцените статью