2025, Dec 09 09:01

Как настроить Mosek Fusion для получения допустимого решения после тайм-аута

Почему после тайм-аута Mosek Fusion не отдает level() и как вернуть лучшую допустимую точку: AccSolutionStatus.Feasible, acceptedSolutionStatus для MIP

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

Воспроизведение проблемы

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

from mosek.fusion import *
import mosek.fusion.pythonic
import numpy as np
import sys

if __name__ == '__main__':
  mdl = Model()
  matA = np.array(np.random.randint(-1, 2, size=(128, 256)), dtype=np.float64)
  dv = mdl.variable("x_bin", 256, Domain.binary())
  vecb = np.array(np.random.randint(0, 20, size=(128)), dtype=np.float64)
  coeffs = np.random.random(size=256)

  mdl.constraint(matA @ dv <= vecb)
  mdl.objective(ObjectiveSense.Maximize, dv.T @ coeffs)
  mdl.setSolverParam("optimizerMaxTime", 1)
  mdl.setLogHandler(sys.stdout)
  mdl.solve()
  print(dv.level())

Когда лимит времени исчерпан, Fusion сообщает статус «допустимо», но не «оптимально», и возникает ошибка:

SolutionError: Solution status is Feasible but Optimal is expected. Reason: Accessing integer solution whose problem status is PrimalFeasible.

Что происходит

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

Решение

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

mdl.acceptedSolutionStatus(AccSolutionStatus.Feasible)

С этой настройкой Fusion позволит запрашивать значения даже если решатель завершился раньше, оставив допустимого инкумбента.

Исправленный пример

from mosek.fusion import *
import mosek.fusion.pythonic
import numpy as np
import sys

if __name__ == '__main__':
  mdl = Model()
  matA = np.array(np.random.randint(-1, 2, size=(128, 256)), dtype=np.float64)
  dv = mdl.variable("x_bin", 256, Domain.binary())
  vecb = np.array(np.random.randint(0, 20, size=(128)), dtype=np.float64)
  coeffs = np.random.random(size=256)

  mdl.constraint(matA @ dv <= vecb)
  mdl.objective(ObjectiveSense.Maximize, dv.T @ coeffs)

  mdl.acceptedSolutionStatus(AccSolutionStatus.Feasible)

  mdl.setSolverParam("optimizerMaxTime", 1)
  mdl.setLogHandler(sys.stdout)
  mdl.solve()
  print(dv.level())

Поведение модели и процесса решения остаётся прежним. Единственное отличие — мы указываем Fusion принимать допустимое решение для чтения значений после истечения лимита времени. Этот подход задокументирован здесь: https://docs.mosek.com/latest/pythonfusion/accessing-solution.html#retrieving-solution-values.

Зачем это нужно

Лимиты времени — практичные «ограждения» в целочисленной оптимизации. Если решатель останавливается по времени, а не по оптимальности, лучшая допустимая точка всё ещё может быть полезной. Разрешив Fusion принимать статус «допустимо», вы сразу получаете доступ к этим значениям — особенно удобно, если собираетесь продолжить работу с этим состоянием модели или донастроить её.

Выводы

Если решение завершилось по тайм-ауту и вам нужна лучшая допустимая точка, заранее укажите в Fusion, что её можно принимать, — до вызова level(). Это поможет работать без сбоев при ограниченных временных бюджетах и избавит от неожиданных исключений, когда достаточно допустимого, пусть и не оптимального, результата.