jenetics: установите предел эволюционного потока вне stream()

#java-stream #jenetics

#java-stream #jenetics

Вопрос:

В jenetics есть несколько возможностей для установки ограничений завершения EvolutionStream , см. Документацию.

Ограничения обычно применяются непосредственно к stream , например

 Phenotype<IntegerGene,Double> result = engine.stream()
    .limit(Limits.bySteadyFitness(10))
    .collect(EvolutionResult.toBestPhenotype());
 

или

 Phenotype<IntegerGene,Double> result = engine.stream()
    .limit(Limits.byFixedGeneration(10))
    .collect(EvolutionResult.toBestPhenotype());
 

или в комбинации, см. Пример:

 Phenotype<IntegerGene,Double> result = engine.stream()
    .limit(Limits.bySteadyFitness(10))
    .limit(Limits.byFixedGeneration(10))
    .collect(EvolutionResult.toBestPhenotype());
 

В моей задаче оптимизации я хочу позволить пользователю решать, какие ограничения назначить для проблемы. Я не знаю заранее настройки ограничения. Это может быть несколько ограничений. Поэтому я должен назначить типы ограничений во время выполнения.

Я попытался создать EvolutionStream объект с помощью

 EvolutionStream<IntegerGene, Double> evolutionStream = engine.stream();
 

и назначьте лимиты на evolutionStream :

 Stream<EvolutionResult<IntegerGene, Double>> limit = evolutionStream.limit(Limits.byFixedGeneration(10));
 

Результатом является поток, который не знает EvolutionStream конкретных методов ограничения. Таким образом, я не могу применить его в случае, если определено несколько ограничений. Попытка привести

 evolutionStream = (EvolutionStream<IntegerGene, Double>)evolutionStream.limit(Limits.byFixedGeneration(10));
 

приводит к ошибке:

 java.lang.ClassCastException: class java.util.stream.SliceOps$1 cannot be cast to class io.jenetics.engine.EvolutionStream (java.util.stream.SliceOps$1 is in module java.base of loader 'bootstrap'; io.jenetics.engine.EvolutionStream is in unnamed module of loader 'app')
 

Итак, есть ли способ правильно применить несколько ограничений вне stream builder?

Ответ №1:

EvolutionStream.limit(Predicate) Метод действительно возвращает an EvolutionStream .

 EvolutionStream<IntegerGene, Double> stream = engine.stream();
stream = stream
    .limit(Limits.byFixedGeneration(10))
    .limit(Limits.bySteadyFitness(5))
    .limit(Limits.byExecutionTime(Duration.ofMillis(100)));
 

Итак, приведенные вами примеры выглядят хорошо и должны работать. Но EvolutionStream.limit(Predicate) метод — это единственный метод, который возвращает вам EvolutionStream .

Альтернативой может быть то, что ваш метод, который инициализирует EvolutionStream , принимает Predicate s извне.

 @SafeVarargs
static EvolutionStream<IntegerGene, Double>
newStream(final Predicate<? super EvolutionResult<IntegerGene, Double>>... limits) {
    final Engine<IntegerGene, Double> engine = Engine
        .builder(a -> a.gene().allele().doubleValue(), IntegerChromosome.of(0, 100))
        .build();

    EvolutionStream<IntegerGene, Double> stream = engine.stream();
    for (var limit : limits) {
        stream = stream.limit(limit);
    }

    return stream;
}    
    
final var stream = newStream(
    Limits.byFixedGeneration(100),
    Limits.byExecutionTime(Duration.ofMillis(1000)),
    Limits.bySteadyFitness(10)
);
 

Комментарии:

1. Спасибо. Как вы сказали, это сработало. Некоторая очистка кода сделала свое дело