/*
 * 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.evaluation;

import static java.lang.Math.log10;
import static java.lang.Math.max;
import static java.lang.Math.pow;
import static java.lang.String.format;

import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.function.Predicate;
import java.util.stream.IntStream;

import org.jenetics.BitGene;
import org.jenetics.engine.Engine;
import org.jenetics.engine.EvolutionResult;
import org.jenetics.engine.limit;
import org.jenetics.problem.Knapsack;
import org.jenetics.trial.Params;
import org.jenetics.trial.TrialMeter;
import org.jenetics.util.ISeq;
import org.jenetics.util.LCG64ShiftRandom;

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

	private static final double GEN_BASE = pow(10, log10(100)/20.0);
	private static final File BASE_OUTPUT_DIR =
		new File("org.jenetics/src/test/scripts/diagram");


	private static final Params<Integer> GENERATIONS = Params.of(
		"Generations",
		IntStream.rangeClosed(1, 50)
			.map(i -> max((int)pow(GEN_BASE, i), i))
			.mapToObj(Integer::new)
			.collect(ISeq.toISeq())
	);


	public static void main(final String[] args) throws IOException {
		final Path outputPath;
		if (args.length > 1) {
			outputPath = Paths.get(args[0]);
		} else {
			outputPath = Paths.get("steady_fitness.xml");
		}

		final TrialMeter<Integer> trialMeter;
		if (Files.exists(outputPath)) {
			trialMeter = TrialMeter.read(outputPath);

			info("Continue existing trial: '%s'.", outputPath.toAbsolutePath());
			info("    " + trialMeter);
		} else {
			trialMeter = TrialMeter.of(
				"Steady fitness", "Create steady fitness performance measures",
				GENERATIONS, "Generation", "Fitness"
			);

			info("Writing results to '%s'.", outputPath.toAbsolutePath());
		}

		final Engine<BitGene, Double> engine = Knapsack.engine(new LCG64ShiftRandom(10101));

		for (int i = 0; i < 500; ++i) {
			trialMeter.sample(generations -> {
				final Predicate<? super EvolutionResult<BitGene, Double>>
					terminator = limit.bySteadyFitness(generations);

				try {
					trialMeter.write(outputPath);
					info(trialMeter.toString());
				} catch (IOException e) {
					throw new UncheckedIOException(e);
				}
				final EvolutionResult<BitGene, Double> result = engine.stream()
					.limit(terminator)
					.collect(EvolutionResult.toBestEvolutionResult());

				return new double[]{
					result.getTotalGenerations(),
					result.getBestFitness()
				};
			});

			trialMeter.write(outputPath);
		}
	}

	private static void info(final String pattern, final Object... params) {
		final LocalDateTime time = LocalDateTime.now();
		System.out.println("" + time + " - " + format(pattern, params));
	}

}

@@ -1113,16 +1113,84 @@
 teTime;%0A
+import java.time.format.DateTimeFormatter;%0Aimport java.util.Arrays;%0A
 import j
@@ -1218,16 +1218,16 @@
 dicate;%0A
-
 import j
@@ -2285,22 +2285,19 @@
 et(%22
-steady_fitness
+trial_meter
 .xml
@@ -3482,16 +3482,127 @@
 %09%09%7D%0A%09%7D%0A%0A
+%09private static final DateTimeFormatter FORMATTER =%0A%09%09DateTimeFormatter.ofPattern(%22yyyy-MM-dd HH:mm:ss.SSS%22);%0A%0A
 %09private
@@ -3742,17 +3742,39 @@
 tln(
+%0A%09%09%09
 %22%22 + 
+FORMATTER.format(
 time
+)
  + %22
@@ -3803,16 +3803,19 @@
  params)
+%0A%09%09
 );%0A%09%7D%0A%0A%7D

Improve logging.