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

io.jenetics.ext.grammar.Mappers 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.grammar;

import java.util.function.Function;

import io.jenetics.BitChromosome;
import io.jenetics.BitGene;
import io.jenetics.Genotype;
import io.jenetics.IntegerChromosome;
import io.jenetics.IntegerGene;
import io.jenetics.engine.Codec;
import io.jenetics.util.IntRange;

import io.jenetics.ext.grammar.Cfg.Rule;

/**
 * This class defines factories for different CFG ↔ Chromosome mappings
 * (encodings). The classical mapping codec, with a bit-chromosome can be created
 * in the following way.
 * {@snippet lang="java":
 * final Cfg cfg = null; // @replace substring='null' replacement="..."
 * final Codec>, BitGene> codec = singleBitChromosomeMapper(
 *     cfg,
 *     1000,
 *     index -> new SentenceGenerator<>(index, 1000)
 * );
 * }
 * This codec creates a mapping for the given grammar {@code cfg} and uses
 * bit-chromosomes with length {@code 1000}. The result of the mapping will be a
 * list of terminal symbols which has been created by the given
 * {@link SentenceGenerator}. The sentence generator creates sentences with a
 * maximal length of {@code 1000}. If no sentence could be created within this
 * limit, an empty list of terminal symbols is returned.
 *
 * @see 
 * 	 Grammatical Evolution
 *
 * @author Franz Wilhelmstötter
 * @since 7.1
 * @version 7.1
 */
public final class Mappers {
	private Mappers() {
	}

	/**
	 * Return a classic mapping codec. It uses a bit-chromosome for creating the
	 * grammar results. The codons are created by dividing the chromosome in
	 * 8-bit junks, as described in 
	 * Grammatical Evolution by Michael O’Neill and Conor Ryan.
	 *
	 * {@snippet lang="java":
	 * final Cfg cfg = null; // @replace substring='null' replacement="..."
	 * final Codec>, BitGene> codec = singleBitChromosomeMapper(
	 *     cfg,
	 *     1000,
	 *     index -> new SentenceGenerator<>(index, 1000)
	 * );
	 * }
	 *
	 * @see #singleIntegerChromosomeMapper(Cfg, IntRange, IntRange, Function)
	 *
	 * @param cfg the encoding grammar
	 * @param length the length of the bit-chromosome
	 * @param generator sentence generator function from a given
	 *        {@link SymbolIndex}
	 * @param  the terminal token type of the grammar
	 * @param  the result type of the mapper
	 * @return a new mapping codec for the given {@code cfg}
	 */
	public static  Codec
	singleBitChromosomeMapper(
		final Cfg cfg,
		final int length,
		final Function> generator
	) {
		return Codec.of(
			Genotype.of(BitChromosome.of(length)),
			gt -> generator
				.apply(Codons.ofBitGenes(gt.chromosome()))
				.generate(cfg)
		);
	}

	/**
	 * Create a mapping codec, similar as in {@link #singleBitChromosomeMapper(Cfg, int, Function)}.
	 * The only difference is that the codons are encoded directly, via an
	 * integer-chromosome, so that no gene split is necessary.
	 *
	 * {@snippet lang="java":
	 * final Cfg cfg = null; // @replace substring='null' replacement="..."
	 * final Codec>, IntegerGene> codec = singleIntegerChromosomeMapper(
	 *     cfg,
	 *     IntRange.of(0, 256), // Value range of chromosomes.
	 *     IntRange.of(100),   // Length (range) ot the chromosome.
	 *     index -> new SentenceGenerator<>(index, 1000)
	 * );
	 * }
	 *
	 * @param cfg the encoding grammar
	 * @param range the value range of the integer genes
	 * @param length the length range of the integer-chromosome
	 * @param generator sentence generator function from a given
	 *        {@link SymbolIndex}
	 * @param  the terminal token type of the grammar
	 * @param  the result type of the mapper
	 * @return a new mapping codec for the given {@code cfg}
	 */
	public static  Codec
	singleIntegerChromosomeMapper(
		final Cfg cfg,
		final IntRange range,
		final IntRange length,
		final Function> generator
	) {
		return Codec.of(
			Genotype.of(IntegerChromosome.of(range, length)),
			gt -> generator
				.apply(Codons.ofIntegerGenes(gt.chromosome()))
				.generate(cfg)
		);
	}

	/**
	 * Create a mapping codec, similar as in {@link #singleBitChromosomeMapper(Cfg, int, Function)}.
	 * The only difference is that the codons are encoded directly, via an
	 * integer-chromosome, so that no gene split is necessary.
	 *
	 * {@snippet lang="java":
	 * final Cfg cfg = null; // @replace substring='null' replacement="..."
	 * final Codec>, IntegerGene> codec = singleIntegerChromosomeMapper(
	 *     cfg,
	 *     IntRange.of(0, 256), // Value range of chromosomes.
	 *     100,                 // Length (range) ot the chromosome.
	 *     index -> new SentenceGenerator<>(index, 1000)
	 * );
	 * }
	 *
	 * @param cfg the encoding grammar
	 * @param range the value range of the integer genes
	 * @param length the length range of the integer-chromosome
	 * @param generator sentence generator function from a given
	 *        {@link SymbolIndex}
	 * @param  the terminal token type of the grammar
	 * @param  the result type of the mapper
	 * @return a new mapping codec for the given {@code cfg}
	 */
	public static  Codec
	singleIntegerChromosomeMapper(
		final Cfg cfg,
		final IntRange range,
		final int length,
		final Function> generator
	) {
		return singleIntegerChromosomeMapper(
			cfg, range, IntRange.of(length), generator
		);
	}

	/**
	 * Codec for creating results from a given grammar. The creation of
	 * the grammar result is controlled by a given genotype. This encoding uses
	 * separate codons, backed up by a {@link IntegerChromosome}, for
	 * every rule. The length of the chromosome is defined as a function of the
	 * encoded rules. This means that the following CFG,
	 *
	 * 
{@code
	 *                       (0)            (1)
	 * (0)  ::= () | 
	 *               (0) (1) (2) (3)
	 * (1)    ::= + | - | * | /
	 *               (0) (1) (2) (3) (4)
	 * (2)   ::= x | 1 | 2 | 3 | 4
	 * }
* * will be represented by the following {@link Genotype} * {@snippet lang="java": * Genotype.of( * IntegerChromosome.of(IntRange.of(0, 2), length.apply(cfg.rules().get(0))), * IntegerChromosome.of(IntRange.of(0, 4), length.apply(cfg.rules().get(1))), * IntegerChromosome.of(IntRange.of(0, 5), length.apply(cfg.rules().get(2))) * ) * } * * The {@code length} function lets you defining the number of codons as * function of the rule the chromosome is encoding. * * {@snippet lang="java": * final Cfg cfg = Bnf.parse(null); // @replace substring='null' replacement="..." * final Codec>, IntegerGene> codec = multiIntegerChromosomeMapper( * cfg, * // The chromosome length is 25 times the * // number of rule alternatives. * rule -> IntRange.of(rule.alternatives().size()*25), * // Using the standard sentence generator * // with a maximal sentence length of 500. * index -> new SentenceGenerator<>(index, 500) * ); * } * * @param cfg the encoding grammar * @param length the length of the chromosome which is used for selecting * rules and symbols. The input parameter for this function is the * actual rule. This way it is possible to define the chromosome * length dependent on the selectable alternatives. * @param generator sentence generator function from a given * {@link SymbolIndex} * @param the terminal token type of the grammar * @param the result type of the mapper * @return a new mapping codec for the given {@code cfg} */ public static Codec multiIntegerChromosomeMapper( final Cfg cfg, final Function, IntRange> length, final Function> generator ) { return new MultiIntegerChromosomeMapper<>(cfg, length, generator); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy