优化Ruby中的利润

时间:2017-09-20 23:22:37

标签: ruby algorithm mathematical-optimization

我使用Ruby,但出于这个问题的目的,它并不重要。

假设我有两种不同的资源,其数量由ab表示。我可以分配d个新资源,由于ab具有相同的成本和相同的生产价值,我可以选择以最有利可图的方式分配资源。

最好这样解释:(a + j) * (b + k) = c,其中j + k = d。我希望通过最佳资源分配来最大化c,同时理解两种不同类型资源的成本及其对生产的价值是相同的。所有变量都是正整数,ab大于0.这是我天真的暴力方法:

def max_alloc(a, b, d)
  max_j = 0
  max_k = 0
  max_c = 0
  (0..d).each do |j|
    k = d - j
    c = (a + j) * (b + k)
    if c > max_c
      max_c = c
      max_j = j
      max_k = k
    end
  end
  [max_j, max_k]
end

我希望有某种数学或算法"技巧"我不知道会让我不得不诉诸蛮力。

2 个答案:

答案 0 :(得分:3)

你真的需要一个算法吗? 这是一个简单的最大/最小优化问题。

现在考虑等式

这是j的函数,所以我们称之为f(j)

您希望找到jc = f(j)最大...所以您想研究它的衍生标志

现在您可以绘制标志表

你有它!

的最大值

这意味着您正在寻找的j, k对是

对于此类值,您的最​​大值为c

在Ruby中

def max_alloc(a, b, d)
    j = (-a + b + d) / 2.0
    j = j.round # round to prevent Float, explained at the end of this answer
    if j < 0
        j = 0 # prevent from negative values
    elsif j > d
        j = d # prevent from values greater than d
    end
    [j, d - j]
end

甚至更短

def max_alloc(a, b, d)
    j = ((-a + b + d) / 2.0).round
    j = [0, [j, d].min].max # make sure j is in range 0..d
    [j, d - j]
end

如果您愿意,也可以使用单行内容

def max_alloc(a, b, d)
    [[0, [((-a + b + d) / 2.0).round, d].min].max, d - [0, [((-a + b + d) / 2.0).round, d].min].max]
end

深入了解案例j < 0j > d

让我们从j必须满足的界限开始:

所以j*是:

现在,由于f(j) 始终抛物线向下打开,绝对最大值将是它的顶点,因此,正如之前发现的那样:

但如果这一点超出j的给定范围怎么办?您必须决定选择j* = 0, k* = dj* = d, k* = 0

由于f(j)的{​​{1}}严格增加且j < j*严格减少,因此距您j > j*越近,j*值越大。

因此,如果f(j)选择j* > d,则选择j* = d,然后选择j* < 0

在这里,我展示了一些情节,只是为了看到这一点:

j* inside the range... nothing to do

j* < 0... the highest in range is when j = 0

j* > d... the highest in range is when j = d

为什么j = 0

正如您刚才所了解的那样j.round是抛物线,而抛物线则具有对称轴。如果f(j)是一个整数,那么你就完成了,否则最大化的整数值是j*?嗯...对于最接近顶点的整数值;即,f(j)

注意:如果j.rounda, b是整数,则d只能是整数或j*。因此xxx.5f(j) j.ceil是相同的......您可以选择。

答案 1 :(得分:0)

对于给定的常量ab,请

f(j,k) = (a + j) * (b + k)

我们希望最大化f(j,k)符合三项要求:

  • j + k = d,对于给定的常量d
  • j >= 0
  • k >= 0

我们可以替换k(或j)来替换k

k = d - j

这会将f更改为:

f(j) = (a + j) * (b + d - j)
     = a*(b + d) + (b + d - a)*j -j**2

现在的问题是f最大化:

0 <= j <= d

这种不平等的第二部分来自k = d - j >= 0。如果d = 0j = k = 0是满足变量非负的要求的唯一解决方案。如果d < 0没有可行的解决方案。应该检查这两种情况,但我会假设d > 0

我们首先将f的导数设置为零并求解j以确定f的斜率为零的位置:

f'(j) = b + d - a - 2*j = 0

所以

j* = (b + d - a)/2

由于f的二阶导数是

f''(j) = -2 < 0

我们知道f是凹的,所以j*是最大值(而不是凸起的最小值)。凸和凹函数在这里显示 1

Convex and Concave Functions

考虑凹函数的图形。 j的值在横轴上。由于j*必须在0d之间才可行(两个变量都具有非负值),所以请点ac和{{图表上的1}}分别等于b0j*

有三种可能性:

  • d,在这种情况下,这是一个可行的解决方案(从0 <= j* <= d开始)。
  • k = d - j* >= 0,在这种情况下,j* < 0的最大可行值是f
  • j = 0,在这种情况下,j* > d的最大可行值是f

确定j = d的最佳值后,j

以下是一些例子。

实施例。 1:k = d - ja = 2b = 3

d = 5

由于j* = (b + d - a)/2 = (3 + 5 - 2)/2 = 3 0 <= 3 <= 5j = 3k = 5 - 3 = 2j的最佳值,k是最佳值。

实施例。 2:f(3) = 25a = 6b = 1

d = 3

由于j* = (b + d - a)/2 = (1 + 3 - 6)/2 = -1 -1 < 0j = 0k = 3 - 0 = 3j的最佳值,k是最佳值。

实施例。 3:f(0) = 24a = 2b = 7

d = 3

由于j* = (b + d - a)/2 = (7 + 3 - 2)/2 = 4 4 < 3j = 3k = 3 - 3 = 0的最佳值,j是最佳值。

如果f(3) = 35j必须是k的最大值的整数值,我们可以假设fa和{{1}是整数值。 (如果bd不是,a可以向上舍入并b向下舍入。)现在让a成为b的值} j*满足j是最大值(但0 <= j <= d不一定是整数)。由于f(j)是凹的,如果j*不是整数,f的最佳值为j*,如果j,则J*.floor。{/ {} p>

1对于所有f(j*.floor) >= f(j*.ceil)j*.ceilf以及所有ab,函数a < b是凹的},x,其中a <= x <= b是具有f(x) >= g(x)g属性的线性函数。