1 | using System;
|
---|
2 | using System.Collections.Generic;
|
---|
3 | using System.Linq;
|
---|
4 | using System.Text;
|
---|
5 | using HeuristicLab.Services.Optimization.ControllerService.Model;
|
---|
6 | using Newtonsoft.Json.Linq;
|
---|
7 | using Newtonsoft.Json;
|
---|
8 |
|
---|
9 | namespace 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 | jrun["algorithmName"] = run.AlgorithmName;
|
---|
193 | return jrun;
|
---|
194 | }
|
---|
195 |
|
---|
196 | public static JArray ConvertRunsToJson(IList<Run> runs) {
|
---|
197 | var jarray = new JArray();
|
---|
198 | foreach (var run in runs)
|
---|
199 | jarray.Add(ConvertRunToJson(run));
|
---|
200 |
|
---|
201 |
|
---|
202 | // if there are multiple different jobs to execute and they have the same id, we must change it here manually
|
---|
203 | var maxId = new Dictionary<string,int>();
|
---|
204 | for (int i = 0; i < jarray.Count; i++) {
|
---|
205 | for (int j = i + 1; j < jarray.Count; j++) {
|
---|
206 | if (jarray[i]["id"].ToString() == jarray[j]["id"].ToString()) {
|
---|
207 | int max;
|
---|
208 | if (!maxId.TryGetValue(jarray[i]["id"].ToString(), out max)) {
|
---|
209 | max = 1;
|
---|
210 | maxId[jarray[i]["id"].ToString()] = max;
|
---|
211 | }
|
---|
212 | maxId[jarray[i]["id"].ToString()]++;
|
---|
213 | // change j's entry
|
---|
214 | jarray[j]["id"] = jarray[j]["id"].ToString() + " (" + max + ")";
|
---|
215 | jarray[j]["name"] = jarray[j]["name"] + " (" + max + ")";
|
---|
216 | }
|
---|
217 | }
|
---|
218 | }
|
---|
219 | return jarray;
|
---|
220 | }
|
---|
221 |
|
---|
222 | public static Experiment ConvertJsonToExperiment(string json) {
|
---|
223 | var experiment = new Experiment();
|
---|
224 | var jsonExperiment = JObject.Parse(json);
|
---|
225 | experiment.Name = (string)jsonExperiment["title"];
|
---|
226 | experiment.Id = (string)jsonExperiment["nodeId"];
|
---|
227 | var stack = new Stack<StackEntry>();
|
---|
228 | var root = new Algorithm();
|
---|
229 |
|
---|
230 | if (jsonExperiment["run"] != null && (bool)jsonExperiment["run"]) {
|
---|
231 | experiment.JobDetails = new JobExecutionDetails() {
|
---|
232 | Group = (string)jsonExperiment["group"],
|
---|
233 | Repititions = (int)jsonExperiment["repititions"]
|
---|
234 | };
|
---|
235 | }
|
---|
236 |
|
---|
237 | // ignore experiment node, skip to its children
|
---|
238 | if (jsonExperiment["experiment"] != null)
|
---|
239 | foreach (var algo in jsonExperiment["experiment"]["children"]) {
|
---|
240 | stack.Push(new StackEntry() { Parent = root, Child = algo });
|
---|
241 | }
|
---|
242 |
|
---|
243 | if (jsonExperiment["children"] != null)
|
---|
244 | foreach (var algo in jsonExperiment["children"]) {
|
---|
245 | stack.Push(new StackEntry() { Parent = root, Child = algo });
|
---|
246 | }
|
---|
247 |
|
---|
248 | while (stack.Count > 0) {
|
---|
249 | var entry = stack.Pop();
|
---|
250 | var data = entry.Child["data"];
|
---|
251 | var currentAlgo = data == null || !data.HasValues ? new Algorithm() : ParseAlgorithm(entry.Child["data"]);
|
---|
252 | currentAlgo.Name = (string)entry.Child["title"];
|
---|
253 | currentAlgo.Id = (string)entry.Child["nodeId"];
|
---|
254 | currentAlgo.IsExperiment = (bool)entry.Child["isExperiment"];
|
---|
255 | entry.Parent.ChildAlgorithms.Add(currentAlgo);
|
---|
256 | // push children on stack (inverse order to preserve ordering)
|
---|
257 | var cnt = entry.Child["children"].Count();
|
---|
258 | for (var i = 0; i < cnt; i++) {
|
---|
259 | stack.Push(new StackEntry() { Parent = currentAlgo, Child = entry.Child["children"][cnt - 1 - i] });
|
---|
260 | }
|
---|
261 | }
|
---|
262 |
|
---|
263 | foreach (var algo in root.ChildAlgorithms) {
|
---|
264 | experiment.Algorithm.Add(algo);
|
---|
265 | }
|
---|
266 |
|
---|
267 | return experiment;
|
---|
268 | }
|
---|
269 | #endregion
|
---|
270 | }
|
---|
271 | }
|
---|