Целочисленная решающая переменная в нелинейном программировании

Я хотел бы максимизировать частное двух функций linear. Я хотел бы, чтобы мои переменные решения были здесь Binary, т.е. они должны быть integers и могут принимать значения только 0 и 1.

Я хотел знать, как я могу достичь этого? Я хочу использовать такой алгоритм, как SLSQP, и я просмотрел scipy, но, к сожалению, он не ограничивает значения переменных решения двоичными и целыми числами.

Кто-нибудь знает библиотеку с простым для понимания интерфейсом, которую я могу использовать для достижения этой цели? Или если есть способ добиться этого через сам scipy. Я прочитал этот вопрос: ограничить scipy.optimize.minimize целыми значениями

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


person linearprogrammer    schedule 20.10.2018    source источник
comment
Решатели MINLP легко доступны. В противном случае взгляните на алгоритм Динкельбаха [link].   -  person Erwin Kalvelagen    schedule 20.10.2018
comment
Знаете ли вы какие-либо высококачественные решатели minlp для python?   -  person linearprogrammer    schedule 21.10.2018
comment
Pyomo предоставляет доступ к различным решателям MINLP.   -  person Erwin Kalvelagen    schedule 21.10.2018
comment
Можете ли вы дать мне ссылку на несколько примеров, где используется решатель MINLP от pyomo? Кажется, я не могу найти его!   -  person linearprogrammer    schedule 22.10.2018
comment
Например. Барон, MindtPy, Выпуклый MINLP. Обратите внимание, что Pyomo может взаимодействовать с решателями AMPL, поэтому таким образом можно использовать такие решатели, как Bonmin и Couenne. Также: вы можете запускать решатели на NEOS через Pyomo.   -  person Erwin Kalvelagen    schedule 22.10.2018


Ответы (2)


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

import numpy as np

def maximize(numer, denom):
    """ 
    Function that maximizes an expression on the form

    a[0]*x[0] + a[1]*x[1] + ... + a[n-1]*x[n-1]
    -----------------------------------------
    b[0]*x[0] + b[1]*x[1] + ... + b[n-1]*x[n-1]

    where a[i] >= 0, b[i] >= 0, x[i] in [0,1] for 0 < i < n (non-negativity)
    and
    a[0] >= 0, b[0] > 0, x[0] = 1 (no division by zero)
    """

    ratios = numer / denom
    indices, ratios = zip(*sorted(enumerate(ratios), key = lambda x: - x[1]))
    decision = np.zeros_like(numer) 
    decision[0] = 1 # the bias is always enabled
    best_value = np.sum(decision * numer) / np.sum(decision * denom)
    for index, ratio in zip(indices, ratios):
        if index == 0:
            continue
        if ratio > best_value:
            decision[index] = 1 
            best_value = np.sum(decision * numer) / np.sum(decision * denom)
        else:
            # no more ratios can increase the cumulative ratio
            break  
    return decision

и вот пример использования

if __name__ == "__main__":
    numer = np.array([1, 3, 4, 6])
    denom = np.array([1, 2, 2, 3])
    print("Input: {} / {}".format(",".join([str(x) for x in numer]), ",".join([str(x) for x in denom])))
    decision = maximize(numer, denom)
    print("Decision: {}".format(decision))
    print("Objective: {}".format(np.sum(decision * numer) / np.sum(decision * denom)))
person skalet    schedule 20.10.2018
comment
Будет ли эта реализация работать, если у меня будут другие ограничения? - person linearprogrammer; 21.10.2018
comment
Зависит от ограничений, но в целом нет - person skalet; 21.10.2018

Я делаю это совершенно неожиданно... но вот как бы я поступил с mystic.

>>> equations = """
... 3.*x0 + 5.*x1 + 7.*x2 + 9.*x3 = 1.*x0 + 2.*x1 + 3.*x3
... """
>>> bounds = [(0,None)]*4
>>>
>>> def objective(x):
...   return x[0]**2 + 2*x[1] - 2*x[2] - x[3]**2
... 
>>> from mystic.symbolic import generate_penalty, generate_conditions
>>> pf = generate_penalty(generate_conditions(equations))
>>> from mystic.constraints import integers
>>> 
>>> @integers()
... def round(x):
...   return x
... 
>>> from mystic.solvers import diffev2
>>> result = diffev2(objective, x0=bounds, bounds=bounds, penalty=pf, constraints=round, npop=20, gtol=50, disp=True, full_output=True)
Optimization terminated successfully.
         Current function value: 0.000000
         Iterations: 121
         Function evaluations: 2440
>>> result[0]
array([0., 0., 0., 0.])

Теперь немного изменим уравнения...

>>> equations = """
... 3.*x0 + 5.*x1 + 7.*x2 + 9.*x3 = 5 + 1.*x0 + 2.*x1 + 3.*x3
... """
>>> pf = generate_penalty(generate_conditions(equations))
>>> result = diffev2(objective, x0=bounds, bounds=bounds, penalty=pf, constraints=round, npop=20, gtol=50, disp=True, full_output=True)
Optimization terminated successfully.
         Current function value: 3.000000
         Iterations: 102
         Function evaluations: 2060
>>> result[0]
array([1., 1., 0., 0.])

Если вам нужны двоичные переменные вместо целых чисел, вы можете либо использовать bounds = [(0,1)]*4, либо заменить @integers() на @discrete([0.0, 1.0]).

Хотя приведенный выше результат не слишком интересен, есть несколько более продуманных примеров глобальной оптимизации с целочисленным программированием и обобщенными ограничениями на GitHub mystic: https://github.com/uqfoundation/mystic/blob/master/examples2/integer_programming.py https://github.com/uqfoundation/mystic/blob/master/examples2/olympic.py

person Mike McKerns    schedule 21.10.2018
comment
Привет, Майк, я хотел узнать, есть ли более элегантный способ создания целевых функций и функций ограничений? Я не хочу писать уравнения str. Как и в ortools, для создания целевой функции я могу использовать следующий код: target = Solver.Objective() for i in range(0, len(data)): food[i] = Solver.NumVar(0.0, Solver. infinity(), data[i][0]) target.SetCoefficient(food[i], 1). Я хочу сделать это, потому что у меня есть более 10000 переменных решения, участвующих в одном уравнении, и ручное написание уравнения, как у вас, не представляется возможным! С нетерпением жду вашего ответа! Ваше здоровье! - person linearprogrammer; 23.10.2018
comment
С помощью mystic вы можете создавать ограничения, границы и цель исключительно с помощью функционального программирования или с помощью интерфейса класса решателя (аналогично ortools). - person Mike McKerns; 23.10.2018
comment
Можете ли вы указать мне пример, где изображено функциональное программирование мистики? Извините, что беспокою вас таким количеством вопросов, но мне трудно выбрать подходящую библиотеку для моей проблемы с MINLP. - person linearprogrammer; 23.10.2018