blob: a1755bf6ca0ada85fd68a68af8c2b3648e0387ee [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.compatibility.common.tradefed.util;
import com.android.compatibility.common.tradefed.testtype.IModuleDef;
import java.util.ArrayList;
import java.util.List;
/**
* Helper for the shard splitting. Split linearly a list into N sublist with
* approximately the same weight.
* TODO: Can be generalized for any weighted objects.
*/
public class LinearPartition {
/**
* Split a list of {@link IModuleDef} into k sub list based on the runtime hint.
*
* @param seq the full list of {@link IModuleDef} to be splitted
* @param k the number of sub list we need.
* @return the List of sublist.
*/
public static List<List<IModuleDef>> split(List<IModuleDef> seq, int k) {
ArrayList<List<IModuleDef>> result = new ArrayList<>();
if (k <= 0) {
ArrayList<IModuleDef> partition = new ArrayList<>();
partition.addAll(seq);
result.add(partition);
return result;
}
int n = seq.size() - 1;
if (k > n) {
for (IModuleDef value : seq) {
ArrayList<IModuleDef> partition = new ArrayList<>();
partition.add(value);
result.add(partition);
}
return result;
}
int[][] table = buildPartitionTable(seq, k);
k = k - 2;
while (k >= 0) {
ArrayList<IModuleDef> partition = new ArrayList<>();
for (int i = table[n - 1][k] + 1; i < n + 1; i++) {
partition.add(seq.get(i));
}
result.add(0, partition);
n = table[n - 1][k];
k = k - 1;
}
ArrayList<IModuleDef> partition = new ArrayList<>();
for (int i = 0; i < n + 1; i++) {
partition.add(seq.get(i));
}
result.add(0, partition);
return result;
}
/**
* Internal helper to build the partition table of the linear distribution used for splitting.
*/
private static int[][] buildPartitionTable(List<IModuleDef> seq, int k) {
int n = seq.size();
float[][] table = new float[n][k];
int[][] solution = new int[n - 1][k - 1];
for (int i = 0; i < n; i++) {
table[i][0] = seq.get(i).getRuntimeHint() + ((i > 0) ? table[i - 1][0] : 0);
}
for (int j = 0; j < k; j++) {
table[0][j] = seq.get(0).getRuntimeHint();
}
for (int i = 1; i < n; i++) {
for (int j = 1; j < k; j++) {
table[i][j] = Integer.MAX_VALUE;
for (int x = 0; x < i; x++) {
float cost = Math.max(table[x][j - 1], table[i][0] - table[x][0]);
if (table[i][j] > cost) {
table[i][j] = cost;
solution[i - 1][j - 1] = x;
}
}
}
}
return solution;
}
}