Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OaaS/HeuristicLab.Services.Optimization.Controller/Parsers/AlgorithmConverter.cs @ 9350

Last change on this file since 9350 was 9350, checked in by fschoepp, 11 years ago

#1888:

  • Added input parameters to the run class. They will be populated by the back-end and returned to the web pages which renders them.
  • Added a ParameterMapper class which converts HL specific model classes to OaaS independent classes. The conversion gets delegated to IParameterHandler which have to be implemented manually and registered for a certain Type before. All parameters which can be converted to IStringConvertible, IStringConvertibleMatrix, IString* will be converted into a OaaS-StringValue instance.
  • Added IParameterHandlers for PathTSPTour and PermutationType (required for TSP).
  • AlgorithmConverter now makes sure that the id of a run is unique. (All runs of a RunList will be shown now.)
  • Web pages are capable of rendering both the results of a run and their input parameters (added a accordion to wrap their content).
  • Renamed "Traveling Salesman Problem" to "Genetic Algorithm - TSP".
  • Changed js-files to render both input and result parameters of a Run.
File size: 10.1 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using HeuristicLab.Services.Optimization.ControllerService.Model;
6using Newtonsoft.Json.Linq;
7using Newtonsoft.Json;
8
9namespace HeuristicLab.Services.Optimization.ControllerService.Parsers {
10  public static class AlgorithmConverter {
11    #region private methods
12    private static Parameter CreateParameter(JObject property) {
13      var name = (string)property["Name"];
14      var value = property["Value"];
15      switch (value.Type) {
16        case JTokenType.Integer:
17        case JTokenType.Float:
18          return new Parameter() { Type = ParameterType.Decimal, Value = new DecimalValue() { Name = name, Value = (double)value } };
19        case JTokenType.Boolean:
20          return new Parameter() { Type = ParameterType.Boolean, Value = new BoolValue() { Name = name, Value = (bool)value } };
21        case JTokenType.String:
22          return new Parameter() { Type = ParameterType.Type, Value = new TypeValue() { Name = name, Value = (string)value, Options = (from e in property["Options"] select (string)e).ToArray() } };
23        case JTokenType.Array:
24          var arr = (JArray)value;
25          // its a matrix
26          if (arr[0].Type == JTokenType.Array) {
27            return CreateMatrixParameter(name, arr);
28          }
29          return CreateVectorParameter(name, arr);
30        default:
31          throw new Exception("Unhandled datatype: " + property.Type);
32      }
33    }
34
35    private static Parameter CreateMatrixParameter(string name, JArray arr) {
36      double[][] entries = new double[arr.Count][];
37      for (int i = 0; i < entries.Length; i++) {
38        entries[i] = (from d in arr[i] select (double)d).ToArray<double>();
39      }
40      return new Parameter { Type = ParameterType.DecimalMatrix, Value = new DecimalMatrix() { Name = name, Value = entries } };
41    }
42
43    private static Parameter CreateVectorParameter(string name, JArray arr) {
44      double[] entries = (from d in arr select (double)d).ToArray<double>();
45      return new Parameter { Type = ParameterType.DecimalVector, Value = new DecimalVector() { Name = name, Value = entries } };
46    }
47
48    private class StackEntry {
49      public Algorithm Parent { get; set; }
50      public JToken Child { get; set; }
51    }
52
53    private static JArray ConvertParametersToJson(IList<Parameter> parameters) {
54      var array = new JArray();
55      foreach (var param in parameters) {
56        array.Add(JObject.FromObject(param.Value));
57      }
58      return array;
59    }
60
61    private struct Entry {
62      public JObject TargetAlgorithm { get; set; }
63
64      public Algorithm SourceAlgorithm { get; set; }
65    }
66
67    private static Algorithm ParseAlgorithm(JToken jsonAlgorithm) {
68      var algorithm = new Algorithm();
69
70      foreach (JObject param in jsonAlgorithm["AlgorithmParameters"]) {
71        Parameter parameter = CreateParameter(param);
72        algorithm.Parameters.Items.Add(parameter);
73      }
74
75      var problemParams = jsonAlgorithm["ProblemParameters"];
76      if (problemParams != null) {
77        algorithm.Problem = new Problem();
78        foreach (JObject param in problemParams) {
79          Parameter parameter = CreateParameter(param);
80          algorithm.Problem.Parameters.Items.Add(parameter);
81        }
82      }
83      return algorithm;
84    }
85    #endregion
86
87
88    #region public methods
89
90
91    public static JObject ConvertExperimentToJson(Experiment experiment) {
92      var exp = new JObject();
93      exp["title"] = experiment.Name;
94      exp["children"] = new JArray();
95      exp["nodeId"] = experiment.Id;
96      exp["isExperiment"] = true;
97
98      var stack = new Stack<Entry>();
99      foreach (var algo in experiment.Algorithm)
100        stack.Push(new Entry() { TargetAlgorithm = exp, SourceAlgorithm = algo });
101
102      while (stack.Count > 0) {
103        var entry = stack.Pop();
104        var algorithm = ConvertAlgorithmToJson(entry.SourceAlgorithm);
105        (entry.TargetAlgorithm["children"] as JArray).Add(algorithm);
106
107        if (entry.SourceAlgorithm.ChildAlgorithms.Count > 0) {
108          // push children
109          foreach (var child in entry.SourceAlgorithm.ChildAlgorithms) {
110            stack.Push(new Entry() { TargetAlgorithm = algorithm, SourceAlgorithm = child });
111          }
112        }
113
114      }
115      return exp;
116    }
117
118    public static JArray ConvertExperimentsToJson(IEnumerable<Experiment> experiments) {
119      var jarray = new JArray();
120      foreach (var exp in experiments)
121        jarray.Add(ConvertExperimentToJson(exp));
122      return jarray;
123    }
124
125    public static JArray ConvertAlgorithmsToJson(IEnumerable<Algorithm> algorithms) {
126      var jarray = new JArray();
127      foreach (var algo in algorithms)
128        jarray.Add(ConvertAlgorithmToJson(algo));
129      return jarray;
130    }
131
132
133    public static JArray ConvertScenariosToJson(IEnumerable<OptimizationScenario> scenarios) {
134      var jarray = new JArray();
135      foreach (var scen in scenarios)
136        jarray.Add(ConvertScenarioToJson(scen));
137      return jarray;
138    }
139
140    public static JObject ConvertScenarioToJson(OptimizationScenario scenario) {
141      var exp = new JObject();
142      exp["title"] = scenario.Id;
143      exp["children"] = new JArray();
144      exp["nodeId"] = scenario.Id;
145      exp["isExperiment"] = false;
146
147      var stack = new Stack<Entry>();
148      var baseAlgorithm = ConvertAlgorithmToJson(scenario.FirstAlgorithm);
149      exp["data"] = baseAlgorithm["data"];
150      if (scenario.FirstAlgorithm.ChildAlgorithms.Count > 0) {
151        foreach (var child in scenario.FirstAlgorithm.ChildAlgorithms)
152          stack.Push(new Entry() { TargetAlgorithm = exp, SourceAlgorithm = child});
153      }
154
155      while (stack.Count > 0) {
156        var entry = stack.Pop();
157        var algorithm = ConvertAlgorithmToJson(entry.SourceAlgorithm);
158        (entry.TargetAlgorithm["children"] as JArray).Add(algorithm);
159
160        if (entry.SourceAlgorithm.ChildAlgorithms.Count > 0) {
161          // push children
162          foreach (var child in entry.SourceAlgorithm.ChildAlgorithms) {
163            stack.Push(new Entry() { TargetAlgorithm = algorithm, SourceAlgorithm = child });
164          }
165        }
166
167      }
168      return exp;
169    }
170
171    public static JObject ConvertAlgorithmToJson(Algorithm algorithm) {
172      var jalgo = new JObject();
173      jalgo["title"] = algorithm.Name;
174      jalgo["nodeId"] = algorithm.Id;
175      var jalgoData = new JObject();
176      jalgo["data"] = jalgoData;
177      jalgo["isExperiment"] = algorithm.IsExperiment;
178      jalgoData["AlgorithmParameters"] = ConvertParametersToJson(algorithm.Parameters.Items);
179      if (algorithm.Problem != null && algorithm.Problem.Parameters != null)
180        jalgoData["ProblemParameters"] = ConvertParametersToJson(algorithm.Problem.Parameters.Items);
181
182      jalgo["children"] = new JArray();
183      return jalgo;
184    }
185
186    public static JObject ConvertRunToJson(Run run) {
187      var jrun = new JObject();
188      jrun["id"] = run.Id;
189      jrun["name"] = run.Name;
190      jrun["results"] = ConvertParametersToJson(run.Results);
191      jrun["params"] = ConvertParametersToJson(run.InputParameters);
192      return jrun;
193    }
194
195    public static JArray ConvertRunsToJson(IList<Run> runs) {
196       var jarray = new JArray();
197      foreach (var run in runs)
198        jarray.Add(ConvertRunToJson(run));
199     
200     
201      // if there are multiple different jobs to execute and they have the same id, we must change it here manually
202      var maxId = new Dictionary<string,int>();
203      for (int i = 0; i < jarray.Count; i++) {
204        for (int j = i + 1; j < jarray.Count; j++) {
205          if (jarray[i]["id"].ToString() == jarray[j]["id"].ToString()) {
206            int max;
207            if (!maxId.TryGetValue(jarray[i]["id"].ToString(), out max)) {
208              max = 1;
209              maxId[jarray[i]["id"].ToString()] = max;             
210            }
211            maxId[jarray[i]["id"].ToString()]++;
212            // change j's entry
213            jarray[j]["id"] = jarray[j]["id"].ToString() + " (" + max + ")";
214            jarray[j]["name"] = jarray[j]["name"] + " (" + max + ")";
215          }
216        }
217      }
218      return jarray;
219    }
220
221    public static Experiment ConvertJsonToExperiment(string json) {
222      var experiment = new Experiment();
223      var jsonExperiment = JObject.Parse(json);
224      experiment.Name = (string)jsonExperiment["title"];
225      experiment.Id = (string)jsonExperiment["nodeId"];     
226      var stack = new Stack<StackEntry>();
227      var root = new Algorithm();
228
229      if (jsonExperiment["run"] != null && (bool)jsonExperiment["run"]) {
230        experiment.JobDetails = new JobExecutionDetails() {
231          Group = (string)jsonExperiment["group"],
232          Repititions = (int)jsonExperiment["repititions"]
233        };
234      }
235
236      // ignore experiment node, skip to its children
237      if (jsonExperiment["experiment"] != null)
238        foreach (var algo in jsonExperiment["experiment"]["children"]) {
239          stack.Push(new StackEntry() { Parent = root, Child = algo });
240        }
241
242      if (jsonExperiment["children"] != null)
243        foreach (var algo in jsonExperiment["children"]) {
244          stack.Push(new StackEntry() { Parent = root, Child = algo });
245        }
246
247      while (stack.Count > 0) {
248        var entry = stack.Pop();
249        var data = entry.Child["data"];
250        var currentAlgo = data == null || !data.HasValues ? new Algorithm() : ParseAlgorithm(entry.Child["data"]);
251        currentAlgo.Name = (string)entry.Child["title"];
252        currentAlgo.Id = (string)entry.Child["nodeId"];
253        currentAlgo.IsExperiment = (bool)entry.Child["isExperiment"];
254        entry.Parent.ChildAlgorithms.Add(currentAlgo);
255        // push children on stack (inverse order to preserve ordering)
256        var cnt = entry.Child["children"].Count();
257        for (var i = 0; i < cnt; i++) {
258          stack.Push(new StackEntry() { Parent = currentAlgo, Child = entry.Child["children"][cnt - 1 - i] });
259        }
260      }
261
262      foreach (var algo in root.ChildAlgorithms) {
263        experiment.Algorithm.Add(algo);
264      }
265
266      return experiment;
267    }
268    #endregion
269  }
270}
Note: See TracBrowser for help on using the repository browser.