@Test(invocationCount = 5, successPercentage = 80)
public void collect() {

	final Problem<double[], DoubleGene, Vec<double[]>> problem = Problem.of(
		v -> Vec.of(v[0]*cos(v[1]), v[0]*sin(v[1])),
		Codecs.ofVector(
			DoubleRange.of(0, 1),
			DoubleRange.of(0, 2*PI)
		)
	);
	final Engine<DoubleGene, Vec<double[]>> engine = Engine.builder(problem)
		.alterers(
			new Mutator<>(0.1),
			new MeanAlterer<>())
		.offspringSelector(new TournamentSelector<>(2))
		.survivorsSelector(UFTournamentSelector.ofVec())
		.minimizing()
		.build();
	final List<Vec<double[]>> pop = new ArrayList<>();
	final var accu = Accumulator.of(MOEA.<DoubleGene, double[], Vec<double[]>>toParetoSet(IntRange.of(20, 25)));
	final ISeq<Vec<double[]>> result = engine.stream()
		.limit(100)
		.peek(accu)
		.peek(er -> pop.addAll(er.population()
			.map(Phenotype::fitness).asList()))
		.collect(MOEA.toParetoSet(IntRange.of(20, 25)))
		.map(Phenotype::fitness);
	Assert.assertTrue(result.size() >= 10, "Expected >= 10, got " + result.size());
	Assert.assertTrue(result.size() <= 50, "Expected <= 50, got " + result.size());
	Assert.assertEquals(accu.result().size(), result.size());
	Assert.assertEquals(accu.result().map(Phenotype::fitness), result);
	final Set<Vec<double[]>> front = new HashSet<>(
		Pareto
			.front(ISeq.of(pop), Comparator.reverseOrder())
			.asList()
	);
	final Set<Vec<double[]>> missing = result.stream()
		.filter(r -> !front.contains(r))
		.collect(Collectors.toSet());
	Assert.assertTrue(missing.size() < 10, "Expected < 10, got " + missing.size());
}