/*
 * 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@gmx.at)
 */
package org.jenetics.example;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;

import org.jenetics.BitGene;
import org.jenetics.Mutator;
import org.jenetics.RouletteWheelSelector;
import org.jenetics.SinglePointCrossover;
import org.jenetics.TournamentSelector;
import org.jenetics.engine.Engine;
import org.jenetics.engine.EvolutionResult;
import org.jenetics.engine.Problem;
import org.jenetics.example.Knapsack.Item;
import org.jenetics.util.IO;
import org.jenetics.util.ISeq;
import org.jenetics.util.RandomRegistry;

/**
 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
 * @version 3.8
 * @since 3.8
 */
public class EvolutionResume {

	// The problem definition.
	private final Problem<ISeq<Item>, BitGene, Double> knapsack =
		Knapsack.of(250, RandomRegistry.getRandom());

	// The evolution engine.
	private final Engine<BitGene, Double> engine = Engine.builder(knapsack)
		.populationSize(100)
		.survivorsSelector(new TournamentSelector<>(5))
		.offspringSelector(new RouletteWheelSelector<>())
		.alterers(
			new Mutator<>(0.03),
			new SinglePointCrossover<>(0.125))
		.build();

	// Run the evolution.
	private EvolutionResult<BitGene, Double> run(
		final EvolutionResult<BitGene, Double> last,
		final AtomicBoolean proceed
	) {
		System.out.println("Starting evolution with existing result.");

		return (last != null ? engine.stream(last) : engine.stream())
			.limit(r -> proceed.get())
			.peek(r -> {
				if (r.getGeneration()%5000 == 0) {
					System.out.println("    generation " + r.getGeneration());
				}
			})
			.collect(EvolutionResult.toBestEvolutionResult());
	}

	public static void main(final String[] args)
		throws IOException, InterruptedException, ExecutionException
	{
		if (args.length == 0) {
			System.out.println("Missing evolution result path.");
			System.exit(1);
		}

		// The result path.
		final Path resultPath = Paths.get(args[0]);

		@SuppressWarnings("unchecked")
		final EvolutionResult<BitGene, Double> result = Files.exists(resultPath)
			? (EvolutionResult<BitGene, Double>)IO.object.read(resultPath)
			: null;

		final AtomicBoolean proceed = new AtomicBoolean(true);
		final EvolutionResume evolution = new EvolutionResume();

		final CompletableFuture<EvolutionResult<BitGene, Double>> future =
			CompletableFuture.supplyAsync(() -> evolution.run(result, proceed));

		System.out.println("Evolution started.");

		// Read console command: type 'exit' for stopping evolution.
		while (!System.console().readLine().equals("exit"))
		proceed.set(false);
		System.out.println("Evolution stopped.");

		// Writing the best evolution result to file.
		System.out.println("Writing evolution result.");
		IO.object.write(future.get(), resultPath);

		System.out.println("Best fitness: " + future.get().getBestFitness());
	}

}

@@ -776,28 +776,43 @@
 ort 
+static 
 java.
+n
 io.
-IOException;
+file.Files.exists;%0A
 %0Aimp
@@ -820,30 +820,30 @@
 rt java.
-n
 io.
-file.Files
+IOException
 ;%0Aimport
@@ -1070,162 +1070,8 @@
 ne;%0A
-import org.jenetics.Mutator;%0Aimport org.jenetics.RouletteWheelSelector;%0Aimport org.jenetics.SinglePointCrossover;%0Aimport org.jenetics.TournamentSelector;%0A
 impo
@@ -1477,17 +1477,16 @@
 esume %7B%0A
-%0A
 %09// The 
@@ -1743,185 +1743,8 @@
 00)%0A
-%09%09.survivorsSelector(new TournamentSelector%3C%3E(5))%0A%09%09.offspringSelector(new RouletteWheelSelector%3C%3E())%0A%09%09.alterers(%0A%09%09%09new Mutator%3C%3E(0.03),%0A%09%09%09new SinglePointCrossover%3C%3E(0.125))%0A
 %09%09.b
@@ -2069,139 +2069,8 @@
 ())%0A
-%09%09%09.peek(r -%3E %7B%0A%09%09%09%09if (r.getGeneration()%255000 == 0) %7B%0A%09%09%09%09%09System.out.println(%22    generation %22 + r.getGeneration());%0A%09%09%09%09%7D%0A%09%09%09%7D)%0A
 %09%09%09.
@@ -2494,22 +2494,16 @@
 esult = 
-Files.
 exists(r
@@ -2672,25 +2672,22 @@
 nResume 
-evolution
+resume
  = new E
@@ -2813,25 +2813,22 @@
 c(() -%3E 
-evolution
+resume
 .run(res
@@ -2843,17 +2843,16 @@
 ceed));%0A
-%0A
 %09%09System
@@ -3296,7 +3296,8 @@
 %0A%09%7D%0A
-%0A
 %7D%0A
+%0A%0A

Implement evolution resume example.