当前位置: 首页 > 面试题库 >

将scipy.optimize.minimize限制为整数值

杨无尘
2023-03-14
问题内容

scipy.optimize.minimize用来优化一个实际问题,答案只能是整数。我当前的代码如下所示:

from scipy.optimize import minimize

def f(x):
    return (481.79/(5+x[0]))+(412.04/(4+x[1]))+(365.54/(3+x[2]))+(375.88/(3+x[3]))+(379.75/(3+x[4]))+(632.92/(5+x[5]))+(127.89/(1+x[6]))+(835.71/(6+x[7]))+(200.21/(1+x[8]))

def con(x):
    return sum(x)-7

cons = {'type':'eq', 'fun': con}

print scipy.optimize.minimize(f, [1,1,1,1,1,1,1,0,0], constraints=cons, bounds=([0,7],[0,7],[0,7],[0,7],[0,7],[0,7],[0,7],[0,7],[0,7]))

这样产生:

x: array([  2.91950510e-16,   2.44504019e-01,   9.97850733e-01,
     1.05398840e+00,   1.07481251e+00,   2.60570253e-01,
     1.36470363e+00,   4.48527831e-02,   1.95871767e+00]

但是我希望使用整数值对其进行优化(将所有数值四舍五入x到最接近的整数并不总是给出最小值)。

有没有办法scipy.optimize.minimize只使用整数值?

(我想我可以创建一个具有所有可能排列的数组,x并为每个组合评估f(x),但这似乎不是一个非常优雅或快速的解决方案。)


问题答案:

纸浆溶液

经过研究,我认为您的目标函数不是线性的。我在Python纸浆库中重新创建了问题,但纸浆不喜欢我们用浮点数和’LpAffineExpression’进行划分。该答案表明线性编程“不理解除法”,但该注释是在添加约束而不是目标函数的情况下进行的。该评论将我指向“混合整数线性分数规划(MILFP)
”和Wikipedia上。

如果纸浆实际起作用,可以按以下方法进行处理(也许有人可以弄清楚原因):

import pulp

data = [(481.79, 5), (412.04, 4), (365.54, 3)] #, (375.88, 3), (379.75, 3), (632.92, 5), (127.89, 1), (835.71, 6), (200.21, 1)]
x = pulp.LpVariable.dicts('x', range(len(data)), lowBound=0, upBound=7, cat=pulp.LpInteger)

numerator = dict((i,tup[0]) for i,tup in enumerate(data))
denom_int = dict((i,tup[1]) for i,tup in enumerate(data))

problem = pulp.LpProblem('Mixed Integer Linear Programming', sense=pulp.LpMinimize)

# objective function (doesn't work)
# TypeError: unsupported operand type(s) for /: 'float' and 'LpAffineExpression'
problem += sum([numerator[i] / (denom_int[i] + x[i]) for i in range(len(data))])

problem.solve()

for v in problem.variables():
  print(v.name, "=", v.varValue)

使用scipy.optimize的蛮力解决方案

您可以在函数中为每个使用brute和的范围。如果函数中有3 s,则范围元组中也将有3 s。所有这一切的关键是添加 步*
的尺寸为如此。slice``x``x``slice
1``slice(start, stop, step*`)``slice(#,

from scipy.optimize import brute
import itertools

def f(x):
  return (481.79/(5+x[0]))+(412.04/(4+x[1]))+(365.54/(3+x[2]))

ranges = (slice(0, 9, 1),) * 3
result = brute(f, ranges, disp=True, finish=None)
print(result)

itertools解决方案

或者,您可以使用itertools生成所有组合:

combinations = list(itertools.product(*[[0,1,2,3,4,5,6,7,8]]*3))

values = []
for combination in combinations:
  values.append((combination, f(combination)))

best = [c for c,v in values if v == min([v for c,v in values])]
print(best)

注意 :这是原始功能的缩小版本,仅供参考。



 类似资料:
  • 问题内容: 我知道这个问题一定已经被提出并回答了一百万遍了,但是我找不到一个简单的解决方案。我有一个JTextField,它只接受正整数作为输入。我需要一种方法来确保此处没有其他输入。 我已经有一个附加到此控件。删除此侦听器在那里要处理的其他代码,我得到了: 如你所见,我正在尝试使用来检查刚刚按下的键是否在整数范围内。这似乎有效。但是我想做的就是,如果该条目不在此范围内,则只需忽略该条目。该代码本

  • 问题内容: 在应用程序的Java部分中创建EditText时,如何将其限制为与xml中一样的数字?例如: 设置像 问题答案: 大概是这样吗?

  • 问题内容: 我经常想制作一张条形图。如果计数较低,我经常会得到不是整数的主要和/或次要刻度位置。我该如何预防?计数数据时在1.5处打勾是没有意义的。 这是我的第一次尝试: 当计数较小时,它可以正常工作,但是当计数较大时,我得到许多次要的滴答声: 如何从第一个示例中获得少量的期望行为,同时避免第二个示例中发生的情况? 问题答案: 您可以使用该方法,如下所示:

  • 我经常想制作一个计数条形图。如果计数很低,我经常会得到不是整数的主要和/或次要刻度位置。我该如何防止这种情况?当数据是计数时,刻度为1.5是没有意义的。 这是我第一次尝试: 当计数很小时,它工作正常,但当计数很大时,我会得到许多小刻度: 如何在避免第二个示例中发生的情况的同时,从第一个示例中获得所需的少量行为?

  • 问题内容: 我正在尝试将一个数字从一个整数转换为另一个整数,如果以十六进制打印,它将看起来与原始整数相同。 例如: 将20转换为32(即0x20) 将54转换为84(即0x54) 问题答案: 即,将原始数字视为十六进制,然后将其转换为十进制。

  • 问题内容: 我正在尝试进行多项选择调查,以允许用户从选项1-x中进行选择。如何做到这一点,以便用户输入除数字以外的任何字符,返回“那是无效答案”之类的内容 问题答案: 您的代码将变为: 它的工作方式是使循环无限循环,直到仅放入数字为止。因此,如果我输入“ 1”,它将破坏循环。但是如果我放“ Fooey!” 该语句将捕获“将引发的错误” ,并且该循环将循环,因为它没有被破坏。