我正在使用纸浆来解决具有许多变量的特定问题,混合了1-D,2-D和3-D变量。当获得解决方案时,我想将这些变量变为k维numpy数组。
变量:
u = pulp.LpVariable.dicts("u", (ns, ns), 0, 1, "Integer")
v = pulp.LpVariable.dicts("v", (ns, ns), 0, 1, "Integer")
w = pulp.LpVariable.dicts("w", (ns, ns, ps), 0, 1, "Integer")
x = pulp.LpVariable.dicts("x", (ns, ps), 0, 1, "Integer")
y = pulp.LpVariable.dicts("y", (ms, ps), 0, 1, "Integer")
z = pulp.LpVariable.dicts("z", (ns), parameters.hold_duration_min,
parameters.hold_duration_max, "Continuous")
varnames = {"u": u, "v": v, "w": w, "x": x, "y": y, "z": z}
输入(解决后):
problem.variables()
输出:
[u_0_1, u_0_2, u_0_3, u_0_4, u_0_5, u_0_6, u_1_2, u_1_3, u_1_4, u_1_5, u_1_6, u_2_3, u_2_4, u_2_5, u_2_6, u_3_4, u_3_5, u_3_6, u_4_5, u_4_6, u_5_6, v_0_1, v_0_2, v_0_3, v_0_4, v_0_5, v_0_6, v_1_2, v_1_3, v_1_4, v_1_5, v_1_6, v_2_3, v_2_4, v_2_5, v_2_6, v_3_4, v_3_5, v_3_6, v_4_5, v_4_6, v_5_6, w_0_1_0, w_0_1_1, w_0_1_2, w_0_1_3, w_0_1_4, w_0_1_5, w_0_1_6, w_0_2_0, w_0_2_1, w_0_2_2, w_0_2_3, w_0_2_4, w_0_2_5, w_0_2_6, w_0_3_0, w_0_3_1, w_0_3_2, w_0_3_3, w_0_3_4, w_0_3_5, w_0_3_6, w_0_4_0, w_0_4_1, w_0_4_2, w_0_4_3, w_0_4_4, w_0_4_5, w_0_4_6, w_0_5_0, w_0_5_1, w_0_5_2, w_0_5_3, w_0_5_4, w_0_5_5, w_0_5_6, w_0_6_0, w_0_6_1, w_0_6_2, w_0_6_3, w_0_6_4, w_0_6_5, w_0_6_6, w_1_0_0, w_1_0_1, w_1_0_2, w_1_0_3, w_1_0_4, w_1_0_5, w_1_0_6, w_1_2_0, w_1_2_1, w_1_2_2, w_1_2_3, w_1_2_4, w_1_2_5, w_1_2_6, w_1_3_0, w_1_3_1, w_1_3_2, w_1_3_3, w_1_3_4, w_1_3_5, w_1_3_6, w_1_4_0, w_1_4_1, w_1_4_2, w_1_4_3, w_1_4_4, w_1_4_5, w_1_4_6, w_1_5_0, w_1_5_1, w_1_5_2, w_1_5_3, w_1_5_4, w_1_5_5, w_1_5_6, w_1_6_0, w_1_6_1, w_1_6_2, w_1_6_3, w_1_6_4, w_1_6_5, w_1_6_6, w_2_0_0, w_2_0_1, w_2_0_2, w_2_0_3, w_2_0_4, w_2_0_5, w_2_0_6, w_2_1_0, w_2_1_1, w_2_1_2, w_2_1_3, w_2_1_4, w_2_1_5, w_2_1_6, w_2_3_0, w_2_3_1, w_2_3_2, w_2_3_3, w_2_3_4, w_2_3_5, w_2_3_6, w_2_4_0, w_2_4_1, w_2_4_2, w_2_4_3, w_2_4_4, w_2_4_5, w_2_4_6, w_2_5_0, w_2_5_1, w_2_5_2, w_2_5_3, w_2_5_4, w_2_5_5, w_2_5_6, w_2_6_0, w_2_6_1, w_2_6_2, w_2_6_3, w_2_6_4, w_2_6_5, w_2_6_6, w_3_0_0, w_3_0_1, w_3_0_2, w_3_0_3, w_3_0_4, w_3_0_5, w_3_0_6, w_3_1_0, w_3_1_1, w_3_1_2, w_3_1_3, w_3_1_4, w_3_1_5, w_3_1_6, w_3_2_0, w_3_2_1, w_3_2_2, w_3_2_3, w_3_2_4, w_3_2_5, w_3_2_6, w_3_4_0, w_3_4_1, w_3_4_2, w_3_4_3, w_3_4_4, w_3_4_5, w_3_4_6, w_3_5_0, w_3_5_1, w_3_5_2, w_3_5_3, w_3_5_4, w_3_5_5, w_3_5_6, w_3_6_0, w_3_6_1, w_3_6_2, w_3_6_3, w_3_6_4, w_3_6_5, w_3_6_6, w_4_0_0, w_4_0_1, w_4_0_2, w_4_0_3, w_4_0_4, w_4_0_5, w_4_0_6, w_4_1_0, w_4_1_1, w_4_1_2, w_4_1_3, w_4_1_4, w_4_1_5, w_4_1_6, w_4_2_0, w_4_2_1, w_4_2_2, w_4_2_3, w_4_2_4, w_4_2_5, w_4_2_6, w_4_3_0, w_4_3_1, w_4_3_2, w_4_3_3, w_4_3_4, w_4_3_5, w_4_3_6, w_4_5_0, w_4_5_1, w_4_5_2, w_4_5_3, w_4_5_4, w_4_5_5, w_4_5_6, w_4_6_0, w_4_6_1, w_4_6_2, w_4_6_3, w_4_6_4, w_4_6_5, w_4_6_6, w_5_0_0, w_5_0_1, w_5_0_2, w_5_0_3, w_5_0_4, w_5_0_5, w_5_0_6, w_5_1_0, w_5_1_1, w_5_1_2, w_5_1_3, w_5_1_4, w_5_1_5, w_5_1_6, w_5_2_0, w_5_2_1, w_5_2_2, w_5_2_3, w_5_2_4, w_5_2_5, w_5_2_6, w_5_3_0, w_5_3_1, w_5_3_2, w_5_3_3, w_5_3_4, w_5_3_5, w_5_3_6, w_5_4_0, w_5_4_1, w_5_4_2, w_5_4_3, w_5_4_4, w_5_4_5, w_5_4_6, w_5_6_0, w_5_6_1, w_5_6_2, w_5_6_3, w_5_6_4, w_5_6_5, w_5_6_6, w_6_0_0, w_6_0_1, w_6_0_2, w_6_0_3, w_6_0_4, w_6_0_5, w_6_0_6, w_6_1_0, w_6_1_1, w_6_1_2, w_6_1_3, w_6_1_4, w_6_1_5, w_6_1_6, w_6_2_0, w_6_2_1, w_6_2_2, w_6_2_3, w_6_2_4, w_6_2_5, w_6_2_6, w_6_3_0, w_6_3_1, w_6_3_2, w_6_3_3, w_6_3_4, w_6_3_5, w_6_3_6, w_6_4_0, w_6_4_1, w_6_4_2, w_6_4_3, w_6_4_4, w_6_4_5, w_6_4_6, w_6_5_0, w_6_5_1, w_6_5_2, w_6_5_3, w_6_5_4, w_6_5_5, w_6_5_6, x_0_0, x_0_1, x_0_2, x_0_3, x_0_4, x_0_5, x_0_6, x_1_0, x_1_1, x_1_2, x_1_3, x_1_4, x_1_5, x_1_6, x_2_0, x_2_1, x_2_2, x_2_3, x_2_4, x_2_5, x_2_6, x_3_0, x_3_1, x_3_2, x_3_3, x_3_4, x_3_5, x_3_6, x_4_0, x_4_1, x_4_2, x_4_3, x_4_4, x_4_5, x_4_6, x_5_0, x_5_1, x_5_2, x_5_3, x_5_4, x_5_5, x_5_6, x_6_0, x_6_1, x_6_2, x_6_3, x_6_4, x_6_5, x_6_6, y_0_0, y_0_1, y_0_2, y_0_3, y_0_4, y_0_5, y_0_6, y_1_0, y_1_1, y_1_2, y_1_3, y_1_4, y_1_5, y_1_6, y_2_0, y_2_1, y_2_2, y_2_3, y_2_4, y_2_5, y_2_6, y_3_0, y_3_1, y_3_2, y_3_3, y_3_4, y_3_5, y_3_6, y_4_0, y_4_1, y_4_2, y_4_3, y_4_4, y_4_5, y_4_6, y_5_0, y_5_1, y_5_2, y_5_3, y_5_4, y_5_5, y_5_6, y_6_0, y_6_1, y_6_2, y_6_3, y_6_4, y_6_5, y_6_6, y_7_0, y_7_1, y_7_2, y_7_3, y_7_4, y_7_5, y_7_6, y_8_0, y_8_1, y_8_2, y_8_3, y_8_4, y_8_5, y_8_6, z_0, z_1, z_2, z_3, z_4, z_5, z_6]
我想要生成的是用于保存结果的numpy数组的字典,例如results
,例如:
results["x"][1][4] == pulp.value(x[1][4])
type(results["x"]) == numpy.ndarray
results["z"][2] == pulp.value(z[2])
results(["w"][6][0][2]) == pulp.value(w[6][0][2])
我尝试了一些使用例如大熊猫,但不能让它适用于我的1-D,2-D和3-D阵列组合:
results = {}
vfunc = numpy.vectorize(lambda i: pulp.value(i))
for k, v in varnames.items():
try:
results[k] = vfunc(pandas.DataFrame(v).values)
except:
pass
......以上适用于2D变量,但不适用于1-D或3-D。
编辑:我最近在另一个项目上回到了这个问题,并通过为多维变量定义一个新类来更彻底地解决了这个问题:
import pulp
import numpy
class MultiDimensionalLpVariable:
def __init__(self, name, dimensions, low_bound, up_bound, cat):
self.name = name
try:
self.dimensions = (*dimensions,)
except:
self.dimensions = (dimensions,)
self.low_bound = low_bound
self.up_bound = up_bound
assert cat in pulp.LpCategories, 'cat must be one of ("{}").'.format(
'", "'.join(pulp.LpCategories)
)
self.cat = cat
self.variables = self._build_variables_array()
self.values = None
def __getitem__(self, index):
return self.variables[index]
def _build_variables_array(self):
f = numpy.vectorize(self._define_variable)
return numpy.fromfunction(f, self.dimensions, dtype="int")
def _define_variable(self, *index):
name = "_".join(map(str, (self.name, *index)))
return pulp.LpVariable(name, self.low_bound, self.up_bound, self.cat)
def evaluate(self):
f = numpy.vectorize(lambda i: pulp.value(i))
self.values = f(self.variables)
我现在可以按如下方式定义一个新变量:
x = MultiDimensionalLpVariable("x",(10,20), 0, 1, "Binary")
可以通过例如
来访问个别变量>>> x[1,2]
x_1_2
或:
>>> x[1][2]
x_1_2
这允许以明确的语法实现约束,例如,等式:
可以写成:
for n in range(N):
problem += sum([x[n][p] for p in range(P)]) == 1
这种方法可以推广到任意数量的维度。
问题解决后,可以获得变量值
>>> x.evaluate()
>>> x.values
array([[1., 0., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[1., 0., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.]])
可以通过例如
来访问单个变量值>>> x.values[1,2]
1.0
或:
>>> x.values[1][2]
1.0
答案 0 :(得分:1)
编辑:忽略此解决方案 - 找到一个更简洁的方法,请参阅原始问题陈述。
我最终解决了这个问题。
使用多维变量的类结构可能对其他人有用。
关键在于定义函数来在numpy数组和一系列dicts之类的字典之间进行转换。
然后,这允许在解决方案上以矢量化的方式在阵列上执行评估,给出一个可用于进一步处理的numpy解决方案值。
它还允许使用相对干净的语法来定义多维LP约束。
import numpy as np
import pulp
class Variable_Matrix:
def __init__(self, name, dimensions, low_bound, up_bound, cat):
self.name = name
self.dimensions = dimensions
self.low_bound = low_bound
self.up_bound = up_bound
self.cat = cat
self.variable_objects = unflatten_variable(
pulp.LpVariable.dicts(self.name,
tuple([range(i) for i in dimensions]),
self.low_bound, self.up_bound, self.cat),
self.dimensions)
self.values = np.empty(self.dimensions)
def __getitem__(self, index):
return self.variable_objects(index)
def evaluate(self):
vectorized_evaluation = np.vectorize(lambda i: pulp.value(i))
self.values = vectorized_evaluation(self.variable_objects)
# Generator for accessing components of a variable, returning the component and
# its position
def variable_iterator_loc(variable, dimensions):
index = [0]* len(dimensions)
depth = 0
yield from _variable_iterator_loc(variable, dimensions, index, depth)
# Recursive function called by variable_iter_loc
def _variable_iterator_loc(variable, dimensions, index, depth):
depth += 1
if len(dimensions) == 1:
for i in range(dimensions[0]):
index[depth - 1] = i
yield variable[i], tuple(index)
else:
for i in range(dimensions[0]):
index[depth - 1] = i
yield from _variable_iterator_loc(variable[i], dimensions[1:],
index, depth)
# create a k-dimensional numpy array of variable objects, given the variable
# as a (dict of dict of ... of dicts) of depth k.
def unflatten_variable(variable, dimensions):
unflattened = np.empty(dimensions, object)
variter = variable_iterator_loc(variable, dimensions)
for i in range(np.prod(dimensions)):
varobject, position = next(variter)
unflattened[position] = varobject
return unflattened
这允许使用干净的语法来定义多维变量,例如:
x = Variable_Matrix("x", (N, N, P), 0, 1, "Integer")
y = Variable_Matrix("y", (N, P), 0, 1, "Integer")
z = Variable_Matrix("z", (N,), c_min, c_max, "Continuous")
这反过来允许在定义多维约束时使用干净的语法,例如:
problem = pulp.LpProblem("My Problem", pulp.LpMinimize)
for n in range(N):
problem += sum([y[n][p] for p in range(P)]) == 1
结果可以按如下方式生成(一旦LP解决):
y.evaluate()
可以访问,例如如下:
y.values[2,3]
上述内容需要大量额外的功能和复杂性,但最终目标是使用非常干净的语法来构建LP方程式,并且可以很好地检索结果和抽象到具有多个维度的变量。
答案 1 :(得分:0)
最初,您的结果(在Pulp中)存储在字典中,但未按数组排序。因此,您需要在ndarray中的正确位置提取它们。另外在我的情况下,变量中有一些我不关心的松弛变量,所以我需要首先提取完整的含义。
#storing Optimisation result (alpha & beta) in a new dictionary
varDic = {}
for v in prob.variables():
if v.name[:5] == 'alpha' or v.name == 'b':
varDic[v.name] = v.varValue
#passing solution (alpha, beta) to proper ndarray
b = varDic['b']
del varDic['b'] #remove beta from dictionary so only alpha is left
x = np.zeros(N)
#storing the value of alpha_i in x(i)
for key in varDic:
x[int(key[6:])] = varDic[key]
答案 2 :(得分:0)
现在老问题,但为了我自己的利益,有更好的(或至少是另一种)方式来做到这一点。它实际上是使用您为变量字典分配的对象:
u = pulp.LpVariable.dicts("u", (ns, ns), 0, 1, "Integer")
v = pulp.LpVariable.dicts("v", (ns, ns), 0, 1, "Integer")
w = pulp.LpVariable.dicts("w", (ns, ns, ps), 0, 1, "Integer")
x = pulp.LpVariable.dicts("x", (ns, ps), 0, 1, "Integer")
y = pulp.LpVariable.dicts("y", (ms, ps), 0, 1, "Integer")
z = pulp.LpVariable.dicts("z", (ns), parameters.hold_duration_min,
parameters.hold_duration_max, "Continuous")
解决问题后,您可以通过以下方式获取解决方案的数组:
u_soln = np.array([[u[i][j].varValue for i in ns] for j in ns])
等