Документация Engee

Задачи линейной и целочисленной оптимизации

Страница в процессе перевода.

Пример: краткосрочное финансирование

Ниже показано, как решить задачу линейной оптимизации с помощью оптимизатора HiGHS. Этот пример взят из документации по JuMP.

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

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

Месяц Янв Фев Мар Апр Май Июн

Чистый объем денежных средств

--150

--100

200

--200

50

300

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

  1. Кредитная линия: компания может использовать кредитную линию на сумму до 100 000 долларов по процентной ставке 1 % в месяц.

  2. Выпуск биржевых облигаций: в любой из первых трех месяцев компания может выпустить 90-дневные биржевые облигации с общей процентной ставкой 2 % за три месяца.

  3. Инвестиция излишков средств: излишки средств можно инвестировать под процентную ставку 0,3 % в месяц.

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

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

  • u_i: сумма, которая берется по кредитной линии в i-й месяц.

  • v_i: стоимость биржевых облигаций, выпущенных в i-й месяц.

  • w_i: излишки средств в i-й месяц.

Необходимо учитывать следующие ограничения.

  1. В каждом месяце поступление денежных средств должно быть равно их расходу.

  2. Для обеспечения соблюдения лимита по кредитной линии должны быть установлены верхние границы для u_i.

  3. Переменные решения u_i, v_i и w_i должны быть неотрицательными.

Конечная цель — максимизировать капитал компании в июне, представленный переменной m.

using Optimization, OptimizationMOI, ModelingToolkit, HiGHS, LinearAlgebra

@variables u[1:5] [bounds = (0.0, 100.0)]
@variables v[1:3] [bounds = (0.0, Inf)]
@variables w[1:5] [bounds = (0.0, Inf)]
@variables m [bounds = (0.0, Inf)]

cons = [u[1] + v[1] - w[1] ~ 150 # Январь
        u[2] + v[2] - w[2] - 1.01u[1] + 1.003w[1] ~ 100 # Февраль
        u[3] + v[3] - w[3] - 1.01u[2] + 1.003w[2] ~ -200 # Март
        u[4] - w[4] - 1.02v[1] - 1.01u[3] + 1.003w[3] ~ 200 # Апрель
        u[5] - w[5] - 1.02v[2] - 1.01u[4] + 1.003w[4] ~ -50 # Май
        -m - 1.02v[3] - 1.01u[5] + 1.003w[5] ~ -300]

@named optsys = OptimizationSystem(m, [u..., v..., w..., m], [], constraints = cons)
optsys = complete(optsys)
optprob = OptimizationProblem(optsys,
    vcat(fill(0.0, 13), 300.0);
    grad = true,
    hess = true,
    sense = Optimization.MaxSense)
sol = solve(optprob, HiGHS.Optimizer())
retcode: Success
u: 14-element Vector{Float64}:
  100.0
  100.0
  100.0
  100.0
  100.0
   50.0
 8274.735079210432
  195.09803921568627
    0.0
 8173.735079210433
 8592.35432366375
 8366.131386634737
    0.0
    0.0

Частично целочисленная нелинейная оптимизация

Мы выбрали пример из файла сведений Juniper.jl, чтобы продемонстрировать частично целочисленную нелинейную оптимизацию с помощью Optimization.jl. Задачу можно сформулировать следующим образом:

что подразумевает задачу максимизации двоичных переменных с целевой функцией в виде скалярного произведения v и u при квадратичном ограничении на u.

using Juniper, Ipopt

v = [10, 20, 12, 23, 42]
w = [12, 45, 12, 22, 21]

objective = (u, p) -> (v = p[1:5]; dot(v, u))

cons = (res, u, p) -> (w = p[6:10]; res .= [sum(w[i] * u[i]^2 for i in 1:5)])

optf = OptimizationFunction(objective, Optimization.AutoSymbolics(), cons = cons)
optprob = OptimizationProblem(optf,
    zeros(5),
    vcat(v, w);
    sense = Optimization.MaxSense,
    lb = zeros(5),
    ub = ones(5),
    lcons = [-Inf],
    ucons = [45.0],
    int = fill(true, 5))

nl_solver = OptimizationMOI.MOI.OptimizerWithAttributes(Ipopt.Optimizer,
    "print_level" => 0)
minlp_solver = OptimizationMOI.MOI.OptimizerWithAttributes(Juniper.Optimizer,
    "nl_solver" => nl_solver)

sol = solve(optprob, minlp_solver)
retcode: Success
u: 5-element Vector{Float64}:
 0.0
 0.0
 0.0
 1.0
 1.0