All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.jenetics.ext.engine.CyclicEngine Maven / Gradle / Ivy

The newest version!
/*
 * Java Genetic Algorithm Library (jenetics-8.1.0).
 * Copyright (c) 2007-2024 Franz Wilhelmstötter
 *
 * 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.
 *
 * Author:
 *    Franz Wilhelmstötter ([email protected])
 */
package io.jenetics.ext.engine;

import java.util.List;
import java.util.Spliterator;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;

import io.jenetics.Gene;
import io.jenetics.engine.EvolutionInit;
import io.jenetics.engine.EvolutionResult;
import io.jenetics.engine.EvolutionStart;
import io.jenetics.engine.EvolutionStream;
import io.jenetics.engine.EvolutionStreamable;
import io.jenetics.internal.engine.EvolutionStreamImpl;

import io.jenetics.ext.internal.util.CyclicSpliterator;

/**
 * The {@code CyclicEngine} lets you concatenate two (or more) evolution
 * {@link io.jenetics.engine.Engine}, with different configurations, and let it
 * use as one engine {@link EvolutionStreamable}. If the last evolution
 * stream terminates, it's final result is fed back to first engine.
 *
 * 
 {@code
 *                  +----------+               +----------+
 *                  |       ES |               |       ES |
 *          +------------+     |       +------------+     |
 *  (Start) |            |-----+ Start |            |-----+
 * ---+---->|  Engine 1  |------------>|  Engine 2  | --------+
 *    ^     |            | Result      |            |         |
 *    |     +------------+             +------------+         |
 *    |                                                       |
 *    +------------------------------<------------------------+
 *                              Result
 * } 
* * The {@code CyclicEngine} allows to do a broad search-fine search-cycle * as long as you want. * * {@snippet lang="java": * final Problem problem = Problem.of( * v -> Math.sin(v[0])*Math.cos(v[1]), * Codecs.ofVector(DoubleRange.of(0, 2*Math.PI), 2) * ); * * final Engine engine1 = Engine.builder(problem) * .minimizing() * .alterers(new Mutator<>(0.2)) * .selector(new MonteCarloSelector<>()) * .build(); * * final Engine engine2 = Engine.builder(problem) * .minimizing() * .alterers( * new Mutator<>(0.1), * new MeanAlterer<>()) * .selector(new RouletteWheelSelector<>()) * .build(); * * final Genotype result = * CyclicEngine.of( * engine1.limit(50), * engine2.limit(() -> Limits.bySteadyFitness(30))) * .stream() * .limit(Limits.bySteadyFitness(1000)) * .collect(EvolutionResult.toBestGenotype()); * * System.out.println(result + ": " + * problem.fitness().apply(problem.codec().decode(result))); * } * * When using a {@code CyclicEnginePool}, you have to limit the final evolution * stream, additionally to the defined limits on the used partial engines. * * @see ConcatEngine * * @param the gene type * @param the fitness type * * @author Franz Wilhelmstötter * @version 4.1 * @since 4.1 */ public final class CyclicEngine< G extends Gene, C extends Comparable > extends EnginePool { /** * Create a new cycling evolution engine with the given list of * {@code engines}. * * @param engines the evolution engines which are part of the cycling engine * @throws NullPointerException if the {@code engines} or one of its * elements is {@code null} */ public CyclicEngine( final List> engines ) { super(engines); } @Override public EvolutionStream stream(final Supplier> start) { final AtomicReference> other = new AtomicReference<>(null); return new EvolutionStreamImpl<>( new CyclicSpliterator<>( _engines.stream() .map(engine -> toSpliterator(engine, start, other)) .toList() ), false ); } private Supplier>> toSpliterator( final EvolutionStreamable engine, final Supplier> start, final AtomicReference> other ) { return () -> engine.stream(() -> start(start, other)) .peek(result -> other.set(result.toEvolutionStart())) .spliterator(); } private EvolutionStart start( final Supplier> first, final AtomicReference> other ) { return other.get() != null ? other.get() : first.get(); } @Override public EvolutionStream stream(final EvolutionInit init) { final AtomicBoolean first = new AtomicBoolean(true); final AtomicReference> other = new AtomicReference<>(null); return new EvolutionStreamImpl<>( new CyclicSpliterator<>( _engines.stream() .map(engine -> toSpliterator(engine, init, other, first)) .toList() ), false ); } private Supplier>> toSpliterator( final EvolutionStreamable engine, final EvolutionInit init, final AtomicReference> other, final AtomicBoolean first ) { return () -> { if (first.get()) { first.set(false); return engine.stream(init) .peek(result -> other.set(result.toEvolutionStart())) .spliterator(); } else { return engine.stream(other::get) .peek(result -> other.set(result.toEvolutionStart())) .spliterator(); } }; } /** * Create a new cycling evolution engine with the given array of * {@code engines}. * * @param engines the evolution engines which are part of the cycling engine * @param the gene type * @param the fitness type * @return a new concatenating evolution engine * @throws NullPointerException if the {@code engines} or one of its * elements is {@code null} */ @SafeVarargs public static , C extends Comparable> CyclicEngine of(final EvolutionStreamable... engines) { return new CyclicEngine<>(List.of(engines)); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy