Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3026_IntegrationIntoSymSpace/HeuristicLab.JsonInterface/JCInstantiator.cs @ 17353

Last change on this file since 17353 was 17353, checked in by dpiringe, 4 years ago

#3026:

  • relocated GetMaxValue and GetMinValue from ValueTypeValueConverter into BaseConverter
  • fixed a bug in ConstrainedValueParameterConverter (from GetType().Name to ToString())
  • printing now PrettyNames for types
  • added comments
  • added StorableConverter.cs (not finished, maybe not a good converter)
  • added ValueRangeConverter.cs for DoubleRange and IntRange
  • added ParameterConverter.cs for default parameter conversion
File size: 8.0 KB
Line 
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using System.IO;
5using System.Linq;
6using System.Reflection;
7using System.Text;
8using System.Threading.Tasks;
9using HeuristicLab.Core;
10using HeuristicLab.Data;
11using HeuristicLab.Optimization;
12using HeuristicLab.SequentialEngine;
13using Newtonsoft.Json.Linq;
14
15namespace HeuristicLab.JsonInterface {
16  /// <summary>
17  /// Static class to instantiate an IAlgorithm object with a json interface template and config.
18  /// </summary>
19  public static class JCInstantiator {
20    private struct InstData {
21      public JToken Template { get; set; }
22      public JArray Config { get; set; }
23      public Dictionary<string, string> TypeList { get; set; }
24      public IDictionary<string, JsonItem> ParameterizedItems { get; set; }
25      public IDictionary<string, JsonItem> ConfigurableItems { get; set; }
26    }
27
28    /// <summary>
29    /// Instantiate an IAlgorithm object with a template and config.
30    /// </summary>
31    /// <param name="templateFile">Template file (json), generated with JCGenerator.</param>
32    /// <param name="configFile">Config file (json) for the template.</param>
33    /// <returns>confugrated IAlgorithm object</returns>
34    public static IAlgorithm Instantiate(string templateFile, string configFile = "") {
35      InstData instData = new InstData() {
36        TypeList = new Dictionary<string, string>(),
37        ParameterizedItems = new Dictionary<string, JsonItem>(),
38        ConfigurableItems = new Dictionary<string, JsonItem>()
39      };
40
41      //1. Parse Template and Config files
42      instData.Template = JToken.Parse(File.ReadAllText(templateFile));
43      if(!string.IsNullOrEmpty(configFile))
44        instData.Config = JArray.Parse(File.ReadAllText(configFile));
45      instData.TypeList = instData.Template[Constants.Types].ToObject<Dictionary<string, string>>();
46      string algorithmName = instData.Template[Constants.Metadata][Constants.Algorithm].ToString();
47      string problemName = instData.Template[Constants.Metadata][Constants.Problem].ToString();
48
49      //2. Collect all parameterizedItems from template
50      CollectParameterizedItems(instData);
51
52      //3. select all ConfigurableItems
53      SelectConfigurableItems(instData);
54
55      //4. if config != null -> merge Template and Config
56      if (instData.Config != null)
57        MergeTemplateWithConfig(instData);
58
59      //5. resolve the references between parameterizedItems
60      ResolveReferences(instData);
61
62      //6. get algorthm data and object
63      JsonItem algorithmData = GetData(algorithmName, instData);
64      IAlgorithm algorithm = CreateObject<IAlgorithm>(algorithmData, instData);
65
66      //7. get problem data and object
67      JsonItem problemData = GetData(problemName, instData);
68      IProblem problem = CreateObject<IProblem>(problemData, instData);
69      algorithm.Problem = problem;
70
71      //8. inject configuration
72      JsonItemConverter.Inject(algorithm, algorithmData);
73      JsonItemConverter.Inject(problem, problemData);
74
75      // TODO: let the engine be configurable
76      if (algorithm is EngineAlgorithm)
77        algorithm.Cast<EngineAlgorithm>().Engine = new SequentialEngine.SequentialEngine();
78
79      return algorithm;
80    }
81
82    #region Helper
83    private static void CollectParameterizedItems(InstData instData) {
84      foreach (JObject item in instData.Template[Constants.Objects]) {
85        JsonItem data = BuildJsonItem(item, instData);
86        instData.ParameterizedItems.Add(data.Path, data);
87      }
88    }
89
90    private static void SelectConfigurableItems(InstData instData) {
91      foreach (var item in instData.ParameterizedItems.Values) {
92        if (item.Parameters != null)
93          AddConfigurableItems(item.Parameters, instData);
94
95        if (item.Operators != null)
96          AddConfigurableItems(item.Operators, instData);
97      }
98    }
99
100    private static void AddConfigurableItems(IEnumerable<JsonItem> items, InstData instData) {
101      foreach (var item in items)
102        if (item.IsConfigurable)
103          instData.ConfigurableItems.Add(item.Path, item);
104    }
105
106    private static void ResolveReferences(InstData instData) {
107      foreach(var x in instData.ParameterizedItems.Values)
108        foreach (var p in x.Parameters)
109          if (p.Value is string) {
110            string key = p.Path;
111            if (p.Range != null)
112              key = $"{p.Path}.{p.Value.Cast<string>()}";
113
114            if (instData.ParameterizedItems.TryGetValue(key, out JsonItem value))
115              p.Reference = value;
116          }
117    }
118
119    private static void MergeTemplateWithConfig(InstData instData) {
120      foreach (JObject obj in instData.Config) {
121        // build item from config object
122        JsonItem item = BuildJsonItem(obj, instData);
123        // override default value
124        if (instData.ConfigurableItems.TryGetValue(item.Path, out JsonItem param)) {
125          param.Value = item.Value;
126          // override ActualName (for LookupParameters)
127          if (param.ActualName != null)
128            param.ActualName = item.ActualName;
129        } else throw new InvalidDataException($"No {Constants.FreeParameters.Trim('s')} with path='{item.Path}' defined!");
130      }
131    }
132
133    private static JsonItem GetData(string key, InstData instData)
134    {
135      if (instData.ParameterizedItems.TryGetValue(key, out JsonItem value))
136        return value;
137      else
138        throw new InvalidDataException($"Type of item '{key}' is not defined!");
139    }
140
141    private static T CreateObject<T>(JsonItem data, InstData instData) {
142      if (instData.TypeList.TryGetValue(data.Name, out string typeName)) {
143        Type type = Type.GetType(typeName);
144        return (T)Activator.CreateInstance(type);
145      } else throw new TypeLoadException($"Cannot find AssemblyQualifiedName for {data.Name}.");
146    }
147
148    #region BuildJsonItemMethods
149    private static JsonItem BuildJsonItem(JObject obj, InstData instData) =>
150      new JsonItem() {
151        Name = obj[nameof(JsonItem.Name)]?.ToString(),
152        Path = obj[nameof(JsonItem.Path)]?.ToString(),
153        Value = obj[nameof(JsonItem.Value)]?.ToObject<object>(),
154        Range = obj[nameof(JsonItem.Range)]?.ToObject<object[]>(),
155        Type = GetType(obj[nameof(JsonItem.Path)]?.ToObject<string>(), instData),
156        ActualName = obj[nameof(JsonItem.ActualName)]?.ToString(),
157        Parameters = PopulateParameters(obj, instData),
158        Operators = PopulateOperators(obj, instData)
159      };
160
161    private static string GetType(string path, InstData instData) {
162      if(!string.IsNullOrEmpty(path))
163        if (instData.TypeList.TryGetValue(path, out string value))
164          return value;
165      return null;
166    }
167
168    private static IList<JsonItem> PopulateParameters(JObject obj, InstData instData) {
169      IList<JsonItem> list = new List<JsonItem>();
170
171      // add staticParameters
172      if (obj[Constants.StaticParameters] != null)
173        foreach (JObject param in obj[Constants.StaticParameters])
174          list.Add(BuildJsonItem(param, instData));
175
176      // merge staticParameter with freeParameter
177      if (obj[Constants.FreeParameters] != null) {
178        foreach (JObject param in obj[Constants.FreeParameters]) {
179          JsonItem tmp = BuildJsonItem(param, instData);
180         
181          // search staticParameter from list
182          JsonItem comp = null;
183          foreach (var p in list)
184            if (p.Name == tmp.Name) comp = p;
185          if (comp == null)
186            throw new InvalidDataException($"Invalid {Constants.FreeParameters.Trim('s')}: '{tmp.Name}'!");
187
188          JsonItem.Merge(comp, tmp);
189        }
190      }
191      return list;
192    }
193
194    private static IList<JsonItem> PopulateOperators(JObject obj, InstData instData) {
195      IList<JsonItem> list = new List<JsonItem>();
196      JToken operators = obj[nameof(JsonItem.Operators)];
197      if (operators != null)
198        foreach (JObject sp in operators)
199          list.Add(BuildJsonItem(sp, instData));
200      return list;
201    }
202    #endregion
203    #endregion
204  }
205}
Note: See TracBrowser for help on using the repository browser.