【发布时间】:2023-01-23 01:52:24
【问题描述】:
我有一个线性问题来解决寻找整数。我找到了一种使用 spicy 中新的 milp 实现来解决它的方法。以下是演示代码。
问题如下。从权重向量 w 我正在寻找整数向量 x 例如 x 和权重的点积在给定范围内。看起来像这样
# minimize
abs(w^T @ x - target)
我将其翻译成以下内容以在 milp 中实现:
# maximize
w^T @ x
# constraints
target - error <= w^T @ x <= target + error
在我的特定上下文中,x 可能存在多种解决方案。有没有办法在给定的时间间隔内获得所有解决方案而不是最大化(或最小化)某些东西?
这是 milp 的实现。
import numpy as np
from scipy.optimize import milp, LinearConstraint, Bounds
# inputs
ratio_l, ratio_u = 0.2, 3.0
max_bounds = [100, 200, 2, 20, 2]
target = 380.2772 # 338.34175
lambda_parameter = 2
error = lambda_parameter * 1e-6 * target
# coefficients of the linear objective function
w = np.array([12.0, 1.007825, 14.003074, 15.994915, 22.989769], dtype=np.float64)
# the aim is to minimize
# w^T x - target_mass
# instead I maximize
# w^T x
# in the constraint domain
# target - error <= w^T x <= target + error
# constraints on variables 0 and 1:
# ratio_l <= x[1] / x[0] <= ratio_u
# translation =>
# (ratio_l - ratio_u) * x[1] <= -ratio_u * x[0] + x[1] <= 0
# use max (x[1]) to have a constant
# linear objective function
c = w
# integrality of the decision variables
# 3 is semi-integer = within bounds or 0
integrality = 3 * np.ones_like(w)
# Matrice A that define the constraints
A = np.array([
# boundaries of the mass defined from lambda_parameters
w,
# c[1] / c[0] max value
[-ratio_u, 1.0, 0., 0., 0.],
])
# b_up and b_low vectors
# b_low <= A @ x <= b_up
n_max_C = max_bounds[0]
b_up = [
target + error, # mass target
0., # c[1] / c[0] constraints up
]
b_low = [
target - error, # mass target
(ratio_l - ratio_u) * max_bounds[0], # H_C constraints up
]
# set up linear constraints
constraints = LinearConstraint(A, b_low, b_up)
bounds = Bounds(
lb=[0, 0, 0, 0, 0],
ub=max_bounds,
)
results = milp(
c=c,
constraints=constraints,
integrality=integrality,
bounds=bounds,
options=dict(),
)
print(results)
结果是这样的
fun: 380.277405
message: 'Optimization terminated successfully. (HiGHS Status 7: Optimal)'
mip_dual_bound: 380.27643944560145
mip_gap: 2.5390790665913637e-06
mip_node_count: 55
status: 0
success: True
x: array([19., 40., 0., 7., 0.])
但它存在其他可能的 x 数组但错误率最高。这个是
m = np.dot(w, [19., 40., 0., 7., 0.])
print(f"{'target':>10s} {'calc m':>27s} {'deviation':>27s} {'error':>12s} match?")
print(f"{target:10.6f} {target - error:14.6f} <= {m:10.6f} <= {target + error:10.6f}"
f" {m - target:12.6f} {error:12.6f} -> {target - error <= m <= target + error}")
target calc m deviation error match?
380.277200 380.276439 <= 380.277405 <= 380.277961 0.000205 0.000761 -> True
这两个其他示例也有效,我想知道如何在不实现网格算法(如 scipy 中的 brute)的情况下获得它们。
m = np.dot(w, [20., 39., 1., 4., 1.])
print(f"{'target':>10s} {'calc m':>27s} {'deviation':>27s} {'error':>12s} match?")
print(f"{target:10.6f} {target - error:14.6f} <= {m:10.6f} <= {target + error:10.6f}"
f" {m - target:12.6f} {error:12.6f} -> {target - error <= m <= target + error}")
target calc m deviation error match?
380.277200 380.276439 <= 380.277678 <= 380.277961 0.000478 0.000761 -> True
m = np.dot(w, [21., 38., 2., 1., 2.])
print(f"{'target':>10s} {'calc m':>27s} {'deviation':>27s} {'error':>12s} match?")
print(f"{target:10.6f} {target - error:14.6f} <= {m:10.6f} <= {target + error:10.6f}"
f" {m - target:12.6f} {error:12.6f} -> {target - error <= m <= target + error}")
target calc m deviation error match?
380.277200 380.276439 <= 380.277951 <= 380.277961 0.000751 0.000761 -> True
【问题讨论】:
-
听起来您想枚举所有最佳整数解决方案。 scipy 的 milp 接口 MILP Solver Highs,据我所知,它还不支持计数/枚举。如果您愿意使用其他 python 包来解决您的问题,我稍后会发布答案。 PS:@Reinderien 最小化线性函数的绝对值可以作为 LP 解决,在重新制定问题后。
-
@joni 好吧,我会被诅咒的。这有一个很好的解释 - math.stackexchange.com/a/1955013/54983
-
谢谢。 @joni,是的,如果需要,我愿意接受其他软件包。目前,我通过构建一个包含各种约束的整数列表来解决它,然后我反复寻找解决方案。 LP 你的意思是线性规划,比如 Reinderien 的例子?
-
@Ger 是的,这就是 LP 所代表的意思,尽管我认为 LP 不能很好地应用于这个问题
标签: python scipy scipy-optimize mixed-integer-programming