Last active
October 5, 2017 23:09
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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