2

The algorithm is in Python. Seems correct to me, ideas how to prove it? And what would be its time complexity?

from bisect import bisect

# Implements the decision version of subset sum.
# The subset sum problem: given a set and a number find a subset of the set which sums to the given number.
# Inputs: an ordered list of integers xs, and an integer n which is the target sum.
def subset_sum(xs, n):
    if n < sum(filter(lambda x: x < 0, xs)):
        return False
    if n > sum(filter(lambda x: x >= 0, xs)):
        return False
    xs = xs[:]
    u = {}
    def rec(i, n):
        if not (i, n) in u:
            u[i, n] = False
            k = bisect(sums[:i], n)
            while k > 0:
                k -= 1
                u[i, n] = u[i, n] or sums[k] == n
                u[i, n] = u[i, n] or rec(k, n - sums[k])
        return u[i, n]    
    sums = xs
    return rec(len(sums), n)

It has been answered below that the above algorithm is exponential time.

That being so, I have a follow up question: Is the algorithm still exponential time if the rec sub-routine above is changed into the following?

def rec(i, n):
    if not (i, n) in u:
        u[i, n] = False
        k = bisect(sums[:i], n)
        k -= 1
        if k >= 0 and n >= sums[0]::
            u[i, n] = sums[k] == n or rec(k, n - sums[k]) or rec(k, n)
    return u[i, n]

The recurrence $T(i, n) = T(i - 1, n - 1) + log_2(i)$ is what I came up with for worst case running time. Maybe that's far off. But from that it seems it is $|S|log(|S|)$.

New information: I have been able to solve a problem instance involving a set of 8192 integers equal to the range (1, 9, ... 65537) and the target n = 65525 in one and a half minute on my laptop. The resulting list consists of 125 integers. That makes the algorithm (with the above changes applied) sub-exponential, certainly not $2^{|S|}$ . The time taken is for the search version which applies the decision version discussed here $|S|$ times.

Here is a link to the full source code of my test set-up:

http://codepad.org/5s5lkHAm

user72935
  • 71
  • 1
  • 7
  • 2
    What's your question? I don't see a question here. (Also, note that you can use LaTeX here to typeset mathematics and pseudocode in a more readable way. See here for a short introduction.) – D.W. Oct 04 '15 at 21:21
  • 2
    It is really hard to understand what your algorithm is supposed to do. Is there any meaning to the answers it finds? It seems like pre-calculating all sums would be a good idea (something that may make your algorithm linear in time). Also, you can get different answers depending on the order in which you try different values for i. Eg. you can first look for whether there is a sum equal to N and only after that try to do other manipulations on N... In other words, do you need to know the complexity of this algorithm, or maybe algorithm can be altered to work faster? – wvxvw Oct 04 '15 at 22:44
  • 2
    Thanks for the edit to explain what your question is. Now that I can see what your question is, have you looked at our reference question? (possible dup?) Also are you aware that subset sum is NP-hard? It is unlikely that you have found a polynomial-time algorithm for subset-sum, so you should be asking yourself whether that algorithm is correct. – D.W. Oct 05 '15 at 06:31
  • Yes I am aware of the np-hardness and of the unlikeliness of a exact polynomial time algorithm. – user72935 Oct 05 '15 at 06:37
  • I think the algorithm only works for non-negative integers, but this is not really a problem because such problem instances can be transformed into an instances of positive integers. – user72935 Oct 18 '15 at 09:46
  • The range of integers you used in your experiment is far too small to trigger the worst-case running time. You need to try a carefully constructed instance where the integers are just "right", for example an instance created by reduction from a 3-SAT formula that encodes integer factorization. – Tom van der Zanden Oct 19 '15 at 07:49

2 Answers2

2

Your algorithm is very similar to exhaustive search. It is basically the following approach:

In order to check whether some subset of $S$ sums to $n$, go over all $i \in S$ and check whether some subset of $S \setminus i$ sums to $n - i$.

The actual algorithm uses memoization and a few other optimizations. Its complexity is exponential in the size of $S$ (probably roughly $2^{|S|}$ in the worst case).

Yuval Filmus
  • 276,994
  • 27
  • 311
  • 503
0

I think you are looking for a subset sum problem. This video explains a DP solution to the problem.

https://www.youtube.com/watch?v=s6FhG--P7z0

  • 2
    Welcome! We discourage answers that contain nothing but a link because links often go out of date, which just leaves a blank answer. Please edit your answer to include al the necessary information: the link is fine as a source and somewhere to go for more information but it shouldn't be the whole answer, please. – David Richerby Oct 05 '15 at 15:50