Advertisement
Guest User

Untitled

a guest
Apr 28th, 2016
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.40 KB | None | 0 0
  1. import numpy
  2. import scipy.signal
  3.  
  4. # to test, try the following
  5. # > import random
  6. # > xs = list(set(random.sample(xrange(10000), 500)))
  7. # > subset_sums_up_to_u(xs,50000) == naive_subset_sums_up_to_u(xs,50000)
  8.  
  9. def naive_subset_sums_up_to_u(xs,u):
  10. sums = set([0])
  11. for x in xs:
  12. sums2 = set(sums)
  13. for y in sums:
  14. if x+y<=u :
  15. sums2.add(x+y)
  16. sums = sums2
  17. return sums
  18.  
  19. def subset_sums_up_to_u(xs,u):
  20. epsilon = 0.0001 # account for floating error
  21. # taking Minkowski sum of two sets, such that
  22. # the sets are contained in the union of intervals
  23. # [i*lc, i*uc] for all 0<=i<=k
  24. def smart_minkowski(A,B,k,lc,uc):
  25. n = min(1+u//lc,k)
  26. m = n*(uc-lc)
  27. gap = lc
  28.  
  29. # in this case, we can be dumb and do normal minkowski
  30. # which is when the first coordinate is 0.
  31. if (lc<=m) or (m>=u):
  32. n = 0
  33. m = min(max(A)+max(B)+1,u)
  34. gap = u+1 # this make sure first coordinate is always 0
  35.  
  36. AA = numpy.zeros((n+1,m+1))
  37. BB = numpy.zeros((n+1,m+1))
  38.  
  39. for x in A:
  40. (i,j) = divmod(x, gap)
  41. AA[i,j] = 1
  42. for x in B:
  43. (i,j) = divmod(x, gap)
  44. BB[i,j] = 1
  45. CC = scipy.signal.fftconvolve(AA, BB)
  46. C = []
  47.  
  48. # Find all the non-zeros
  49. (na,nb) = CC.shape
  50. for i in xrange(n+1):
  51. for j in xrange(m+1):
  52. if CC[i,j]>epsilon and i*lc+j<=u:
  53. C.append(i*lc+j)
  54. return set(C)
  55.  
  56. # taking minkowski sum of two sets with some extra information
  57. def minkowski((A,ka,la,ua),(B,kb,lb,ub)):
  58. lc = min(la,lb)
  59. uc = max(ua,ub)
  60. kc = ka+kb
  61. C = smart_minkowski(A,B,kc,lc,uc)
  62. return (C,kc,lc,uc)
  63.  
  64. # combine a list, where each element of the list is
  65. # (set of subset sums, number of generators, lower bound of generators, upper bound of generators)
  66. def combine(xs):
  67. if len(xs)==1:
  68. return xs[0]
  69. evens = xs[::2]
  70. odds = xs[1::2]
  71. extra = []
  72. if len(xs)%2 != 0:
  73. extra = [xs[-1]]
  74.  
  75. ys = [minkowski(A,B) for (A,B) in zip(evens,odds)] + extra
  76. return combine(ys)
  77.  
  78. # The elements in xs are called generators
  79. # Assume the input is actually a set
  80. ys = [(set([0,x]),1,x,x) for x in sorted(xs) if x<=u]
  81. # output is list of subset sums
  82. return combine(ys)[0]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement