jenetics:在 stream() 之外设置 EvolutionStream 限制

jenetics: Set EvolutionStream limit outside of stream()

jenetics to set termination limits to EvolutionStream, see the documentation有几种可能性。

限制通常直接应用于 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());

或组合,参见 example:

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));

结果是一个Stream,不知道EvolutionStream具体的限制方法。因此,如果定义了多个限制,我将无法应用它。尝试投射

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

导致错误:

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

那么,有没有办法在流生成器之外正确应用多个限制?

EvolutionStream.limit(Predicate) 方法执行 return 和 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) 方法是 only 方法,它返回一个 EvolutionStream.

另一种方法是您的方法初始化 EvolutionStream,从外部获取 Predicates。

@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)
);