我正在尝试优化一个过程,即计算所有可能的玩家组合以形成分区。为了解我的问题,我使用以下示例。例如,我们有一组玩家N = {1,2,3,4,5}
,这个玩家会像{1,2},{3,4},{5}
一样重新组合。这意味着palyer 1将作为单个玩家与玩家2一起玩,所以一个玩家。每组玩家都有一套策略或选择。每个玩家选择他想要归属的组,例如:
小组{1,2}
有这些可能性{{1,2};{1,2,3,4}}
;即球员{1,2}他们选择留在一起或加入小组{3,4}。
对其他球员的解释相同:
{3,4}=>{{3,4};{3,4,5};{1,2,3,4}}
{5}=>{{5};{3,4,5}}
现在,选择相同策略的玩家组将形成一个新组(联盟)。例如,小组{1,2}
选择了策略{1,2,3,4}
;即。球员{1,2}希望与球员{3,4}组成一个新的球队。玩家{3,4}选择策略{3,4,5}
,玩家{5}
选择策略{3,4,5}
。玩家选择相同的策略将组合在一起,在最终形成一个像这样的玩家分区:{1,2},{3,4,5};玩家3,4,5选择了相同的策略,所以他们组合在一起,玩家{1,2}选择不同的策略让你独自留下。我们对玩家策略的所有可能组合做同样的事情,以获得基数= K的所有可能的玩家分区。在最后,我必须选择玩家的最佳分区。在前面的示例中:我必须只生成基数= 2的分区:
| {1,2,3,4},{5} | = 2
| {1,2} {3,4,5} | = 3
此分区不可接受:|{1,2}{3,4}{5}|=3
我已经将这个过程编程为一个递归函数,以获得所有允许的玩家分区。这里的另一个问题是我的函数生成了所有可能的分区,而且我只获得了多次允许的允许值!
现在我的问题是,是否可以在java中使用并行性来计算玩家的所有可允许分区,特别是当我们有很多玩家和很多分区时。我必须做些什么来加速大问题的执行?
import static java.util.Arrays.asList;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Test {
@SafeVarargs
static <T> Set<T> set(T ... elems) {
return new HashSet<T>(asList(elems));
}
static <T> List<Set<Set<T>>> calcPartitions(List<T> teams, Map<T, List<Set<T>>> team2Strategies, int k, boolean doParallel) {
if(k == 0) {
if(teams.isEmpty()) return asList(new HashSet<>());
else return new ArrayList<>();
} else if(teams.isEmpty()) {
return new ArrayList<>();
}
Set<T> teamsSet = new HashSet<>(teams);
T team = teams.get(0);
Stream<Set<T>> strategies =
(doParallel ? team2Strategies.get(team).parallelStream() : team2Strategies.get(team).stream())
.filter(strategy ->
strategy.stream().allMatch(team2 ->
teamsSet.contains(team2) && team2Strategies.get(team2).contains(strategy)));
return strategies.flatMap(strategy -> {
List<T> newTeams = new ArrayList<>(teams);
newTeams.removeAll(strategy);
List<Set<Set<T>>> restPartitions = calcPartitions(newTeams, team2Strategies, k - 1, false);
for(Set<Set<T>> partition: restPartitions) {
partition.add(strategy);
}
return restPartitions.stream();
})
.collect(Collectors.toList());
}
public static void main(String[] args) {
List<Set<Integer>> teams = asList(set(0,1,2), set(3,4), set(5),set(6,7,8),set(9,10,11),set(12,13,14));
Map<Set<Integer>, List<Set<Set<Integer>>>> team2Strategies = new HashMap<>();
team2Strategies.put(set(0,1,2), asList(set(set(0,1, 2)),
set(set(0,1, 2), set(3, 4))));
team2Strategies.put(set(3,4), asList(set(set(3, 4), set(5)),
set(set(0,1, 2), set(3, 4))));
team2Strategies.put(set(5), asList(set(set(5)),
set(set(3, 4), set(5)),set(set(5),set(6,7,8)),set(set(5),set(6,7,8),set(9,10,11),set(12,13,14))));
team2Strategies.put(set(6,7,8), asList(set(set(6,7,8)),
set(set(6, 7,8), set(5)),set(set(5),set(6,7,8),set(9,10,11),set(12,13,14))));
team2Strategies.put(set(9,10,11), asList(set(set(9,10,11)),
set(set(9, 10,11), set(12,13,14)),set(set(5),set(6,7,8),set(9,10,11),set(12,13,14))));
team2Strategies.put(set(12,13,14), asList(set(set(12,13,14)),
set(set(12, 13,14), set(9,10,11)),set(set(5),set(6,7,8),set(9,10,11),set(12,13,14))));
List<Set<Set<Set<Integer>>>> partitions = calcPartitions(teams, team2Strategies, 3, true);
Comparator<List<Integer>> intListComparator = (a, b) -> {
int i = 0;
while(i < a.size() && i < b.size()) {
if(a.get(i) > b.get(i)) return 1;
else if(a.get(i) < b.get(i)) return -1;
i++;
}
return a.size() - b.size();
};
//in "partitions" a strategy was a Set<Set<Integer>>
//in "partitionsList" however a strategy is a List<Integer>
List<List<List<Integer>>> partitionsList =
partitions.stream().map(partition ->
partition.stream().map(strategy ->
strategy.stream().flatMap(Set::stream)
.sorted()
.collect(Collectors.toList()))
.sorted(intListComparator).collect(Collectors.toList()))
.collect(Collectors.toList());
System.out.println(partitionsList);
System.out.println(
partitionsList.stream().map(partition ->
partition.stream().map(strategy ->
strategy.stream().map(i -> i.toString()).collect(Collectors.joining(", ", "{", "}")))
.collect(Collectors.joining()))
.collect(Collectors.joining("\n")));
}
}