package resa.evaluation.scheduler.plan; import org.junit.Before; import org.junit.Test; import resa.migrate.plan.KuhnMunkres; import resa.migrate.plan.PackCalculator; import java.util.*; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import static resa.migrate.plan.PackCalculator.convertPack; /** * Created by ding on 14-9-4. */ public class BestPackFinder { private double workload[]; private double[] dataSizes; private float ratio = 1.20f; private double totalDataSize; @Before public void init() { workload = new double[100]; Arrays.fill(workload, 100); dataSizes = new double[100]; Arrays.fill(dataSizes, 100); totalDataSize = DoubleStream.of(dataSizes).sum(); } @Test public void generateAllPacks() { int[] allStates = new int[]{2, 3, 4}; Map<Integer, int[][]> statePacks = new HashMap<>(); for (int state : allStates) { double loadUpperLimit = DoubleStream.of(workload).sum() / state * ratio; List<int[]> packs = new ArrayList<>(); genPacks(0, new int[0], state, state, loadUpperLimit, workload, packs); statePacks.put(state, packs.toArray(new int[0][])); } float[] values = new float[statePacks.get(allStates[allStates.length - 1]).length]; String[] paths = new String[statePacks.get(allStates[allStates.length - 1]).length]; Arrays.fill(paths, ""); for (int i = allStates.length - 2; i >= 0; i--) { int[][] currPacks = statePacks.get(allStates[i]); float[] newValues = new float[currPacks.length]; for (int j = 0; j < currPacks.length; j++) { int[][] nextPacks = statePacks.get(allStates[i + 1]); PackCost selected = selectTargetPack(convertPack(currPacks[j]), nextPacks, values, 0.9f); } } } private PackCost selectTargetPack(PackCalculator.Range[] srcPack, int[][] allTargetPacks, float[] costVector, float gam) { return IntStream.range(0, allTargetPacks.length).parallel().mapToObj(i -> new PackCost(gam * costVector[i] + (totalDataSize - packGain(srcPack, convertPack(allTargetPacks[i]), new KuhnMunkres(dataSizes.length))), i)) .min(Comparator.<PackCost>naturalOrder()).get(); } private static class PackCost implements Comparable<PackCost> { double cost; int pos; PackCost(double cost, int pos) { this.cost = cost; this.pos = pos; } @Override public int compareTo(PackCost o) { return Double.compare(cost, o.cost); } } private void genPacks(int start, int[] splits, int part, int totalNumPartitions, double loadUpperLimit, double[] normalizedWordloads, List<int[]> packs) { if (start + part > workload.length) { return; } if (part == 1) { if (start == workload.length || splits.length + 1 != totalNumPartitions) { throw new IllegalStateException("start == workloads.length"); } else if (totalWorkload(start, workload.length, normalizedWordloads) <= loadUpperLimit) { int[] newPack = new int[splits.length + 1]; System.arraycopy(splits, 0, newPack, 0, splits.length); newPack[newPack.length - 1] = workload.length - start; packs.add(newPack); } return; } int[] newSplits = new int[splits.length + 1]; System.arraycopy(splits, 0, newSplits, 0, splits.length); for (int i = start + 1; i < workload.length; i++) { if (totalWorkload(start, i, normalizedWordloads) > loadUpperLimit) { break; } newSplits[newSplits.length - 1] = i - start; genPacks(i, newSplits, part - 1, totalNumPartitions, loadUpperLimit, normalizedWordloads, packs); } } private double totalWorkload(int wStart, int wEnd, double[] normalizedWordloads) { double sum = 0; for (int i = wStart; i < wEnd; i++) { sum += normalizedWordloads[i]; } return sum; } private double packGain(PackCalculator.Range[] pack1, PackCalculator.Range[] pack2, KuhnMunkres kmAlg) { double[][] weights = new double[pack1.length][pack2.length]; for (int i = 0; i < pack1.length; i++) { for (int j = 0; j < pack2.length; j++) { weights[i][j] = overlap(pack1[i], pack2[j]); } } //System.out.println(Arrays.toString(pack1) + " " +Arrays.toString(pack2) ); double[] maxWeight = new double[1]; kmAlg.getMaxBipartie(weights, maxWeight); return maxWeight[0]; } private double overlap(PackCalculator.Range r1, PackCalculator.Range r2) { if (r1.end < r2.start || r1.start > r2.end) { return 0; } else if (r1.start <= r2.start && r1.end >= r2.start) { return IntStream.rangeClosed(r2.start, Math.min(r2.end, r1.end)).mapToDouble(i -> dataSizes[i]).sum(); } else if (r1.start >= r2.start && r1.start <= r2.end) { return IntStream.rangeClosed(r1.start, Math.min(r2.end, r1.end)).mapToDouble(i -> dataSizes[i]).sum(); } return 0; } }