using System; using System.Collections.Generic; namespace HeuristicLab.Problems.ProgramSynthesis.Push.Problem { using HeuristicLab.BenchmarkSuite; using HeuristicLab.BenchmarkSuite.Problems; using HeuristicLab.Core; using HeuristicLab.Optimization; using HeuristicLab.Problems.ProgramSynthesis.Push.Expressions; using HeuristicLab.Problems.ProgramSynthesis.Push.Interpreter; using HeuristicLab.Problems.ProgramSynthesis.Push.Stack; public static class PushEvaluator { public static double Evaluate(IPushInterpreter interpreter, PushProgram program, Example example, double worstResult) { interpreter.BooleanStack.Push(example.InputBoolean); interpreter.IntegerStack.Push(example.InputInt); interpreter.FloatStack.Push(example.InputFloat); interpreter.Run(program); return GetDiff(example.OutputInt, interpreter.IntegerStack, worstResult, LongDiffer) + GetDiff(example.OutputFloat, interpreter.FloatStack, worstResult, DoubleDiffer) + GetDiff(example.OutputBoolean, interpreter.BooleanStack, worstResult, BooleanDiffer); } public static double Evaluate(PushProgram program, PushInterpreterPool pool, IRandom random, Data data, int startIndex, int endIndex) { if (endIndex - startIndex <= 0) return default(double); var result = 0d; using (var interpreter = pool.Create(random)) { for (var i = startIndex; i < endIndex; i++) { result += Evaluate(interpreter, program, data.Examples[i], data.WorstResult); interpreter.Clear(); } } return result / (endIndex - startIndex); } public static double Evaluate(Individual individual, PushInterpreterPool pool, IRandom random, Data data, int startIndex, int endIndex) { var program = individual.PushProgram(pool.PushGpConfiguration.EnabledExpressions as IReadOnlyList); return Evaluate(program, pool, random, data, startIndex, endIndex); } private static double DoubleDiffer(double a, double b) { var result = a - b; return result == double.MinValue ? double.MaxValue : Math.Abs(result); } private static double LongDiffer(long a, long b) { var result = a - b; return result == long.MinValue ? long.MaxValue : Math.Abs(result); } private static double BooleanDiffer(bool a, bool b) { return a && b ? 0 : a || b ? 1 : 2; } private static double GetDiff(IReadOnlyList estimated, IStack resultStack, double worstResult, Func differ) where T : IComparable { var count = Math.Min(estimated.Count, resultStack.Count); var result = resultStack.Peek(count); var comparableLength = Math.Min(estimated.Count, result.Length); var diff = 0d; for (var i = 0; i < comparableLength; i++) { diff += Math.Min(differ(estimated[i], result[0]), worstResult); } if (estimated.Count > result.Length) { diff += worstResult * (estimated.Count - comparableLength); } return diff; } } }