Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 优化:带最大值的受限整数分区_Java_Math_Combinations_Mathematical Optimization_Integer Partition - Fatal编程技术网

Java 优化:带最大值的受限整数分区

Java 优化:带最大值的受限整数分区,java,math,combinations,mathematical-optimization,integer-partition,Java,Math,Combinations,Mathematical Optimization,Integer Partition,在下面的代码中,我计算受限整数partitionsAch编号在每个分区中只能出现一次,每个分区中有k个编号,每个编号等于或大于1,但不大于m。这段代码生成了大量的缓存值,因此它可以很快地从内存中释放出来 例如: 和=15,k=4,m=10预期结果为6 具有以下受限制的整数分区: 1,2,3,9,1,2,4,8,1,2,5,7,1,3,4,7,1,3,5,7,2,3,4,6 是否有避免/减少缓存的公式?或者我如何用k和m计算受限整数部分?您的密钥包含4个部分,因此哈希空间可能会达到这些部分的最大值

在下面的代码中,我计算受限整数partitionsAch编号在每个分区中只能出现一次,每个分区中有k个编号,每个编号等于或大于1,但不大于m。这段代码生成了大量的缓存值,因此它可以很快地从内存中释放出来

例如:

和=15,k=4,m=10预期结果为6

具有以下受限制的整数分区:

1,2,3,9,1,2,4,8,1,2,5,7,1,3,4,7,1,3,5,7,2,3,4,6


是否有避免/减少缓存的公式?或者我如何用k和m计算受限整数部分?

您的密钥包含4个部分,因此哈希空间可能会达到这些部分的最大值乘积的值。使用反向循环和零值作为自然限制,可以将关键点减少到3个部分

Python示例使用哈希表大小为N*K*M的内置功能lru_缓存


您的密钥包含4个部分,所以散列空间可能会达到这些部分的最大值乘积的值。使用反向循环和零值作为自然限制,可以将关键点减少到3个部分

Python示例使用哈希表大小为N*K*M的内置功能lru_缓存


您的问题可以转置,所以您只需要缓存中的3个键,启动的运行时就少了很多。不那么明显的密钥意味着更好地缓存一个比我聪明的人可能仍然会找到一个更便宜的解决方案

让我们以集合的形式查看分区。每组的元件应按升序排列。 当您将sum:=15,k:=4,m:=10的预期结果声明为[1,2,3,9]时,您已经隐式地这样做了;[1,2,4,8]

您为分区定义的限制包括:

每个集合正好有k个元素 最大m as元素 不同的价值观 非零正整数 区分的限制实际上有点麻烦,所以我们将取消它。 为此,我们需要稍微改变一下这个问题。因为集合中的元素是升序且不同的,我们知道,如果忽略总和必须是总和,则每个元素的最小值是升序,因此最小值是:[1,2,3,…]。 例如,如果m小于k,那么可能的分区数将始终为零。同样地,如果[1,2,3,…k]的和大于和,则结果也为零。我们在开始时排除这些边缘案例,以确保转换是合法的

让我们看一看“合法分割”的几何表示,以及我们想要如何变换它。我们有k列,m行,平方和用浅蓝色或深蓝色填充

红色和深蓝色的方块是不相关的,正如我们已经知道的,深蓝色的方块必须总是被填满,而红色的方块必须总是空的。因此,我们可以从计算中排除它们,并在继续进行时假设它们各自的状态。结果框显示在右侧。每一列都被它的位置“向下移动”,红色和深蓝色区域被切断。 我们现在有一个较小的整体框,一列现在可以为空,相邻列中的蓝色框数量可能相同

从算法上讲,转换现在的工作原理如下: 对于合法分区中的每个元素,我们从1开始减去它的位置。所以 [1,2,4,8]我们得到[0,0,1,4]。此外,我们必须相应地调整界限和m:

// from the sum, we subtract the sum of [1, 2, 3, ... k], which is (k * (k + 1) / 2)
sum_2 = sum - (k * (k + 1) / 2)

// from m we subtract the maximum position (which is k)
m_2 = m - k
现在,我们已经将分区问题转换为另一个分区问题,一个不受不同元素限制的问题!此外,这个分区可以包含元素0,而我们的原始分区不能包含元素0。我们保持内在的升序

现在我们需要稍微细化递归。如果我们知道元素是上升的,不一定是不同的,并且总是小于m_2,那么我们就把可能的元素限制在一个范围内。例如:

[0, 1, 3, n1, n2]
=> 3 <= n1 <= m_2
=> 3 <= n2 <= m_2
注意:我在这里使用ApacheCommon的三重类作为密钥,以避免显式密钥类的实现,但这不是运行时的优化,它只是保存代码

编辑:除了@MBo thank you发现的问题的修复之外,我还添加了一些快捷方式以达到相同的结果。该算法现在的性能甚至更好,缓存重用率也更好。也许这能满足你的要求

优化解释说,它们仅在上述问题转换后适用:

如果k>m,我们可以垂直“翻转”矩形,仍然可以得到相同的合法分区数。这将把一些“躺着”配置映射为“直立”配置,并减少不同键的总数量。 如果矩形中的正方形的数目大于“空格”的数目,我们可以把“空格”当作正方形来代替,这将把另一串键映射在一起。 如果sum您的问题可以转置,所以您只需要缓存中的3个键,启动的运行时就少了很多。不那么明显的密钥意味着更好地缓存一个比我聪明的人可能仍然会找到一个更便宜的解决方案

让我们以集合的形式查看分区。每组的元件应按升序排列。 当您将sum:=15,k:=4,m:=10的预期结果声明为[1,2,3,9]时,您已经隐式地这样做了;[1,2,4,8]

您为分区定义的限制包括:

每个集合正好有k个元素 最大m as元素 不同的价值观 非零正整数 区分的限制实际上有点麻烦,所以我们将取消它。 为此,我们需要稍微改变一下这个问题。因为集合中的元素是升序且不同的,我们知道,如果忽略总和必须是总和,则每个元素的最小值是升序,因此最小值是:[1,2,3,…]。 例如,如果m小于k,那么可能的分区数将始终为零。同样地,如果[1,2,3,…k]的和大于和,则结果也为零。我们在开始时排除这些边缘案例,以确保转换是合法的

让我们看一看“合法分割”的几何表示,以及我们想要如何变换它。我们有k列,m行,平方和用浅蓝色或深蓝色填充

红色和深蓝色的方块是不相关的,正如我们已经知道的,深蓝色的方块必须总是被填满,而红色的方块必须总是空的。因此,我们可以从计算中排除它们,并在继续进行时假设它们各自的状态。结果框显示在右侧。每一列都被它的位置“向下移动”,红色和深蓝色区域被切断。 我们现在有一个较小的整体框,一列现在可以为空,相邻列中的蓝色框数量可能相同

从算法上讲,转换现在的工作原理如下: 对于合法分区中的每个元素,我们从1开始减去它的位置。所以 [1,2,4,8]我们得到[0,0,1,4]。此外,我们必须相应地调整界限和m:

// from the sum, we subtract the sum of [1, 2, 3, ... k], which is (k * (k + 1) / 2)
sum_2 = sum - (k * (k + 1) / 2)

// from m we subtract the maximum position (which is k)
m_2 = m - k
现在,我们已经将分区问题转换为另一个分区问题,一个不受不同元素限制的问题!此外,这个分区可以包含元素0,而我们的原始分区不能包含元素0。我们保持内在的升序

现在我们需要稍微细化递归。如果我们知道元素是上升的,不一定是不同的,并且总是小于m_2,那么我们就把可能的元素限制在一个范围内。例如:

[0, 1, 3, n1, n2]
=> 3 <= n1 <= m_2
=> 3 <= n2 <= m_2
注意:我在这里使用ApacheCommon的三重类作为密钥,以避免显式密钥类的实现,但这不是运行时的优化,它只是保存代码

编辑:除了@MBo thank you发现的问题的修复之外,我还添加了一些快捷方式以达到相同的结果。该算法现在的性能甚至更好,缓存重用率也更好。也许这能满足你的要求

优化解释说,它们仅在上述问题转换后适用:

如果k>m,我们可以垂直“翻转”矩形,仍然可以得到相同的合法分区数。这将把一些“躺着”配置映射为“直立”配置,并减少不同键的总数量。 如果矩形中的正方形的数目大于“空格”的数目,我们可以把“空格”当作正方形来代替,这将把另一串键映射在一起。 如果sum另一种方法是使用约束解算器并将其配置为显示所有解决方案。这里是一种含微量锌的溶液:

include "globals.mzn";

int: sum = 15;
int: k = 4;
int: m = 10;

array[1..k] of var 1..m: numbers;

constraint sum(numbers) = sum;

constraint alldifferent(numbers);

constraint increasing(numbers);

solve satisfy;

另一种方法是使用约束解算器并将其配置为显示所有解决方案。这里是一种含微量锌的溶液:

include "globals.mzn";

int: sum = 15;
int: k = 4;
int: m = 10;

array[1..k] of var 1..m: numbers;

constraint sum(numbers) = sum;

constraint alldifferent(numbers);

constraint increasing(numbers);

solve satisfy;

显示一个小值的示例,以确保在问题公式中。允许零和吗?n,k的限制是什么?更新的问题,不允许零和。对sum,kOK没有限制,问题很清楚。你想要一个提示,还是一个完整的解决方案?我可以提供两者,但完整的解决方案需要一点时间来编写。你自己找出更大的部分可能也很有趣:一个有很好文档记录的提示会很好,但只有一个小的数学背景。展示一个小值的例子,以确保在问题公式中。允许零和吗?n,k的限制是什么?更新的问题,不允许零和。对sum,kOK没有限制,问题很清楚。你想要一个提示,还是一个完整的解决方案?我可以提供两者,但完整的解决方案需要一点时间

写下来。你自己弄清楚更大的部分可能也很有趣:一个有很好文档记录的提示会很好,但只有一个次要的数学背景。@TreffnonX这很有趣。有可能使用一些参数依赖性吗?实际上我错了。我的回答有缺陷。对于这个例子来说,它恰好起作用,但最终需要三个关键值。Sorry@TreffnonX很有趣。有可能使用一些参数依赖性吗?实际上我错了。我的回答有缺陷。对于这个例子来说,它恰好起作用,但最终需要三个关键值。对不起,很好。工作速度比我的版本快3-5倍,这是因为问题规模缩小更智能。谢谢,尽管你的版本更优雅!如果不先转换整个问题,它可能是不可能的…哎呀。。。隐马尔可夫模型。。我想我需要弄清楚,找到了。循环毕竟需要上升到m。在“楼梯”场景中,解决方案实际上是内部函数循环中的i=m。现在应该会产生正确的结果。谢谢您的再次检查!一个更聪明的人可以做哪些额外的优化?非常好。工作速度比我的版本快3-5倍,这是因为问题规模缩小更智能。谢谢,尽管你的版本更优雅!如果不先转换整个问题,它可能是不可能的…哎呀。。。隐马尔可夫模型。。我想我需要弄清楚,找到了。循环毕竟需要上升到m。在“楼梯”场景中,解决方案实际上是内部函数循环中的i=m。现在应该会产生正确的结果。谢谢您的再次检查!更聪明的人还可以进行哪些其他优化?请详细说明此处是Minizing网站的链接:请详细说明此处是Minizing网站的链接: