【问题标题】:How to use external data in the objective function in Python PuLP?如何在 Python PuLP 的目标函数中使用外部数据?
【发布时间】:2016-12-13 05:20:32
【问题描述】:

我想选择一个正方形矩阵的一个固定大小的正方形子集,以使子集矩阵的总和最小化。一些代码:

import nump as np
import pulp

def subset_matrix(data, inds):
    return data[np.ix_(inds, inds)]

A = np.random.random((10, 10))

indices = list(range(len(A)))

prob = pulp.LpProblem("Minimum subset", pulp.LpMaximize)

x = pulp.LpVariable.dicts('elem', indices, lowBound=0, upBound=1, cat=pulp.LpInteger)

prob += pulp.lpSum(subset_matrix(A, [x[i] for i in indices]))

prob.solve()

这失败了,因为 numpy 索引不喜欢 indsLpVariables 的列表。有没有解决的办法?如何使纸浆约束包含 numpy 数组查找?

【问题讨论】:

  • 什么是subset_cov?另外,我不确定我是否理解问题中关于indsLpVariables 的列表的要点。从上面的内容来看,这只是一个range
  • @RandyC:对不起,代码错误。我将函数调用固定为subset_matrix,并更改了外部范围索引的名称,以便更清楚地说明我在说哪些索引。
  • 正如我试图在你的同一个问题@pull 的 github 页面中概述的那样:并不是说纸浆不能使用 numpy 数组来查找常量,这当然是可能的,但是查找/索引本身就是undefined 直到优化结束,因为这些变量尚未固定(索引取决于 x;x[] 是您的决策变量)。就像我之前告诉过你的那样:你必须手动完成(使用二进制/整数变量和一些繁重的重新制定)或者寻找一些可用作黑盒的优化软件!问题:支持使用离散变量进行黑盒优化的软件不多

标签: python numpy linear-programming pulp


【解决方案1】:

我不认为这是一个纸浆问题,而是如何将数学问题正确地表述为混合整数线性程序的问题。

您似乎正试图将您的目标表达为系数的总和(“子集矩阵的总和”),在一组要优化的索引上。 (顺便说一句,我看不到子矩阵的大小约束写在哪里。)但是 MILP 要求目标是决策变量向量与成本系数向量在预定索引集上的点积.因此,在自然公式中,决策向量将使用二进制值表示您选择的完整索引集中的哪些索引在您的子矩阵中。

如果我理解您想要做什么,这似乎是一个很好的问题。我相信你正在尝试选择一个固定大小的索引子集 I \subset {0, 1, ..., N-1},这样 sum{A(i,j): i,j both in I}被最大化。例如,假设大矩阵是 10x10,而您想要一个 6x6 的子矩阵。所以我是 {0, ..., 9} 的大约六个元素。

然后我会在 {0, ..., 9} 中为 i, j 定义变量 x(i,j),对于为子矩阵选择的大矩阵的每个元素都等于 1(否则为零) , 和变量 y(i), i in {0, ..., 9},用于选择的索引。然后我会尝试将这些约束表示为线性的,并使 y 变量二进制来表示每个索引是进还是出。

这是我认为您的意思的表述:

import pulp as pp
import numpy as np
import itertools

#####################
#  Problem Data:    #
#####################

full_matrix_size = 10
submatrix_size = 6

A = np.random.random((full_matrix_size, full_matrix_size)).round(2)

inds = range(full_matrix_size)
product_inds = list(itertools.product(inds,inds))

#####################
#  Variables:       #
#####################

# x[(i,j)] = 1 if the (i,j)th element of the data matrix is in the submatrix, 0 otherwise.
x = pp.LpVariable.dicts('x', product_inds, cat='Continuous', lowBound=0, upBound=1)

# y[i] = 1 if i is in the selected index set, 0 otherwise.
y = pp.LpVariable.dicts('y', inds, cat='Binary')

prob = pp.LpProblem("submatrix_problem", pp.LpMaximize)

#####################
#  Constraints:     #
#####################

# The following constraints express the required submatrix shape:
for (i,j) in product_inds:
    # x[(i,j)] must be 1 if y[i] and y[j] are both in the selected index set.
    prob += pp.LpConstraint(e=x[(i,j)] - y[i] - y[j], sense=1, rhs=-1,
                            name="true_if_both_%s_%s" % (i,j))

    # x[(i,j)] must be 0 if y[i] is not in the selected index set.
    prob += pp.LpConstraint(e=x[(i,j)] - y[i], sense=-1, rhs=0,
                            name="false_if_not_row_%s_%s" % (i,j))

    # x[(i,j)] must be 0 if y[j] is not in the selected index set.
    prob += pp.LpConstraint(e=x[(i,j)] - y[j], sense=-1, rhs=0,
                            name="false_if_not_col_%s_%s" % (i,j))

# The number of selected indices must be what we require:    
prob += pp.LpConstraint(e=pp.LpAffineExpression([(y[i],1) for i in inds]), sense=0,
                        rhs=submatrix_size, name="submatrix_size")

#####################
#  Objective:       #
#####################

prob += pp.LpAffineExpression([(x[pair], A[pair]) for pair in product_inds])

print(prob)

########################
#  Create the problem: #
########################

prob.writeLP("max_sum_submatrix.lp")
prob.solve()

########################## 
#  Display the solution: #
##########################
print("The following indices were selected:")
print([v.name for v in prob.variables() if v.name[0]=='y' and  v.varValue==1])
print("Objective value is " + str(pp.value(prob.objective)))

我猜那是带回家的考试题……至少这个学期已经结束了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    • 1970-01-01
    • 2018-12-28
    • 1970-01-01
    相关资源
    最近更新 更多