Skip to content

Instantly share code, notes, and snippets.

@plopp
Last active October 5, 2017 23:09
Show Gist options
  • Save plopp/12a1f261b30f4c183ea0b8d823693fd0 to your computer and use it in GitHub Desktop.
Save plopp/12a1f261b30f4c183ea0b8d823693fd0 to your computer and use it in GitHub Desktop.
Loose perfect sum algorithm for detecting electric loads that are probably running given a power sum and known power consumptions of appliances.
//Based on work from: http://www.geeksforgeeks.org/perfect-sum-problem-print-subsets-given-sum/
let c = 0.2; //Looseness in percent of current power consumtion
let s = 600; //Current power consumtion
let dp; //Solution tree
let appliances = ["Lights", "Fridge/Freezer standby", "Tap water standby", "Tap water heating on", "Pipe anti-freeze", "Fridge/Freezer on", "Modem/Electronics/etc"];
let always_on = [false, false, false, false, false, true, false];
//Known appliance power from measurements.
let x = [60, 200, 50, 300, 62, 201, 15];
//Subtract known always on power
always_on_arr = x.filter((o, i) => {
return always_on[i];
});
s = s - always_on_arr.reduce(function (accumulator, currentValue) {
return accumulator + currentValue;
});
let A = printAllSubsets(x, x.length, s);
let B = printAllSubsets(x, x.length, Math.round(s * (1 + c)));
let res = [...new Set([...A, ...B, ...always_on_arr])];
//Run
console.log("Appliances probably on:");
console.log(res.map(o => appliances[x.indexOf(o)]))
// A recursive function to print all subsets with the
// help of dp[][]. Vector p[] stores current subset.
function printSubsetsRec(arr, i, sum, p) {
// If we reached end and sum is non-zero. We print
// p[] only if arr[0] is equal to sun OR dp[0][sum]
// is true.
if (i === 0 && sum !== 0 && dp[0][sum]) {
p.push(arr[i]);
//console.log("1",p);
return p;
}
// If sum becomes 0
if (i == 0 && sum == 0) {
//console.log("2",p);
return p;
}
// If given sum can be achieved after ignoring
// current element.
if (dp[i - 1][sum]) {
// Create a new vector to store path
//vector<int> b = p;
b = p.slice();
return printSubsetsRec(arr, i - 1, sum, b);
}
// If given sum can be achieved after considering
// current element.
if (sum >= arr[i] && dp[i - 1][sum - arr[i]]) {
p.push(arr[i]);
return printSubsetsRec(arr, i - 1, sum - arr[i], p);
}
}
// Prints all subsets of arr[0..n-1] with sum 0.
function printAllSubsets(arr, n, sum) {
if (n == 0 || sum < 0)
return;
// Sum 0 can always be achieved with 0 elements
dp = new Array(n);
for (let i = 0; i < n; ++i) {
dp[i] = new Array(sum + 1);
dp[i][0] = true;
}
// Sum arr[0] can be achieved with single element
if (arr[0] <= sum)
dp[0][arr[0]] = true;
// Fill rest of the entries in dp[][]
for (let i = 1; i < n; ++i)
for (let j = 0; j < sum + 1; ++j)
dp[i][j] = (arr[i] <= j) ? dp[i - 1][j] ||
dp[i - 1][j - arr[i]]
: dp[i - 1][j];
if (!dp[n - 1][sum]) {
//Find closest subsets
//Search forward within c times sum s:
search_length = Math.round(c * s);
search_offset = 0;//Math.round(search_length/2.0);
for (let i = 1; i < search_length; i++) {
if (sum + search_offset - i < 0) break; //nothing was found
else if (dp[n - 1][sum - i]) {
//Found subset with new sum
return printAllSubsets(arr, n, sum + search_offset - i);
}
}
}
// Now recursively traverse dp[][] to find all
// paths from dp[n-1][sum]
let p = new Array();
return printSubsetsRec(arr, n - 1, sum, p);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment