不确定如何在数据生成算法中整合负数函数?

1 投票
1 回答
751 浏览
提问于 2025-04-17 12:51

我在控制一个数据生成算法的结果时遇到了一些麻烦。这个算法基本上是从一个列表中取值,然后列出所有不同的组合,以达到一个特定的总和。目前代码运行得还不错(还没测试过用很多变量的情况),但我需要让列表中可以包含负数。

我想我可以通过给可能的结果设置一个限制来解决这个问题,以防止出现无限的结果(比如如果苹果是2,橙子是-1,那么对于任何总和,都会有无限多的解,但如果我设定一个限制,那么结果就不会无限下去)。

下面是一个非常基础的代码,用来检测权重:

import math

data = [-2, 10,5,50,20,25,40]
target_sum = 100
max_percent = .8 #no value can exceed 80% of total(this is to prevent infinite solutions

for node in data:
    max_value = abs(math.floor((target_sum * max_percent)/node))
    print node, "'s max value is ", max_value

这是生成结果的代码(第一个函数生成一个表格,如果可能的话,第二个函数则组合出实际的结果。算法的详细信息和伪代码在这里:暴力算法能扩展吗?):

from collections import defaultdict

data = [-2, 10,5,50,20,25,40]
target_sum = 100
# T[x, i] is True if 'x' can be solved
# by a linear combination of data[:i+1]
T = defaultdict(bool)           # all values are False by default
T[0, 0] = True                # base case


for i, x in enumerate(data):    # i is index, x is data[i]
    for s in range(target_sum + 1): #set the range of one higher than sum to include sum itself
        for c in range(s / x + 1):  
            if T[s - c * x, i]:
                T[s, i+1] = True

coeff = [0]*len(data)
def RecursivelyListAllThatWork(k, sum): # Using last k variables, make sum
    # /* Base case: If we've assigned all the variables correctly, list this
    # * solution.
    # */
    if k == 0:
        # print what we have so far
        print(' + '.join("%2s*%s" % t for t in zip(coeff, data)))
        return
    x_k = data[k-1]
    # /* Recursive step: Try all coefficients, but only if they work. */
    for c in range(sum // x_k + 1):
       if T[sum - c * x_k, k - 1]:
           # mark the coefficient of x_k to be c
           coeff[k-1] = c
           RecursivelyListAllThatWork(k - 1, sum - c * x_k)
           # unmark the coefficient of x_k
           coeff[k-1] = 0

RecursivelyListAllThatWork(len(data), target_sum)

我的问题是,我不知道该在哪里或如何将我的限制代码整合到主代码中,以便限制结果并允许负数的存在。当我把负数添加到列表中时,它会显示出来,但不包括在输出中。我觉得这可能是因为它没有被添加到表格中(第一个函数),我不确定该如何添加它(同时还保持程序的结构,以便我可以用更多变量进行扩展)。

提前感谢,如果有什么不清楚的地方,请告诉我。

补充:这有点不相关(如果影响了问题就忽略它),但既然你已经在看代码,有没有办法让我在运行这个代码时利用我机器上的两个CPU?现在运行时只使用了一个CPU。我知道在Python中并行计算的技术方法,但不太确定如何逻辑上并行化这个算法。)

1 个回答

3

你可以通过改变对c的两个循环来限制结果,从

for c in range(s / x + 1):  

改成

max_value = int(abs((target_sum * max_percent)/x))
for c in range(max_value + 1):

这样可以确保最终答案中的任何系数都是一个整数,范围在0到max_value之间,包括这两个值。

如果你想简单地添加负值,可以把对s的循环从

for s in range(target_sum + 1):

改成

R=200 # Maximum size of any partial sum
for s in range(-R,R+1):

注意,如果你这样做,你的解决方案会有一个额外的限制。这个新限制是每个部分加权和的绝对值必须小于等于R。

(你可以把R设得大一些,以避免这个限制减少解决方案的数量,但这样会让执行速度变慢。)

完整的代码看起来是:

from collections import defaultdict

data = [-2,10,5,50,20,25,40]

target_sum = 100
# T[x, i] is True if 'x' can be solved
# by a linear combination of data[:i+1]
T = defaultdict(bool)           # all values are False by default
T[0, 0] = True                # base case

R=200 # Maximum size of any partial sum
max_percent=0.8 # Maximum weight of any term

for i, x in enumerate(data):    # i is index, x is data[i]
    for s in range(-R,R+1): #set the range of one higher than sum to include sum itself
        max_value = int(abs((target_sum * max_percent)/x))
        for c in range(max_value + 1):  
            if T[s - c * x, i]:
                T[s, i+1] = True

coeff = [0]*len(data)
def RecursivelyListAllThatWork(k, sum): # Using last k variables, make sum
    # /* Base case: If we've assigned all the variables correctly, list this
    # * solution.
    # */
    if k == 0:
        # print what we have so far
        print(' + '.join("%2s*%s" % t for t in zip(coeff, data)))
        return
    x_k = data[k-1]
    # /* Recursive step: Try all coefficients, but only if they work. */
    max_value = int(abs((target_sum * max_percent)/x_k))
    for c in range(max_value + 1):
       if T[sum - c * x_k, k - 1]:
           # mark the coefficient of x_k to be c
           coeff[k-1] = c
           RecursivelyListAllThatWork(k - 1, sum - c * x_k)
           # unmark the coefficient of x_k
           coeff[k-1] = 0

RecursivelyListAllThatWork(len(data), target_sum)

撰写回答