PageRenderTime 62ms CodeModel.GetById 34ms RepoModel.GetById 1ms app.codeStats 0ms

/README.md

http://github.com/rafaelpiccolo/SubSetSum-Delphi
Markdown | 66 lines | 48 code | 18 blank | 0 comment | 0 complexity | 5d29ff9499bd54708238c899d4411c1b MD5 | raw file
  1. SubSetSum Algorithm
  2. -------------------
  3. _Delphi implementation_
  4. This is a polynomial algorithm to solve the SubSetSum problem (which is non-polynomial). The limitation is that it works for _positive numbers only_. The implementation is based on the [Wikipedia algorithm](http://en.wikipedia.org/wiki/Subset_sum_problem#Polynomial_time_approximate_algorithm).
  5. The algorithm is considered polynomial thanks to the trimming step. The main iteration can be devided in 2 steps:
  6. 0. New combinations are appended, increasing the size of the list
  7. 0. Every sum that exceeds the goal sum is discarded permanently
  8. In other words, the list keeps growing and shrinking, and that mantains the size of the list more or less the same. That is the reason it works for positive numbers only. Once the sum of a combination exceeds the goal, it is discarded. That could never be done if there were a possibility of decreasing the value (negative numbers).
  9. This algorithm was used to solve a financial problem in the project I was working. The software was 100% client-server database driven, so the data comes from a DataSet.
  10. *Notes:*
  11. 0. The wikipedia algorithm returns only a boolean. This implementation returns a string where:
  12. a) Each line is a possible combination
  13. b) Items in the line are separated by comma
  14. Ex: Return = 2 possible combinations:
  15. - 1st and 2nd item
  16. - 1st and 3rd item
  17. In this case, the return of the function would be the string:
  18. 1,2
  19. 1,3
  20. 0. This algorithm was written in Delphi 7 build 4453, no updates (unfortunately, but I had no choice on that). It looks like there is a bug in this version and I couldn't use the Double data type.
  21. (I had a case with two variables storing the same value: 7.2. The test: if Var1 = Var2 then... was returning False!!)
  22. I switched the data types to Currency as a work arround.
  23. 0. The original trimming step, excludes values that are greater than goal sum and also similar values (for instance: if item1 + item2 + item3 = 500 and item4 + item5 = 500, it just keeps one of them). That works only because the original result is a Boolean. This implementation returns a list with all possible combinations, so it must keep similar values. In this case, there's no point in sorting the list (won't search for similar values), the QuickSort function is commented out.
  24. 0. Note the difference between upper "S" (list with sums) and lower "s" (goal sum)
  25. Text from wikipedia:
  26. An approximate version of the subset sum would be: given a set of N numbers x1, x2, ..., xN and a number s, output
  27. - yes, if there is a subset that sums up to s;
  28. - no, if there is no subset summing up to a number between (1 - c)s and s for some small c > 0;
  29. - any answer, if there is a subset summing up to a number between (1 - c)s and s but no subset summing up to s.
  30. If all numbers are non-negative, the approximate subset sum is solvable in time polynomial in N and 1/c.
  31. The solution for subset sum also provides the solution for the original subset sum problem in the case where the numbers are small (again, for nonnegative numbers).
  32. If any sum of the numbers can be specified with at most P bits, then solving the problem approximately with c = 2-P is equivalent to solving it exactly.
  33. Then, the polynomial time algorithm for approximate subset sum becomes an exact algorithm with running time polynomial in N and 2P (i.e., exponential in P).
  34. The algorithm for the approximate subset sum problem is as follows:
  35. initialize a list S to contain one element 0.
  36. for each i from 1 to N do
  37. let T be a list consisting of xi + y, for all y in S
  38. let U be the union of T and S
  39. sort U
  40. make S empty
  41. let y be the smallest element of U
  42. add y to S
  43. for each element z of U in increasing order do
  44. //trim the list by eliminating numbers close to one another
  45. //and throw out elements greater than s
  46. if y + cs/N < z = s, set y = z and add z to S
  47. if S contains a number between (1 - c)s and s, output yes, otherwise no
  48. _PS: sorry for the poor english_ :)