Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package de.ohnes.AlgorithmicComponents.Approximation;

import de.ohnes.util.Instance;

public class TrivialLowerBound implements Approximation {

@Override
public double approximate(Instance I) {

double totalWork = 0;

for(int i = 0; i < I.getN(); i++) {
totalWork += Math.min(I.getJob(i).getSequentialProcessingTime(), I.getJob(i).getProcessingTime(1));
}

return totalWork / (I.getM() + I.getL());

}

}
137 changes: 30 additions & 107 deletions src/main/java/de/ohnes/AlgorithmicComponents/Knapsack/MDKnapsack.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package de.ohnes.AlgorithmicComponents.Knapsack;

import java.util.HashMap;
import java.util.List;

import de.ohnes.util.Job;
Expand All @@ -24,15 +23,18 @@ public class MDKnapsack {
* @param smallJobs
* @param seqJobs
*/
public void solve(List<MDKnapsackItem> smallItems, List<MDKnapsackItem> bigItems, Vector3D capacity, List<Job> shelf1, List<Job> shelf2, List<Job> smallJobs, List<Job> seqJobs) {

public boolean solve(List<MDKnapsackItem> smallItems, List<MDKnapsackItem> bigItems, Vector3D capacity, List<Job> shelf1, List<Job> shelf2, List<Job> smallJobs, List<Job> seqJobs) {
List<MDKnapsackItem> items = new java.util.ArrayList<>() {{
addAll(smallItems);
addAll(bigItems);
}};
int b = bigItems.size();
int s = smallItems.size();
int n = s + b;
//TODO: reduce 3rd dimension
Double[][][][] dp = new Double[b+1][capacity.get(0)+1][capacity.get(2)+1][capacity.get(1)+1];
Double[][][][] dp = new Double[n+1][capacity.get(0)+1][capacity.get(1)+1][capacity.get(2)+1];


//initialization
for (int x1 = 0; x1 < dp[0].length; x1++) {
for (int x2 = 0; x2 < dp[0][x1].length; x2++) {
Expand All @@ -41,21 +43,21 @@ public void solve(List<MDKnapsackItem> smallItems, List<MDKnapsackItem> bigItems
}
}
}

//acutal dp
// fist solve the knapsack problem for the big items
for (int i = 1; i <= bigItems.size(); i++) {
Integer[] costs = bigItems.get(i-1).getCosts();
Vector3D[] weights = bigItems.get(i-1).getWeights();
for (int i = 1; i <= items.size(); i++) {
boolean placed = false;
Integer[] costs = items.get(i-1).getCosts();
Vector3D[] weights = items.get(i-1).getWeights();
for (int x1 = 0; x1 < dp[0].length; x1++) {
for (int x2 = 0; x2 < dp[0][x1].length; x2++) {
for (int x3 = 0; x3 < dp[0][x1][x2].length; x3++) {
double minVal = Double.MAX_VALUE;
for (int c = 0; c < costs.length; c++) { //for the choices
Vector3D w = weights[c];
int x1_ = x1 - w.get(0);
int x2_ = x2 - w.get(2);
int x3_ = x3 - w.get(1);
int x2_ = x2 - w.get(1);
int x3_ = x3 - w.get(2);
if (x1_ < 0 || x2_ < 0 || x3_ < 0) {
continue;
}
Expand All @@ -68,118 +70,38 @@ public void solve(List<MDKnapsackItem> smallItems, List<MDKnapsackItem> bigItems
}
if (minVal < Double.MAX_VALUE) {
dp[i][x1][x2][x3] = minVal;
placed = true;
}
}
}
}
}

//discard 2nd constraint, as the small items don't change it.

Double[][][] dp2 = new Double[s+1][capacity.get(0)+1][capacity.get(2)+1];
HashMap<String, Integer> map = new HashMap<>(); // a map to remember the position of the best solution for the big items
//initialization
for (int x1 = 0; x1 < dp[0].length; x1++) {
for (int x2 = 0; x2 < dp[0][x1].length; x2++) {
// find the best solution for the big items
// dp2[0][x1][x2] = Arrays.stream(dp[bigItems.size()][x1][x2]).filter(d -> d != null).min(Double::compare).orElse(null);
// remember the position of best solution
for (int i = 0; i < dp[b][x1][x2].length; i++) {
if (dp[b][x1][x2][i] != null) {
String key = x1 + "," + x2;
if (map.containsKey(key)) {
if (dp[b][x1][x2][i] < dp2[0][x1][x2]) {
map.put(key, i);
dp2[0][x1][x2] = dp[b][x1][x2][i];
}
} else {
map.put(key, i);
dp2[0][x1][x2] = dp[b][x1][x2][i];
}
}
}
if (!placed) {
return false;
}
}

//acutal dp
// solve the knapsack problem for the remaining small items
for (int i = 1; i <= s; i++) {
Integer[] costs = smallItems.get(i-1).getCosts();
Vector3D[] weights = smallItems.get(i-1).getWeights();
for (int x1 = 0; x1 < dp2[0].length; x1++) {
for (int x2 = 0; x2 < dp2[0][x1].length; x2++) {
double minVal = Double.MAX_VALUE;
for (int c = 0; c < costs.length; c++) { //for the choices
Vector3D w = weights[c];
int x1_ = x1 - w.get(0);
int x2_ = x2 - w.get(2);
if (x1_ < 0 || x2_ < 0) {
continue;
}
if (dp2[i-1][x1_][x2_] == null) {
continue;
}
if (dp2[i-1][x1_][x2_] + costs[c] < minVal) {
minVal = dp2[i-1][x1_][x2_] + costs[c];
}
}
if (minVal < Double.MAX_VALUE) {
dp2[i][x1][x2] = minVal;
}
}
}
}


Vector3D minValue = new Vector3D(0, 0, 0);
double minCost = Double.MAX_VALUE;
for (int x1 = 0; x1 < dp2[0].length; x1++) {
for (int x2 = 0; x2 < dp2[0][x1].length; x2++) {
if (dp2[s][x1][x2] != null && dp2[s][x1][x2] < minCost) {
minCost = dp2[s][x1][x2];
minValue = new Vector3D(x1, 0, x2);
}
}
}
minValue.set(1, map.get(minValue.get(0) + "," + minValue.get(2))); // set the 2nd dimension to the best solution for the big items
//reconstruction for small items
for (int i = s; i > 0; i--) {
MDKnapsackItem item = smallItems.get(i - 1);
for (KnapsackChoice choice : item.getChoices()) {
Vector3D newWeight = minValue.subtract(choice.getWeight());
if (newWeight.get(0) < 0 || newWeight.get(1) < 0 || newWeight.get(2) < 0) {
continue;
}
if (dp2[i-1][newWeight.get(0)][newWeight.get(2)] != null) {
switch (choice.getAllotment()) {
case SMALL:
smallJobs.add(item.getJob());
break;
case SEQUENTIAL:
seqJobs.add(item.getJob());
break;
case SHELF1:
shelf1.add(item.getJob());
break;
case SHELF2:
shelf2.add(item.getJob());
break;
for (int x1 = 0; x1 < dp[0].length; x1++) {
for (int x2 = 0; x2 < dp[0][x1].length; x2++) {
for (int x3 = 0; x3 < dp[0][x1][x2].length; x3++) {
if (dp[items.size()][x1][x2][x3] != null && dp[items.size()][x1][x2][x3] < minCost) {
minCost = dp[items.size()][x1][x2][x3];
minValue = new Vector3D(x1, x2, x3);
}
minValue = newWeight;
break; //break out of loop as soon as some allotment was found.
}
}
}

//reconstruction for big items
for (int i = b; i > 0; i--) {
MDKnapsackItem item = bigItems.get(i - 1);
//reconstruction
for (int i = items.size(); i > 0; i--) {
MDKnapsackItem item = items.get(i - 1);
for (KnapsackChoice choice : item.getChoices()) {
Vector3D newWeight = minValue.subtract(choice.getWeight());
if (newWeight.get(0) < 0 || newWeight.get(1) < 0 || newWeight.get(2) < 0) {
continue;
}
if (dp[i-1][newWeight.get(0)][newWeight.get(2)][newWeight.get(1)] != null) {
if (dp[i-1][newWeight.get(0)][newWeight.get(1)][newWeight.get(2)] != null) {
switch (choice.getAllotment()) {
case SMALL:
smallJobs.add(item.getJob());
Expand All @@ -200,6 +122,7 @@ public void solve(List<MDKnapsackItem> smallItems, List<MDKnapsackItem> bigItems
}
}
// at the end we should arrive at 0.0
assert dp[0][minValue.get(0)][minValue.get(2)][minValue.get(1)] == 0.0;
assert dp[0][minValue.get(0)][minValue.get(1)][minValue.get(2)] == 0.0;
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ public boolean solve(double d, double epsilon) {
final int invDelta = 6;
final int n = I.getN();
final int l = I.getL();
final double v = (2.0 * invDelta) / d; //TODO: separate rounding for big tasks and small tasks
final double mu = (1.0 * n * invDelta) / d * l;
final double mu = (1.0 * n * invDelta) / d;

List<Job> shelf2 = new ArrayList<>(Arrays.asList(MyMath.findBigJobs(I, d)));
List<Job> smallJobs = new ArrayList<>(Arrays.asList(MyMath.findSmallJobs(I, d)));
Expand Down Expand Up @@ -118,8 +117,10 @@ public boolean solve(double d, double epsilon) {
// 2nd dimension: weight of tasks on L (less than 2l)
// 3rd dimension: total work regarding the scaled and rounded instace on L (less than n/\delta)
// -> optimized: (less than 2l/\delta)
Vector3D capacity = new Vector3D(I.getM(), 2* l, invDelta * 2 * l + 1);
kS.solve(smallKnapsackItems, bigKnapsackItems, capacity, shelf1, shelf2, smallJobs, sequentialJobs);
Vector3D capacity = new Vector3D(I.getM(), 2* l, invDelta * l * n);
if (!kS.solve(smallKnapsackItems, bigKnapsackItems, capacity, shelf1, shelf2, smallJobs, sequentialJobs)) {
return false;
}

// calculate the work for the jobs in the shelves for the malleable machines.
double Ws = 0;
Expand Down
10 changes: 4 additions & 6 deletions src/main/java/de/ohnes/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.core.config.plugins.util.ResolverUtil.Test;

import com.fasterxml.jackson.databind.ObjectMapper;

import de.ohnes.AlgorithmicComponents.Approximation.TrivialLowerBound;
import de.ohnes.AlgorithmicComponents.Approximation.TwoApproximation;
import de.ohnes.AlgorithmicComponents.Shelves.CpuGpuApproach;
import de.ohnes.logger.MyElasticsearchClient;
Expand Down Expand Up @@ -102,14 +100,13 @@ private static void readEnv() {
*/
private static TestResult runTest(Instance I) {

DualApproximationFramework dF = new DualApproximationFramework(null, new CpuGpuApproach(), new TwoApproximation(), I);
DualApproximationFramework dF = new DualApproximationFramework(null, new CpuGpuApproach(), new TrivialLowerBound(), I);


long startTime = System.currentTimeMillis();
double d = dF.start(epsilon);
long endTime = System.currentTimeMillis();
LOGGER.info("Ran instance with {} malleable, {} sequential machines and {} jobs in {} milliseconds.", I.getM(), I.getL(), I.getN(), (endTime - startTime));

TestResult tr = new TestResult();
tr.setAchivedMakespan(I.getMakespan());
tr.setEstimatedOptimum(d);
Expand All @@ -119,7 +116,8 @@ private static TestResult runTest(Instance I) {
tr.setSeqMachines(I.getL());
tr.setMilliseconds((endTime - startTime));
tr.setInstanceID(I.getId());


LOGGER.info("Result: {}", tr.toString());
return tr;
}
}
4 changes: 4 additions & 0 deletions src/main/java/de/ohnes/util/TestResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ public class TestResult {
private double achivedMakespan;
private long milliseconds;

public String toString() {
return String.format("%d, %d, %d, %d, %d, %f, %f, %d", InstanceID, jobs, machines, seqMachines, malMachines, estimatedOptimum, achivedMakespan, milliseconds);
}

}