set = SubSet([23603, 6105, 5851, 19660, 8398, 8545, 14712], 37760)
= set.solve_LLL()
X assert np.dot(X, [23603, 6105, 5851, 19660, 8398, 8545, 14712]) == 37760
5 SubSet Sum
5.1 Introduction
Given a set of integers \(S\) and an integer \(M\), we want to find the biggest subset sum of \(S\) such that the sum of its elements does not exceed \(M\).
The associated decision problem is to find a subset sum that is strictly equal to \(M\), the existence of such a set is known to be NP-Hard.
Perhaps, there exist two heuristics for the above problem: LLL and a dynamic programming approach.
Remark : the general SubSet Sum problem allows \(S\) to be a MultiSet.
5.2 Code
Let \(S\) be a python set of integers and \(M\) the target value.
= set(<values>)
S = <target_value> M
To find a solution to the subset sum problem, create a subset and solve it.
= SubSet(S, M)
problem = problem.solve_dynamic_prog()
dynamic_solution = problem.solve_LLL() LLL_solution
- Dynamic
solve_dynamic_prog
returns a couple (target, chosen elemements), as if there is no solution to the problem, it will give the closest to the target.
- LLL
solve_LLL
returns a vector corresponding to the chosen elements
Alternative constructors :
- Concatenantion :
SubSet(S + M)
- Random example :
SubSet.generate_random_low_density_subset_problem(number_of_elements, density)
- If you dont specify parameters, the number of elements will be a random number between 0 and 20, and the density will be 0.5
5.2.1 Examples
5.2.1.1 LLL algorithm
To perform a single, precise test:
X = [0, 1, 0, 0, 1, 1, 1]
To parameterize set length and density, and study the algorithm’s performance:
= 0
solved_count = 0
unsolved_count = 0
total_density = 4
n
for i in range(1000):
= SubSet.generate_random_low_density_subset_problem(n,density=0.2)
subset_problem = subset_problem.solve_LLL()
X = subset_problem.density()
density
if X is not None:
+= 1
solved_count += density
total_density else:
+= 1
unsolved_count
= total_density / solved_count if solved_count > 0 else 0 avg_density
Benchmark Table: n = 4
Number of problems solved: 555
Number of problems unsolved: 445
Average density: 0.19783403475538835
The test above can be modified in the tests/subset_sum.py file.
5.2.1.2 Dynamic programming
= SubSet([23603, 6105, 5851, 19660, 8398, 8545, 14712], 37760)
problem
= problem.solve_dynamic_prog() dynamic_solution
Dynamic solution : (37760, [6105, 8398, 8545, 14712])