I've got a sparse power set for an input (ie some combos have been pre-excluded). Each entry in the power set has a certain score. I want to find the combination that covers all points and maximizes the overall score.
For example, let's say the input is generated as follows:
function powerset(ary) {
var ps = [[]];
for (var i = 0; i < ary.length; i++) {
for (var j = 0, len = ps.length; j < len; j++) {
ps.push(ps[j].concat(ary[i]));
}
}
return ps;
}
function generateScores() {
var sets = powerset([0, 1, 2, 3]);
sets.pop() //remove the last entry to make it "sparse"
var scores = {};
for (var i = 1; i < sets.length; i++) { //skip 0-len
var set = sets[i];
var val = 0;
for (var j = 0; j < set.length; j++) {
val |= (1 << set[j]);
}
scores[val] = ~~Math.pow(((Math.random()+1)*4),set.length);
}
return scores;
}
var scores = generateScores();
And the output would look like this:
{
"1": 7,
"2": 4,
"3": 36,
"4": 5,
"5": 32,
"6": 50,
"7": 84,
"8": 4,
"9": 30,
"10": 50,
"11": 510,
"12": 47,
"13": 73,
"14": 344,
}
Since order doesn't matter, I can convert the combinations into a bitmask & use that as the key. So to read the table: a key of "3" is 011
is base 2, which means linking 0-1 yields a score of 36, whereas 0 individually + 1 individually yields a total sum of 11, therefore the linkage, 0-1
, is greater than the sum of its parts 0,1
.
In doing so, I've reduced this to a weighted subset sum problem, where the goal is to find every combination that sums to 15 (the equivalent of 1111
in base 2) & then take the max. This is where I'm stuck. I tried using dynamic programming, but due to the randomness, I don't see how I can make any reductions. For example, 1-2
may be better than 1,2
(in the above table, "3" has a higher score than "1" + "2"). However 1-3,2
could be better than 1-2,3
or 1-2-3
).
How might I efficiently find the optimal mix? (brute force isn't feasible). For this example, the solution would be "11" + "4", for a total of 515.