Karp reduction from PARTITION to SUBSET SUM - complexity-theory

PARTITION: Given a set of positive integers A={a_1,...,a_n} does there exist a subset of A with sum equal to the sum of it's complement?
SUBSET SUM: Given a set of positive integers A={a_1,...,a_n} and another positive integer B, does there exist a subset of A such that it's sum is equal to B?
I was trying to prove that if PARTITION is NP-complete then SUBSET SUM is also NP-complete, by reducing PART to SSUM.
My solution was: let A={a1,...,an} be a set of positive integers. Then if A when fed into PART gives the solution I={k1,...,km} (where k_i are the indices of the members of the solution subset), then we construct A'={a1,...an,S} where S is the sum of {a_k1,a_k2,...,a_km}. A' is a solution to SSUM.
My problem with this is that this goes only one way, meaning that we can't show that given A' then A is a solution to PART. Is this a problem? and how could i modify the proof to cover it?

Partition to SubsetSum is actually easier than what you've done here.
If Partition is Satisfied that means that there are some subsets P1 and P2 such that sum(P1) = sum(P2) correct? Because sum(P1) + sum(P2) = Sum(A), which means that sum(P1) = sum(P2) = (1/2)sum(A)
We don't even need to construct an A' for subset sum. Just set A' = A and the target sum = (1/2)sum(A). It should be clear that this is the exact same problem as Partition with almost no abstraction.
In other words Partition is always just subset sum where target sum = (1/2)sum(A)

Related

Integer partition weighted minimum of maximum

Given a non-negative integer n and a positive real weight vector w with dimension m, partition n into a length-m non-negative integer vector that sums to n (call it v) such that max w_iv_i is the smallest, that is, we want to find the vector v such that the maximum of element-wise product between w and v is the smallest. There maybe several partitions, and we only want the smallest value of max w_iv_i among all possible v.
Seems like this problem can use a greedy algorithm to solve. From a target vector v for n-1, we add 1 to each entry, and find the minimum among those m vectors. but I don't think it's correct. The intuition is that it might add "over" the minimum. That is, there exists another partition not yielded by the add 1 procedure that falls in between the "minimum" of n-1 produced by this greedy algorithm and that of n produced by this greedy algorithm. Can anyone prove if this is correct or incorrect?
If you already know the maximum element-wise product P, then you can just set vi = floor(P/wi) until you run out of n.
Use binary search to find the smallest possible value of P.
The largest guess you need to try is n * min(w), so that means testing log(n) + log(min(w)) candidates, spending O(m) time for each test, or O(m*(log n + log(min(w))) all together.

Count all subsets with given sum - Java

I have an array list of distinct positive integers representing a set L, and an integer S. What's the fastest way to count all subsets of L which have the sum of their elements equal to S, instead of iterating over all subsets and just checking if each subset's sum equal is equal to S?
This can be solved in O(NS) using a simple dynamic programming approach, similar to knapsack problem. Let's for each Q and for each i solve the following problem: how many subsets of first i elements of L exist so that their sum is equal to Q. Let us denote the number of such subsets C[i,Q].
Obviously, C[0,0]=1 and C[0,Q]=0 for Q!=0. (Note that i=0 denotes first 0 elements, that is no elements.)
For a bigger i we have two possibilities: either the last available element (L[i-1]) is taken to our set, then we have C[i-1, Q-L[i-1]] such sets. Either it is not taken, then we have C[i-1, Q] such sets. Therefore, C[i,Q]=C[i-1, Q-L[i-1]]+C[i-1, Q]. Iterating over i and Q, we calculate all Cs.
Note that if all elements in L are non-negative, then you can solve the problem only for non-negative Qs, and the first term disappears if Q<L[i-1]. If negative elements are allowed, then you need to consider negative Qs too.

Algorithm to approximate an optimal solution for an integer allocation pro­blem

I have the following problem:
Given a set of sums of variables like { a + b, b + c, c + d, a + a + d, b }, find positive integer values for the variables such that all sums are distinct and the highest sum is as small as possible.
Is there an algorithm to find or approximate a solution to this kind of problems?
I have created a possible solution and an implementation in C#. Hope it is what you need. It would be nice if someone proves it is correct/incorrect but it works and results look correct. The details on theory are below. Its complexity is something about O(N!*M^3*Log2(N)) where N is number of variables and M is number of summands all sums.
BTW, for your example it gives this result:
c=3, a=2, d=2, b=1
{a+b=3; b+c=4; c+d=5; a+a+d=6; b=1}
max=6
UPDATE
Theory of the algorithm.
Assume the variables are ordered, e.g. a >= b >= c >= ....
Lets say a set of sums is a Bag if all sums in it are distinct.
All sums in a Bag can be divided into two groups: sums that do not contain variable a and sums that do contain. Lets call the first group as Head and the second as Tail.
Note that both are Bags because they contain distinct sums.
We can subtract a from each sum in Tail so that all sums remain distinct (i.e. the Tail is still a Bag). This way we get two bags both without variable a.
Similar way we exclude variable b from two Bags and get four Bags.
This operation we repeat for each variable until we get sums with last variable (lets say it is d). The smallest value of d is 1.
After that we can return to the previous step and include variable c in sums from tails. Remember that we have many pairs Head-Tail and need to join them back. To do that we add c to each sum in each Tail so that sums from the Tail have to be distinct from the Head.
How to calculate c? The idea is to calculate its invalid values and then take the smallest value that is not invalid and also is equal or greater than d. Calculating invalid values is trivial, using condition HeadSum != TailSum + c => c != HeadSum - TailSum. For each combination of tail sum and head sum we get all invalid values.
Collapsing all pairs Head-Tail back and calculating each variable we get the solution for the case a >= b >= c >= d.
Then we calculate a solution for each permutation of a >= b >= c >= d and find the smallest one.
PS It would be great if someone provide better solution because I think my algorithm is somewhat of approximation (but a good approximation) or even better to prove it.
The worst thing is N! complexity because of permutations and I still have no idea how to get rid of it.

Partitioning a list of integers to minimize difference of their sums

Given a list of integers l, how can I partition it into 2 lists a and b such that d(a,b) = abs(sum(a) - sum(b)) is minimum. I know the problem is NP-complete, so I am looking for a pseudo-polynomial time algorithm i.e. O(c*n) where c = sum(l map abs). I looked at Wikipedia but the algorithm there is to partition it into exact halves which is a special case of what I am looking for...
EDIT:
To clarify, I am looking for the exact partitions a and b and not just the resulting minimum difference d(a, b)
To generalize, what is a pseudo-polynomial time algorithm to partition a list of n numbers into k groups g1, g2 ...gk such that (max(S) - min(S)).abs is as small as possible where S = [sum(g1), sum(g2), ... sum(gk)]
A naive, trivial and still pseudo-polynomial solution would be to use the existing solution to subset-sum, and repeat for sum(array)/2to 0 (and return the first one found).
Complexity of this solution will be O(W^2*n) where W is the sum of the array.
pseudo code:
for cand from sum(array)/2 to 0 descending:
subset <- subsetSumSolver(array,cand)
if subset != null:
return subset
The above will return the maximal subset that is lower/equals sum(array)/2, and the other part is the complement for the returned subset.
However, the dynamic programming for subset-sum should be enough.
Recall that the formula is:
f(0,i) = true
f(x,0) = false | x != 0
f(x,i) = f(x-arr[i],i-1) OR f(x,i-1)
When building the matrix, the above actually creates you each row with value lower than the initial x, if you input sum(array)/2 - it's basically all values.
After you generate the DP matrix, just find the maximal value of x such that f(x,n)=true, and this is the best partition you can get.
Complexity in this case is O(Wn)
You can phrase this as a 0/1 integer linear programming optimization problem. Let wi be the ith number, and let xi be a 0/1 variable which indicates whether wi is in the first set or not. Then you want to minimize sum(xi wi) - sum((1 - xi) wi) subject to
sum(xi wi) >= sum((1 - xi) wi)
and also subject to all xi being 0 or 1. There has been a lot of research into optimizing 0/1 linear programming solvers. For large total sum W this may be an improvement over the O(W n) pseudo-polynomial time algorithm presented because the W factor is scary.
My first thought is to:
Sort list of integers
Create two empty lists A and B
While iterating from biggest integer to smallest integer...add next integer to the list with the smallest current sum.
This is, of course, not guaranteed to give you the best result but you can bound the result it will give you by the size of the biggest integer in your list

Sum Combination List

I need an algorithm for this problem:
Given a set of n natural numbers x1,x2,...,xn, a number S and k. Form the sum of k numbers picked from the set (a number can be pick many times) with sum S.
Stated differently: List every possible combination for S with Bounds: n<=256, x<=1000, k<=32
E.g.
problem instance: {1,2,5,9,11,12,14,15}, S=30, k=3
There are 4 possible combinations
S=1+14+15, 2+14+14, 5+11+15, 9+9+12.
With these bounds, it is unfeasible to use brute force but I think of dynamic programming is a good approach.
The scheme is: Table t, with t[m,v] = number of combinations of sum v formed by m numbers.
1. Initialize t[1,x(i)], for every i.
2. Then use formula t[m,v]=Sum(t[m-1,v-x(i)], every i satisfied v-x(i)>0), 2<=m<=k.
3. After obtaining t[k,S], I can trace back to find all the combinations.
The dilemma is that t[m,v] can be increase by duplicate commutative combinations e.g., t[2,16]=2 due to 16=15+1 and 1+15. Furthermore, the final result f[3,30] is large, due to 1+14+15, 1+15+14, ...,2+14+14,14+2+14,...
How to get rid of symmetric permutations? Thanks in advance.
You can get rid of permutations by imposing an ordering on the way you pick elements of x. Make your table a triple t[m, v, n] = number of combinations of sum v formed by m numbers from x1..xn. Now observe t[m, v, n] = t[m, v, n-1] + t[m-1, v-x_n, n]. This solves the permutation problem by only generating summands in reverse order from their appearance in x. So for instance it'll generate 15+14+1 and 14+14+2 but never 14+15+1.
(You probably don't need to fill out the whole table, so you should probably compute lazily; in fact, a memoized recursive function is probably what you want here.)

Resources