Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3133_ProblemModifiers/HeuristicLab.Problems.Modifiers/Modifier/EvaluationLoggingProblemModifier.cs

Last change on this file was 18029, checked in by bwerth, 3 years ago

#3133 added implementation of problem modifiers

File size: 4.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.IO;
25using System.Linq;
26using System.Text;
27using HEAL.Attic;
28using HeuristicLab.Common;
29using HeuristicLab.Core;
30using HeuristicLab.Data;
31using HeuristicLab.Encodings.IntegerVectorEncoding;
32using HeuristicLab.Encodings.RealVectorEncoding;
33using HeuristicLab.Optimization;
34using HeuristicLab.Parameters;
35
36namespace HeuristicLab.Problems.Modifiers {
37  [StorableType("FADAA1BF-7B7A-4E28-AA15-22AF56D63CFE")]
38  [Item("MultiObjectiveEvaluationLogProblemModifier", "A problem modifier that logs evaluations in a file")]
39  public class EvaluationLoggingProblemModifier : ProblemModifier {
40    private readonly object fileLock = new object();
41    #region ParameterNames
42    private const string LogFileParameterName = "LogFile";
43    #endregion
44
45    #region Parameters
46    public IValueParameter<FileValue> LogFileParameter => (IValueParameter<FileValue>)Parameters[LogFileParameterName];
47    #endregion
48
49    #region ParameterNames
50    public FileValue LogFile => LogFileParameter.Value;
51    #endregion
52
53    #region Constructors & Cloning
54    [StorableConstructor]
55    protected EvaluationLoggingProblemModifier(StorableConstructorFlag _) : base(_) { }
56    protected EvaluationLoggingProblemModifier(EvaluationLoggingProblemModifier original, Cloner cloner) : base(original, cloner) {
57    }
58    public EvaluationLoggingProblemModifier() {
59      var defaultFileName = $"{Environment.CurrentDirectory}\\Log_{Guid.NewGuid()}.txt";
60      var value = new FileValue();
61      value.StringValue.Value = defaultFileName;
62      Parameters.Add(new ValueParameter<FileValue>(LogFileParameterName, "The log file into which evaluations should be logged.", value));
63    }
64    [StorableHook(HookType.AfterDeserialization)]
65    private void AfterDeserialization() { }
66    public override IDeepCloneable Clone(Cloner cloner) {
67      return new EvaluationLoggingProblemModifier(this, cloner);
68    }
69    #endregion
70
71    #region ProblemModifier
72    public override double[] ModifiedEvaluate(Individual individual, IRandom random) {
73      var qualities = base.ModifiedEvaluate(individual, random);
74      lock (fileLock) { LogResultsToFile(individual, LogFile.Value, Encoding); }
75      return qualities;
76    }
77    #endregion
78
79    #region Helpers
80    private static void LogResultsToFile(Individual individual, string logFilePath, IEncoding enc) {
81      if (string.IsNullOrEmpty(logFilePath)) throw new ArgumentException("Log path is null or empty");
82      var logFile = new FileInfo(logFilePath);
83      if (!logFile.Exists) {
84        logFile.Directory?.Create();
85        logFile.Create();
86      }
87      var logLines = new List<string>();
88      var sb = new StringBuilder();
89      var inputs = ExtractInputs(individual, enc).ToArray();
90      var additionalInfo = ExtractAdditionalInfo(individual, enc);
91      if (logFile.Length == 0) {
92        var digits = Math.Ceiling(Math.Log10(inputs.Length));
93        var header = Enumerable
94          .Range(0, inputs.Length)
95          .Select(x => string.Format($"X{{0:D{digits}}}", x))
96          .Concat(additionalInfo.Select(x => x.Item1));
97        logLines.Add(string.Join(";", header));
98        sb.Clear();
99      }
100      logLines.Add(string.Join(";", inputs.Concat(additionalInfo.Select(x => x.Item2))));
101      sb.Clear();
102      File.AppendAllLines(logFilePath, logLines);
103    }
104    private static Tuple<string, string>[] ExtractAdditionalInfo(Individual individual, IEncoding enc) {
105      return individual.Values.Where(x => x.Key != enc.Name).OrderBy(x => x.Key).Select(x => Tuple.Create(x.Key, x.Value.ToString())).ToArray();
106    }
107    private static IEnumerable<object> ExtractInputs(Individual individual, IEncoding encoding) {
108      var encodingType = encoding.GetType();
109      if (encodingType == typeof(IntegerVectorEncoding))
110        return individual.IntegerVector().Select(x => (object)x);
111      if (encodingType == typeof(RealVectorEncoding))
112        return individual.RealVector().Select(x => (object)x);
113      throw new ArgumentException("This input encoding is not supported yet");
114    }
115    #endregion
116  }
117}
Note: See TracBrowser for help on using the repository browser.