I am trying to solve a problem with combinations:
I receive an array of products which include an availability percentage and have to calculate the most efficient and cheapest combination that add up to get a given availability percentage. There are some rules that make it harder.
Given the following problem:
[{
"name": "network 1",
"availability": 0.5,
"cost": 20,
},
{
"name": "network 2",
"availability": 0.75,
"cost": 30,
}]
I need to find the most efficient and cheap combination using the following equation to calculate the availability:
1 - (1 - availability A) * (1 - availability B)… * (1 - availability n)
Requirements/rules:
- The total availability is 0.9999 (i.e 99.99%)
- Repetition is allowed
- Should be the cheapest combination
cost
-wise
At the end it should print the items used to get to the solution as well as the total cost.
I have tried solving it using the bounded/unbounded knapsack problem as well as min cost path and subset sum, but couldn't figure out a solution. Also at the end it only prints the supposed solution, but I don't know how to get the items used to get to that solution.
At the end I went back to the unbounded knapsack since it has repetitions and I got this so far:
private static int max(int i, int j) {
return (i > j) ? i : j;
}
private static int unboundedKnapsack(int W, int n, List<Long> val, List<Long> wt) {
int dp[] = new int[W + 1];
for(int i = 0; i <= W; i++){
for(int j = 0; j < n; j++){
if(wt.get(j) <= i){
dp[i] = max(dp[i], Math.toIntExact(dp[(int) (i - wt.get(j))] + val.get(j))); // TODO: can't figure out how to implement 1 - (1 - availability A) * (1 - availability B)… * (1 - availability n) instead.
}
}
}
return dp[W];
}
public static void main(String[] args) {
String problem = "" +
"[{\"function\":\"Server\", " +
"\"name\":\"server 1\", " +
"\"availability\":5, " +
"\"cost\":10 }, " +
"{\"function\":\"Server\", " +
"\"name\":\"server 2\", " +
"\"availability\":10, " +
"\"cost\":30 }, " +
"{\"function\":\"Server\", " +
"\"name\":\"server 3\", " +
"\"availability\":15, " +
"\"cost\":20 }] ";
JSONParser parser = new JSONParser();
try{
Object obj = parser.parse(problem);
JSONArray array = (JSONArray) obj;
List<Long> valArray = new ArrayList<>();
List<Long> wtArray = new ArrayList<>();
for (Object value : array) {
JSONObject o = (JSONObject) value;
Long cost = (Long) o.get("cost");
valArray.add(cost);
Long availability = (Long) o.get("availability");
wtArray.add(availability);
}
int W = 100; // TODO: should be the required availability i.e 0.9999. Can't figure out how to get it to work with double values
int n = valArray.size();
System.out.println("cost: " + unboundedKnapsack(W, n, valArray, wtArray));
} catch(ParseException pe) {
System.out.println("position: " + pe.getPosition());
System.out.println(pe);
}
}
Currently I only get the cost as output. So if you run the code ubove you should get:
cost: 300
However the output I'm trying to achieve is something like this:
availability: 0.9999
items: server 1, server 2...
cost: 300
If anyone has an idea of an algorithm to fix this, I would really appreciate it.