Почему я не могу настроить ограниченную оптимизацию SciPy для целочисленного программирования?

Я читал, что целочисленное Программирование либо очень сложно, либо невозможно с помощью SciPy и что мне, вероятно, нужно использовать что-то вроде zibopt, чтобы сделать это на Python . Но я действительно думал, что смогу сделать это, создав одно "двоичное" ограничение для каждого элемента в векторе, оптимизированном SciPy.

для этого я использовал трюк закрытия из http://docs.python-guide.org/en/latest/writing/gotchas/#late-binding-closures и создал одного функция ограничения для каждого элемента, например:

def get_binary_constraints(vector, indices_to_make_binary=None):
    indices_to_make_binary = indices_to_make_binary or range(len(vector))
    for i in indices_to_make_binary:
        def ith_element_is_binary(vector, index=i):
            return vector[index] == 0 or vector[index] == 1
        yield ith_element_is_binary

test_vector = scipy.array([0.5, 1, 3])
constraints = list(get_binary_constraints(test_vector))
for constraint in constraints:
    print constraint(test_vector)

, который печатает:

False
True
False

затем я изменил get_binary_constraints для fmin_cobyla, ограничения которого являются "последовательность функций, которые все должны быть >=0".

def get_binary_constraints(vector, indices_to_make_binary=None):
    indices_to_make_binary = indices_to_make_binary or range(len(vector))
    for i in indices_to_make_binary:
        def ith_element_is_binary(vector, index=i):
            return int(vector[index] == 0 or vector[index] == 1) - 1
        yield ith_element_is_binary

который печатает следующее Для того же вектора теста[0.5, 1, 3]:

-1
0
-1

таким образом, только 2-е значение в массиве будет соответствовать условию >= 0.

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

from scipy import optimize
import scipy

def get_binary_constraints(vector, indices_to_make_binary=None):
    indices_to_make_binary = indices_to_make_binary or range(len(vector))
    for i in indices_to_make_binary:
        def ith_element_is_binary(vector, index=i):
            return int(vector[index] == 0 or vector[index] == 1) - 1
        yield ith_element_is_binary

def objective_function(vector):
    return scipy.sum(vector)

def main():
    guess_vector = scipy.zeros(3)
    constraints = list(get_binary_constraints(guess_vector))
    result = optimize.fmin_cobyla(objective_function, guess_vector, constraints)
    print result

if __name__ == '__main__':
    main()

и вот что я получил:

Return from subroutine COBYLA because the MAXFUN limit has been reached.

NFVALS = 1000   F =-8.614066E+02    MAXCV = 1.000000E+00
X =-2.863657E+02  -2.875204E+02  -2.875204E+02
[-286.36573349 -287.52043407 -287.52043407]

прежде чем я пойду использовать пакет LPSolve R или установить zipobt для этого, я бы очень хотел посмотреть, могу ли я просто использовать SciPy.

Я делаю что-то неправильно, или это просто невозможно сделать в SciPy?

1 ответов


проблема в том, что, как бы неинтуитивно это ни казалось,Целочисленного Программирования является принципиально более сложной задачей, чем линейное программирование с вещественными числами. Кто-то в потоке SO, с которым вы связаны, упоминает, что SciPy использует Симплекс. Алгоритм не работает для целочисленного программирования. Вы должны использовать другой алгоритм.

Если вы найдете способ использовать Симплекс для эффективного решения целочисленного программирования, вы решили P=NP проблема, которая стоит US$1,000,000 для первого лица, чтобы решить.