/*
 * Java Genetic Algorithm Library (@__identifier__@).
 * Copyright (c) @__year__@ 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 (franz.wilhelmstoetter@gmail.com)
 */
package io.jenetics.example;

import static io.jenetics.engine.limit.byFixedGeneration;

import java.util.Random;

import io.jenetics.AnyChromosome;
import io.jenetics.AnyGene;
import io.jenetics.Genotype;
import io.jenetics.RouletteWheelSelector;
import io.jenetics.SinglePointCrossover;
import io.jenetics.SwapMutator;
import io.jenetics.engine.Codec;
import io.jenetics.engine.Engine;
import io.jenetics.engine.EvolutionResult;
import io.jenetics.util.ISeq;
import io.jenetics.util.RandomRegistry;

public class RectFill {

	private static final int MAX_RECT_COUNT = 100;

	static final class Rect {
		static final Rect EMPTY = new Rect(-1, -1, -1, -1);
		final int x1, x2, y1, y2;
		Rect(final int x1, final int x2, final int y1, final int y2) {
			this.x1 = x1; this.x2 = x2; this.y1 = y1; this.y2 = y2;
		}

		static Rect newInstance() {
			final Random random = RandomRegistry.getRandom();
			return random.nextBoolean()
				? new Rect(
					random.nextInt(100),
					random.nextInt(100),
					random.nextInt(100),
					random.nextInt(100))
				: EMPTY;
		}
	}

	static final Codec<ISeq<Rect>, AnyGene<Rect>> CODEC = Codec.of(
		Genotype.of(AnyChromosome.of(Rect::newInstance, MAX_RECT_COUNT)),
		gt -> gt.getChromosome()
				.stream()
				.map(AnyGene::getAllele)
				.filter(r -> r != Rect.EMPTY)
				.collect(ISeq.toISeq())
	);

	static int fitness(final ISeq<Rect> rects) {
		// Here comes your fitness function.
		return rects.length();
	}

	public static void main(final String[] args) {
		final Engine<AnyGene<Rect>, Integer> engine = Engine
			.builder(RectFill::fitness, CODEC)
			.offspringSelector(new RouletteWheelSelector<>())
			.alterers(
				new SwapMutator<>(),
				new SinglePointCrossover<>())
			.build();

		final ISeq<Rect> best = CODEC.decode(
			engine.stream()
				.limit(byFixedGeneration(10))
				.collect(EvolutionResult.toBestGenotype())
		);

		System.out.println(best);
	}

}

@@ -850,16 +850,52 @@
 .Random;
+%0Aimport java.util.function.Function;
 %0A%0Aimport
@@ -1842,16 +1842,187 @@
 %09%09%7D%0A%09%7D%0A%0A
+%09static boolean valid(final ISeq%3C? super Rect%3E objects) %7B%0A%09%09@SuppressWarnings(%22unchecked%22) // Issue: #256%0A%09%09final ISeq%3CRect%3E seq = (ISeq%3CRect%3E)objects;%0A%09%09return true;%0A%09%7D%0A%0A
 %09static 
@@ -2106,19 +2106,29 @@
 omosome.
-of(
+%3CRect%3Eof(%0A%09%09%09
 Rect::ne
@@ -2137,17 +2137,54 @@
 nstance,
- 
+%0A%09%09%09a -%3E true,%0A%09%09%09RectFill::valid,%0A%09%09%09
 MAX_RECT
@@ -2189,16 +2189,19 @@
 CT_COUNT
+%0A%09%09
 )),%0A%09%09gt
@@ -2333,16 +2333,17 @@
 ))%0A%09);%0A%0A
+%0A
 %09static 
@@ -2448,16 +2448,91 @@
 ();%0A%09%7D%0A%0A
+%09static boolean gtv(final Genotype%3CAnyGene%3CRect%3E%3E gt) %7B%0A%09%09return true;%0A%09%7D%0A%0A
 %09public 
@@ -2626,16 +2626,16 @@
  Engine%0A
-
 %09%09%09.buil
@@ -2664,16 +2664,87 @@
  CODEC)%0A
+%09%09%09.individualCreationRetries(10)%0A%09%09%09.genotypeValidator(RectFill::gtv)%0A
 %09%09%09.offs

Extend example.