/** * Create a new {@code Codec} with the mapped result type. The following * example creates a double codec who's values are not uniformly distributed * between {@code [0..1)}. Instead the values now follow an exponential * function. * * <pre>{@code * final Codec<Double, DoubleGene> c = Codecs.ofScalar(DoubleRange.of(0, 1)) * .map(Math::exp); * }</pre> * * @since 4.0 * * @param mapper the mapper function * @param <B> the new argument type of the given problem * @return a new {@code Codec} with the mapped result type * @throws NullPointerException if the mapper is {@code null}. */ public default <B> Codec<B, G> map(final Function<? super T, ? extends B> mapper) { requireNonNull(mapper); return Codec.of( encoding(), gt -> mapper.apply(decode(gt)) ); }
/** * Return a scalar {@code Codec} for the given range. * * @param domain the domain of the returned {@code Codec} * @return a new scalar {@code Codec} with the given domain. * @throws NullPointerException if the given {@code domain} is {@code null} */ public static Codec<Long, LongGene> ofScalar(final LongRange domain) { requireNonNull(domain); return Codec.of( Genotype.of(LongChromosome.of(domain)), gt -> gt.getGene().getAllele() ); }
/** * Return a scalar {@code Codec} for the given range. * * @param domain the domain of the returned {@code Codec} * @return a new scalar {@code Codec} with the given domain. * @throws NullPointerException if the given {@code domain} is {@code null} */ public static Codec<Double, DoubleGene> ofScalar(final DoubleRange domain) { requireNonNull(domain); return Codec.of( Genotype.of(DoubleChromosome.of(domain)), gt -> gt.getGene().getAllele() ); }
@Override public Codec<ISeq<Rect>, AnyGene<Rect>> codec() { return Codec.of( Genotype.of(AnyChromosome.of( () -> Rect.newInstance(_outer), a -> true, a -> true, MAX_RECT_COUNT )), gt -> gt.getChromosome().stream() .map(AnyGene::getAllele) .filter(r -> r != Rect.EMPTY) .collect(ISeq.toISeq()) ); }
/** * Create a permutation {@code Codec} of integer in the range * {@code [0, length)}. * * @param length the number of permutation elements * @return a permutation {@code Codec} of integers * @throws IllegalArgumentException if the {@code length} is smaller than * one. */ public static Codec<int[], EnumGene<Integer>> ofPermutation(final int length) { require.positive(length); return Codec.of( Genotype.of(PermutationChromosome.ofInteger(length)), gt -> gt.getChromosome().stream() .mapToInt(EnumGene::getAllele) .toArray() ); }
/** * Return a scalar {@code Codec} for the given range. * * @param domain the domain of the returned {@code Codec} * @return a new scalar {@code Codec} with the given domain. * @throws NullPointerException if the given {@code domain} is {@code null} */ public static Codec<Integer, IntegerGene> ofScalar(final IntRange domain) { requireNonNull(domain); return Codec.of( Genotype.of(IntegerChromosome.of(domain)), gt -> gt.getChromosome().getGene().getAllele() ); }
/** * Create a vector {@code Codec} for the given ranges. Each vector element * might have a different domain. The vector length is equal to the number * of domains. * * @param domains the domain ranges * @return a new vector {@code Codec} * @throws NullPointerException if one of the arguments is {@code null} * @throws IllegalArgumentException if the {@code domains} array is empty */ public static Codec<long[], LongGene> ofVector(final LongRange... domains) { if (domains.length == 0) { throw new IllegalArgumentException("Domains must not be empty."); } final ISeq<LongChromosome> chromosomes = Stream.of(domains) .peek(Objects::requireNonNull) .map(LongGene::of) .map(LongChromosome::of) .collect(ISeq.toISeq()); return Codec.of( Genotype.of(chromosomes), gt -> { final long[] args = new long[gt.length()]; for (int i = gt.length(); --i >= 0;) { args[i] = gt.getChromosome(i).getGene().longValue(); } return args; } ); }
@Override public Codec<ISeq<BitGene>, BitGene> codec() { return Codec.of( Genotype.of(BitChromosome.of(_length, _onesProbability)), gt -> gt.getChromosome().toSeq() ); }
/** * Create a permutation {@code Codec} with the given alleles. * * @param alleles the alleles of the permutation * @param <T> the allele type * @return a new permutation {@code Codec} * @throws IllegalArgumentException if the given allele array is empty * @throws NullPointerException if one of the alleles is {@code null} */ public static <T> Codec<ISeq<T>, EnumGene<T>> ofPermutation(final ISeq<? extends T> alleles) { if (alleles.isEmpty()) { throw new IllegalArgumentException( "Empty allele array is not allowed." ); } return Codec.of( Genotype.of(PermutationChromosome.of(alleles)), gt -> gt.getChromosome().stream() .map(EnumGene::getAllele) .collect(ISeq.toISeq()) ); }
/** * Return a scala {@code Codec} with the given allele {@link Supplier} and * allele {@code validator}. The {@code supplier} is responsible for * creating new random alleles. * * @see #ofScalar(Supplier, Predicate) * @see AnyGene#of(Supplier) * @see AnyChromosome#of(Supplier) * * @param <A> the allele type * @param supplier the allele-supplier which is used for creating new, * random alleles * @return a new {@code Codec} with the given parameters * @throws NullPointerException if the parameter is {@code null} */ public static <A> Codec<A, AnyGene<A>> ofScalar( final Supplier<? extends A> supplier ) { return Codec.of( Genotype.of(AnyChromosome.of(supplier)), gt -> gt.getGene().getAllele() ); }
/** * Return a vector {@code Codec} for the given range. All vector values * are restricted by the same domain. * * @param domain the domain of the vector values * @param length the vector length * @return a new vector {@code Codec} * @throws NullPointerException if the given {@code domain} is {@code null} * @throws IllegalArgumentException if the {@code length} is smaller than * one. */ public static Codec<int[], IntegerGene> ofVector( final IntRange domain, final int length ) { requireNonNull(domain); require.positive(length); return Codec.of( Genotype.of(IntegerChromosome.of(domain, length)), gt -> gt.getChromosome().as(IntegerChromosome.class).toArray() ); }
/** * Return a vector {@code Codec} for the given range. All vector values * are restricted by the same domain. * * @param domain the domain of the vector values * @param length the vector length * @return a new vector {@code Codec} * @throws NullPointerException if the given {@code domain} is {@code null} * @throws IllegalArgumentException if the {@code length} is smaller than * one. */ public static Codec<long[], LongGene> ofVector( final LongRange domain, final int length ) { requireNonNull(domain); require.positive(length); return Codec.of( Genotype.of(LongChromosome.of(domain, length)), gt -> gt.getChromosome().as(LongChromosome.class).toArray() ); }
/** * Return a vector {@code Codec} for the given range. All vector values * are restricted by the same domain. * * @param domain the domain of the vector values * @param length the vector length * @return a new vector {@code Codec} * @throws NullPointerException if the given {@code domain} is {@code null} * @throws IllegalArgumentException if the {@code length} is smaller than * one. */ public static Codec<double[], DoubleGene> ofVector( final DoubleRange domain, final int length ) { requireNonNull(domain); require.positive(length); return Codec.of( Genotype.of(DoubleChromosome.of(domain, length)), gt -> gt.getChromosome().as(DoubleChromosome.class).toArray() ); }
@Test public void streamWithInitialGenotypes() { final Problem<Integer, IntegerGene, Integer> problem = Problem.of( a -> a, Codec.of( Genotype.of(IntegerChromosome.of(0, 1000)), g -> g.getGene().getAllele() ) ); final int genotypeCount = 10; final int max = 1000; final ISeq<Genotype<IntegerGene>> genotypes = IntRange.of(1, genotypeCount) .stream() .mapToObj(i -> IntegerChromosome.of(IntegerGene.of(max, 0, max))) .map(Genotype::of) .collect(ISeq.toISeq()); final Engine<IntegerGene, Integer> engine = Engine.builder(problem) .build(); final EvolutionResult<IntegerGene, Integer> result = engine.stream(genotypes) .limit(1) .collect(EvolutionResult.toBestEvolutionResult()); final long maxCount = result.getPopulation().stream() .filter(pt -> pt.getFitness() == max) .count(); Assert.assertTrue(maxCount >= genotypeCount); }
@Test(invocationCount = 5) public void onesCountLimit() { final Problem<ISeq<BitGene>, BitGene, Integer> problem = Problem.of( genes -> (int)genes.stream().filter(BitGene::getBit).count(), Codec.of( Genotype.of(BitChromosome.of(20, 0.125)), gt -> gt.getChromosome().toSeq() ) ); final Engine<BitGene, Integer> engine = Engine.builder(problem) .build(); final EvolutionResult<BitGene, Integer> result = engine.stream() .limit(Limits.byPopulationConvergence(0.015)) .collect(toBestEvolutionResult()); Assert.assertTrue( result.getTotalGenerations() < 2901, "Gen: " + result.getTotalGenerations() ); }
@Test(invocationCount = 5) public void onesCountLimit() { final Problem<ISeq<BitGene>, BitGene, Integer> problem = Problem.of( genes -> (int)genes.stream().filter(BitGene::getBit).count(), Codec.of( Genotype.of(BitChromosome.of(20, 0.125)), gt -> gt.getChromosome().toSeq() ) ); final Engine<BitGene, Integer> engine = Engine.builder(problem) .build(); final EvolutionResult<BitGene, Integer> result = engine.stream() .limit(Limits.byFitnessConvergence(5, 10, 0.01)) .collect(EvolutionResult.toBestEvolutionResult()); Assert.assertTrue( result.getTotalGenerations() < 50, "Gen: " + result.getTotalGenerations() ); }
public static void main(final String[] args) { final Problem<int[][], IntegerGene, Integer> problem = Problem.of( Matrix::fitness, Codec.of( Genotype.of(IntegerChromosome.of(IntRange.of(0, 10), 3), 3), gt -> gt.stream() .map(ch -> ch.stream() .mapToInt(IntegerGene::intValue).toArray()) .toArray(int[][]::new) ) ); final Engine<IntegerGene, Integer> engine = Engine.builder(problem).build(); final Genotype<IntegerGene> gt = engine.stream() .limit(Limits.byFixedGeneration(20)) .collect(EvolutionResult.toBestGenotype()); final int[][] best = problem.codec().decode(gt); print(best); }
@Test public void variableDoubleSum() { final Problem<int[], IntegerGene, Integer> problem = Problem.of( array -> IntStream.of(array).sum(), Codec.of( Genotype.of(IntegerChromosome.of(0, 100, IntRange.of(10, 100))), gt -> gt.getChromosome().as(IntegerChromosome.class).toArray() ) ); final Engine<IntegerGene, Integer> engine = Engine.builder(problem) .alterers( new Mutator<>(), new SwapMutator<>()) .selector(new TournamentSelector<>()) .minimizing() .build(); final int[] result = problem.codec().decode( engine.stream() .limit(100) .collect(EvolutionResult.toBestGenotype()) ); Assert.assertTrue(result.length < 50, "result length: " + result.length); //System.out.println(result.length); //System.out.println(Arrays.toString(result)); }
static Codec<Tuple, DoubleGene> codec( final IntRange v1Domain, final LongRange v2Domain, final DoubleRange v3Domain ) { return Codec.of( Genotype.of( DoubleChromosome.of(DoubleRange.of(v1Domain.getMin(), v1Domain.getMax())), DoubleChromosome.of(DoubleRange.of(v2Domain.getMin(), v2Domain.getMax())), DoubleChromosome.of(v3Domain) ), gt -> new Tuple( gt.getChromosome(0).getGene().intValue(), gt.getChromosome(1).getGene().longValue(), gt.getChromosome(2).getGene().doubleValue() ) ); }
public static void main(final String[] args) throws Exception { final Problem<BitChromosome, BitGene, Integer> count = Problem.of( BitChromosome::bitCount, Codec.of( Genotype.of(BitChromosome.of(10)), gt -> gt.getChromosome().as(BitChromosome.class) ) ); final Engine<BitGene, Integer> engine = Engine.builder(count).build(); final EvolutionResult<BitGene, Integer> result = engine.stream() .limit(10) .collect(EvolutionResult.toBestEvolutionResult()); final ISeq<Genotype<BitGene>> genotypes = result.getGenotypes(); Writers.write(System.out, genotypes.asList(), Writers.BitChromosome.writer()); Readers.read(System.in, Readers.BitChromosome.reader()); engine.stream(genotypes); }