Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
608 views
in Technique[技术] by (71.8m points)

python - How to find all combinations that sum up to at most a constant?

Let P=[P1, P2, ..., Pk] be k positive integers and let T be a positive integer. I would like to generate all combinations that sum up to at most T. That is, sum(x[i] * P[i] for i in 1:k) <= T where x[i] = 1 iff i is chosen in the combination.

Example.

Let P=[1, 2, 3] and T=4. The combinations should be:

1
2
3
1, 2
1, 3
2, 3

So only the combination 1, 2, 3 cannot be there because 1 + 1 + 3 = 5 > 4.

I thought of generating all combinations first and then start verifying the constraint sum(x[i] * P[i] for i in 1:k) <= T. But this approach could be more time consuming than other clever approaches. How can we generate such combinations?

NB. If you know any function in Python or Matlab that can be used to generate such combinations, you can provide it.

Thank you.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is like the subset sum problem (mentioned in the comments), except that's about finding numbers summing equal to a target. You want to find numbers summing to a total less-than-or-equal to the target.

Nonetheless, a similar approach with dynamic programming can be used:

def subset_sum(vals, target=0):
    sums = {0: [()]}  # key=sum, value=list of subsets for the sum
    if target in sums:
        yield from sums[target]  # annoying base case
    for val in vals:
        items = sums.items()  # don't change dict size during iteration
        sums = dict(items)
        for prev_sum, prev_subsets in items:
            sum_ = prev_sum + val
            subsets = [s + (val,) for s in prev_subsets]
            sums[sum_] = sums.get(sum_, []) + subsets
            if sum_ <= target:
                yield from subsets

Demo:

>>> for subset in subset_sum([1, 2, 3], target=4):
...     print(*subset, sep='+')
...     
1
2
1+2
3
1+3

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...