package resa.migrate.plan; import java.util.Map; import java.util.stream.IntStream; import java.util.stream.Stream; /** * Created by ding on 14-7-23. */ public class SimpleCalculator extends PackCalculator { private double gain = -1.0; private int[] pack = null; private KuhnMunkres kmAlg; @Override protected Pack calcPack() { int maxPackSize = Stream.of(srcPacks).map(Map.Entry::getKey).mapToInt(pack -> pack.length).max().getAsInt(); kmAlg = new KuhnMunkres(Math.max(packSize, maxPackSize)); split(0, new int[0], packSize); kmAlg = null; if (pack == null) { throw new IllegalStateException("No pack is found"); } Pack ret = new Pack(pack, gain); gain = -1.0; pack = null; return ret; } private void split(int start, int[] spilts, int part) { if (start + part > workloads.length) { return; } if (part == 1) { if (start == workloads.length || spilts.length + 1 != packSize) { throw new IllegalStateException("start == workloads.length"); } else if (totalWorkload(start, workloads.length) <= loadUpperLimit) { int[] newPack = new int[spilts.length + 1]; System.arraycopy(spilts, 0, newPack, 0, spilts.length); newPack[newPack.length - 1] = workloads.length - start; double g = totalGain(convertPack(newPack)); if (g > gain) { gain = g; pack = newPack; } } return; } int[] newSplits = new int[spilts.length + 1]; System.arraycopy(spilts, 0, newSplits, 0, spilts.length); for (int i = start + 1; i < workloads.length; i++) { if (totalWorkload(start, i) > loadUpperLimit) { break; } newSplits[newSplits.length - 1] = i - start; split(i, newSplits, part - 1); } } private double totalGain(Range[] pack) { return Stream.of(srcPacks).mapToDouble(e -> packGain(pack, e.getKey()) * e.getValue()).sum(); } private double packGain(Range[] pack1, Range[] pack2) { 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]); } } double[] maxWeight = new double[1]; kmAlg.getMaxBipartie(weights, maxWeight); // int[][] pairs = kmAlg.getMaxBipartie(weights, maxWeight); // return Stream.of(pairs).mapToDouble(r -> overlap(newPacks[r[0]], currPacks[pStart + r[1]])).sum(); return maxWeight[0]; } private double overlap(Range r1, 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; } private double totalWorkload(int wStart, int wEnd) { double sum = 0; for (int i = wStart; i < wEnd; i++) { sum += normalizedWordloads[i]; } return sum; } }