Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3026_IntegrationIntoSymSpace/HeuristicLab.JsonInterface/JsonTemplateInstantiator.cs @ 18055

Last change on this file since 18055 was 18055, checked in by dpiringe, 3 years ago

#3026

  • added StorableTypeAttribute and StorableConstructorAttribute to all JsonItems
  • added a new JsonItem ListJsonItem + Interfaces IListJsonItem
  • renamed SymRegPythonProcessor to RunCollectionSRSolutionPythonFormatter
  • removed Interface IResultCollectionProcessor -> using the interface IRunCollectionModifier now (has aleady implementations)
  • renamed all related variables/fields/properties with a connection to ResultCollectionProcessor
  • added new implementations for IRunCollectionModifier
File size: 7.0 KB
RevLine 
[17828]1using System;
2using System.Collections.Generic;
[17263]3using System.IO;
4using System.Linq;
[18030]5using System.Text.RegularExpressions;
[17379]6using HEAL.Attic;
[17263]7using HeuristicLab.Optimization;
[18046]8using HeuristicLab.PluginInfrastructure;
[17263]9using Newtonsoft.Json.Linq;
10
[17284]11namespace HeuristicLab.JsonInterface {
[17481]12  public readonly struct InstantiatorResult {
13    public InstantiatorResult(IOptimizer optimizer, IEnumerable<IResultJsonItem> configuredResultItems) {
14      Optimizer = optimizer;
15      ConfiguredResultItems = configuredResultItems;
[18055]16      RunCollectionModifiers = Enumerable.Empty<IRunCollectionModifier>();
[17481]17    }
18
[18055]19    public InstantiatorResult(IOptimizer optimizer, IEnumerable<IResultJsonItem> configuredResultItems, IEnumerable<IRunCollectionModifier> runCollectionModifiers) {
[18046]20      Optimizer = optimizer;
21      ConfiguredResultItems = configuredResultItems;
[18055]22      RunCollectionModifiers = runCollectionModifiers;
[18046]23    }
24
[17481]25    public IOptimizer Optimizer { get; }
26    public IEnumerable<IResultJsonItem> ConfiguredResultItems { get; }
[18055]27    public IEnumerable<IRunCollectionModifier> RunCollectionModifiers { get; }
[17477]28  }
29
30
[17353]31  /// <summary>
[17477]32  /// Class to instantiate an IAlgorithm object with a json interface template and config.
[17353]33  /// </summary>
[17477]34  public class JsonTemplateInstantiator {
[17263]35
[18039]36    #region Constants
37    private const string RelativePathCurrentDirectoryRegex = @"^(\.)";
38    #endregion
39
[17477]40    #region Private Properties
41    private JToken Template { get; set; }
42    private JArray Config { get; set; }
43    private IDictionary<string, IJsonItem> Objects { get; set; } = new Dictionary<string, IJsonItem>();
44    #endregion
[17442]45
[17353]46    /// <summary>
47    /// Instantiate an IAlgorithm object with a template and config.
48    /// </summary>
49    /// <param name="templateFile">Template file (json), generated with JCGenerator.</param>
50    /// <param name="configFile">Config file (json) for the template.</param>
[17395]51    /// <returns>confugrated IOptimizer object</returns>
[17477]52    public static InstantiatorResult Instantiate(string templateFile, string configFile = null) {
53      JsonTemplateInstantiator instantiator = new JsonTemplateInstantiator();
54      return instantiator.ExecuteInstantiaton(templateFile, configFile);
55    }
[17322]56
[17477]57    #region Helper
58    private InstantiatorResult ExecuteInstantiaton(string templateFile, string configFile = null) {
59
60      #region Parse Files
[18040]61      string templateFileFullPath = Path.GetFullPath(templateFile);
[17477]62      Template = JToken.Parse(File.ReadAllText(templateFile));
[17330]63      if(!string.IsNullOrEmpty(configFile))
[18040]64        Config = JArray.Parse(File.ReadAllText(Path.GetFullPath(configFile)));
[17477]65      #endregion
[17379]66
[18050]67      #region Deserialize HL File
[17379]68      // extract metadata information
[18039]69      string relativePath = Template[Constants.Metadata][Constants.HLFileLocation].ToString().Trim(); // get relative path
[18030]70      // convert to absolute path
[18039]71      if (Regex.IsMatch(relativePath, RelativePathCurrentDirectoryRegex))
72        relativePath = relativePath.Remove(0, 2); // remove first 2 chars -> indicates the current directory
[17263]73
[18040]74      string hLFileLocation = Path.Combine(Path.GetDirectoryName(templateFileFullPath), relativePath);
[17379]75      ProtoBufSerializer serializer = new ProtoBufSerializer();
[17395]76      IOptimizer optimizer = (IOptimizer)serializer.Deserialize(hLFileLocation);
[17477]77      #endregion
[17379]78
79      // collect all parameterizedItems from template
[17477]80      CollectParameterizedItems(optimizer);
[17394]81     
[17477]82      if (Config != null)
83        MergeTemplateWithConfig();
[17322]84
[17477]85      // get algorithm root item
86      IJsonItem rootItem = Objects.First().Value;
[17560]87
[17828]88      // validation
89      ValidationResult validationResult = rootItem.GetValidator().Validate();
90      if (!validationResult.Success)
91        throw validationResult.GenerateException();
[17560]92
[17379]93      // inject configuration
[17477]94      JsonItemConverter.Inject(optimizer, rootItem);
[17266]95
[18055]96      return new InstantiatorResult(optimizer, CollectResults(), CollectRunCollectionModifiers());
[18050]97    }
98
99    /// <summary>
100    /// Instantiates all defined (in template) ResultCollectionProcessors and injects the configured parameters.
101    /// </summary>
[18055]102    private IEnumerable<IRunCollectionModifier> CollectRunCollectionModifiers() {
103      IList<IRunCollectionModifier> runCollectionModifiers = new List<IRunCollectionModifier>();
104      foreach (JObject obj in Template[Constants.RunCollectionModifiers]) {
[18050]105        var guid = obj["GUID"].ToString();
106        var parameters = obj[Constants.Parameters];
107        var type = Mapper.StaticCache.GetType(new Guid(guid));
[18055]108        var rcp = (IRunCollectionModifier)Activator.CreateInstance(type);
[18050]109        var rcpItem = JsonItemConverter.Extract(rcp);
110
111        foreach (JObject param in parameters) {
112          var path = param[nameof(IJsonItem.Path)].ToString();
113          foreach (var item in rcpItem)
114            if (item.Path == path)
115              item.SetJObject(param);
[18046]116        }
[18050]117
118        JsonItemConverter.Inject(rcp, rcpItem);
[18055]119        runCollectionModifiers.Add(rcp);
[18046]120      }
[18055]121      return runCollectionModifiers;
[17263]122    }
123
[17477]124    private IEnumerable<IResultJsonItem> CollectResults() {
125      IList<IResultJsonItem> res = new List<IResultJsonItem>();
126      foreach(JObject obj in Template[Constants.Results]) {
[17834]127        var resultItem = new ResultJsonItem();
128        resultItem.SetJObject(obj);
129        res.Add(resultItem);
[17442]130      }
131      return res;
132    }
133
[17477]134    private void CollectParameterizedItems(IOptimizer optimizer) {
135      IJsonItem root = JsonItemConverter.Extract(optimizer);
136      Objects.Add(root.Path, root);
[17410]137
[17477]138      foreach (JObject obj in Template[Constants.Parameters]) {
[18050]139        string path = obj.Property(nameof(IJsonItem.Path)).Value.ToString();
[17477]140        foreach(var tmp in root) {
141          if(tmp.Path == path) {
142            tmp.SetJObject(obj);
143            Objects.Add(tmp.Path, tmp);
[17410]144          }
145        }
146      }
[17263]147    }
[17379]148   
[17477]149    private void MergeTemplateWithConfig() {
150      foreach (JObject obj in Config) {
[17322]151        // build item from config object
[18030]152        var prop = obj.Property("Path");
153        if (prop == null)
154          throw new ArgumentException("Path property is missing.");
155        string path = prop.Value.ToString();
[17322]156        // override default value
[17477]157        if (Objects.TryGetValue(path, out IJsonItem param)) {
[17483]158          // remove fixed template parameter from config => dont allow to copy them from concrete config
[17828]159          // TODO: shift this into JsonItems?
[17473]160          obj.Property(nameof(IIntervalRestrictedJsonItem<int>.Minimum))?.Remove();
161          obj.Property(nameof(IIntervalRestrictedJsonItem<int>.Maximum))?.Remove();
162          obj.Property(nameof(IConcreteRestrictedJsonItem<string>.ConcreteRestrictedItems))?.Remove();
[17828]163          obj.Property(nameof(IMatrixJsonItem.ColumnsResizable))?.Remove();
164          obj.Property(nameof(IMatrixJsonItem.RowsResizable))?.Remove();
165          obj.Property(nameof(IArrayJsonItem.Resizable))?.Remove();
[17473]166          // merge
[17477]167          param.SetJObject(obj);
[17410]168        } else throw new InvalidDataException($"No parameter with path='{path}' defined!");
[17322]169      }
170    }
171    #endregion
[17263]172  }
173}
Note: See TracBrowser for help on using the repository browser.