我想在每个分区中将一个数字分区为几乎相等数量的值。唯一的标准是每个分区必须在60到80之间。
例如,如果我有value = 300
,则表示75 * 4 = 300
。
我想知道在上面的示例中获取此4
和75
的方法。在某些情况下,所有分区都不需要具有相同的值,但它们应该在60 and 80
之间。可以使用任何约束(加法,减法等)。但是,输出不能是浮点数。
同样不是总数必须与300
完全相同,但是它们最多可以达到总数的+40
,因此对于300
,如果需要,这些数字可以总计为340
。
答案 0 :(得分:3)
假设只添加,您可以将此问题表示为linear programming problem。您可以选择一个目标函数,该函数可以最大化为您生成该数字所选择的所有因子的总和。因此,您的目标函数是:
在这种情况下,n
将是您尝试将数字分解为的因素数。每个是您要分解的值的总和中的特定因子。我也将假设所有因素都不是浮点数,并且只能是整数。因此,您需要使用称为integer programming的线性编程的特殊情况,其中约束和问题的实际解决方案都是整数。通常,整数规划问题由此形成:
您实际上是在尝试最小化此目标函数,以便生成受所有这些约束约束的x
参数向量。在我们的例子中,x
将是一个数字向量,其中每个元素构成您尝试分解的值的总和的一部分(在您的情况下为300)。
您的解决方案中的每个参数都必须遵守x
的不等式,等式以及边界。您还需要确保x
的每个参数都是整数。因此,MATLAB有一个名为intlinprog
的函数,它将为您执行此操作。但是,此函数假定您正在最小化目标函数,因此如果要最大化,只需最小化负数。 f
是要应用于参数向量中每个值的权重向量,使用我们的目标函数,您只需将所有这些设置为-1
。
因此,要在整数编程框架中表达您的问题,您实际上是在做:
V
将是您尝试分解的值(在您的示例中为300)。
调用intlinprog
的标准方式如下:
x = intlinprog(f,intcon,A,b,Aeq,beq,lb,ub);
f
是对要解决的解决方案的每个参数进行加权的向量,intcon
表示您的哪个参数需要为整数。在这种情况下,您希望所有这些都是整数,因此您必须提供从1到n
的增加向量,其中n
是要分解数字{{1}的因子数进入(和以前一样)。 V
和A
是定义不等式约束的矩阵和向量。因为你想要平等,所以你要将它设置为空(b
)。 []
和Aeq
与beq
和A
相同,但是为了相等。因为这里只有一个约束,所以您只需创建一个1行的矩阵,其中每个值都设置为1. b
将是一个值,表示您尝试分解的数字。 beq
和lb
是您要绑定的参数集中每个值的下限和上限,因此分别为60和80,并且您必须指定一个向量确保参数的每个值都在这两个范围之间。
现在,因为您没有知道有多少因素会均匀地分解您的价值,您必须循环超过一组给定的因素(如1到10之间,或1到20之间等),将结果放在ub
数组中,然后您必须手动检查自己是否成功进行整数分解。
cell
然后,您可以浏览num_factors = 20; %// Number of factors to try and decompose your value
V = 300;
results = cell(1, num_factors);
%// Try to solve the problem for a number of different factors
for n = 1 : num_factors
x = intlinprog(-ones(n,1),1:n,[],[],ones(1,n),V,60*ones(n,1),80*ones(n,1));
results{n} = x;
end
并查看results
哪个值成功将您的号码分解为所述多个因素。
这里的一个小问题是我们也不知道我们应该检查多少因素。不幸的是,我没有答案,所以你必须玩这个值,直到你得到好的结果。这也是一个不受约束的参数,我将在本文稍后讨论这个问题。
但是,n
仅在最新版本的MATLAB中发布。如果你想在没有它的情况下做同样的事情,你可以使用linprog
,它是整数编程的浮点版本......实际上,它只是核心线性编程框架本身。您可以通过这种方式致电intlinprog
:
linprog
所有变量都是相同的,除了这里没有使用x = linprog(f,A,b,Aeq,beq,lb,ub);
......这是有道理的,因为intcon
可能会生成浮点数作为其解决方案的一部分。由于linprog
可以生成浮点解决方案,您可以做的是,如果您想确保对于给定的linprog
值,您可以循环搜索结果,请在结果并减去最终结果,并对结果求和。如果得到值0,则表示您具有完全整数结果。因此,您必须执行以下操作:
n
num_factors = 20; %// Number of factors to try and decompose your value
V = 300;
results = cell(1, num_factors);
%// Try to solve the problem for a number of different factors
for n = 1 : num_factors
x = linprog(-ones(n,1),[],[],ones(1,n),V,60*ones(n,1),80*ones(n,1));
results{n} = x;
end
%// Loop through and determine which decompositions were successful integer ones
out = cellfun(@(x) sum(abs(floor(x) - x)), results);
%// Determine which values of n were successful in the integer composition.
final_factors = find(~out);
将包含您指定在整数分解中成功的因子数。现在,如果final_factors
为空,这意味着它无法成功找到能够将值分解为整数因子的任何内容。注意到您的问题描述,您说您可以允许容差,因此可能会扫描final_factors
并确定哪个总和最符合该值,然后选择任何数量的因子,将结果作为最终答案。
现在,从我的评论中注意到,你会发现这个问题非常不受约束。您不知道需要多少因子来获得值的整数分解,这就是为什么我们不得不半强制它。实际上,这是subset sum problem的更一般情况。这个问题是NP-complete。基本上,这意味着不知道是否存在可用于解决此类问题的多项式时间算法,并且获得有效解决方案的唯一方法是强制执行每个可能的解决方案并检查是否它适用于指定的问题。通常,强制解决方案需要指数时间,这对于大问题非常棘手。另一个有趣的事实是,现代密码算法使用NP-Complete难以处理作为其密文和加密的一部分。基本上,他们依赖于这样一个事实,即确定用于加密纯文本的正确密钥的唯一方法是检查所有可能的密钥,这是一个棘手的问题...特别是如果你使用128位加密!这意味着您必须检查results
种可能性,并假设计算速度适中的计算机,找到正确密钥的最坏情况时间将超过当前的宇宙年龄。关于密码学中的密钥破解,请查看这个很酷的Wikipedia post for more details in intractability。
事实上,NP完全问题非常受欢迎,并且已经有很多尝试来确定是还是不是多项式时间算法解决这类问题。一个有趣的特性是,如果你能找到一个能解决一个问题的多项式时间算法,你就会找到一个算法来解决这些问题。
克莱数学研究所有着名的Millennium Problems,如果你解决了他们网站上列出的任何问题,你将得到一百万美元。
此外,还有每个问题,2^128
!
http://www.quickmeme.com/img/76/762195e1666497074ede151e0cbeb39738a411d967572cbbe24b90cf8db6011f.jpg
NP问题是解决问题的七个问题之一。如果我没记错的话,到目前为止只解决了一个问题,这些问题首先在2000年向公众发布(因此是千年......)。所以......已经有14年了,只有一个问题已经解决了。不要让你气馁!如果你想投入一些时间并尝试解决其中一个问题,请做!
希望这足以让你入门。祝你好运!