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

io.jenetics.ext.engine.ConcatEngine 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.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Spliterator;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import java.util.stream.BaseStream;

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.ConcatSpliterator;

/**
 * The {@code ConcatEngine} lets you concatenate two (or more) evolution
 * {@link io.jenetics.engine.Engine}, with different configurations, and let it
 * use as one engine {@link EvolutionStreamable}.
 *
 * 
 {@code
 *                  +----------+               +----------+
 *                  |       ES |               |       ES |
 *          +-------+----+     |       +-------+----+     |
 *  (Start) |            +-----+ Start |            +-----+
 *   ------>|  Engine 1  |------------>|  Engine 2  |----------->
 *          |            | Result      |            |      Result
 *          +------------+             +------------+
 * } 
* * The sketch above shows how the engine concatenation works. In this example, * the evolution stream of the first engine is evaluated until it terminates. * The result of the first stream is then used as start input of the second * evolution stream, which then delivers the final result. *

* Concatenating evolution engines might be useful, if you want to explore your * search space with random search first and then start the real GA * search. * {@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 = * ConcatEngine.of( * engine1.limit(50), * engine2.limit(() -> Limits.bySteadyFitness(30))) * .stream() * .collect(EvolutionResult.toBestGenotype()); * * System.out.println(result + ": " + * problem.fitness().apply(problem.codec().decode(result))); * } * * An essential part, when concatenating evolution engines, is to make sure your * engines are creating limited evolution streams. This is what * the {@link EvolutionStreamable#limit(Supplier)} and * {@link EvolutionStreamable#limit(long)} methods are for. Limiting an engine * means, that this engine will surely create only streams, which are limited * with the predicate/generation given to the engine. If you have limited your * engines, it is no longer necessary to limit your final evolution stream, but * you are still able to do so. * * @see CyclicEngine * * @param the gene type * @param the fitness type * * @author Franz Wilhelmstötter * @version 4.1 * @since 4.1 */ public final class ConcatEngine< G extends Gene, C extends Comparable > extends EnginePool { /** * Create a new concatenating evolution engine with the given list of engines. * * @param engines the engines which are concatenated to one engine * @throws NullPointerException if the {@code engines} or one of its * elements is {@code null} */ public ConcatEngine(final List> engines) { super(engines); } @Override public EvolutionStream stream(final Supplier> start) { final AtomicReference> other = new AtomicReference<>(null); return new EvolutionStreamImpl<>( new ConcatSpliterator<>( _engines.stream() .map(engine -> engine .stream(() -> start(start, other)) .peek(result -> other.set(result.toEvolutionStart()))) .map(BaseStream::spliterator) .toList() ), false ); } 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 AtomicReference> other = new AtomicReference<>(null); return new EvolutionStreamImpl<>( new ConcatSpliterator<>(spliterators(init, other)), false ); } private Collection>> spliterators( final EvolutionInit init, final AtomicReference> other ) { final Collection>> result; if (_engines.isEmpty()) { result = Collections.emptyList(); } else if (_engines.size() == 1) { result = List.of( _engines.get(0) .stream(init) .peek(er -> other.set(er.toEvolutionStart())) .spliterator() ); } else { final List>> concat = new ArrayList<>(); concat.add( _engines.get(0) .stream(init) .peek(er -> other.set(er.toEvolutionStart())) .spliterator() ); concat.addAll( _engines.subList(1, _engines.size()).stream() .map(engine -> engine .stream(other::get) .peek(er -> other.set(er.toEvolutionStart()))) .map(BaseStream::spliterator) .toList() ); result = concat; } return result; } /** * Create a new concatenating evolution engine with the given array of * engines. * * @param engines the engines which are concatenated to one 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> ConcatEngine of(final EvolutionStreamable... engines) { return new ConcatEngine<>(List.of(engines)); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy