source: branches/3026_IntegrationIntoSymSpace/HeuristicLab.JsonInterface/Converters/RegressionProblemDataConverter.cs @ 17834

Last change on this file since 17834 was 17834, checked in by dpiringe, 2 months ago

#3026

  • added ResultFormatter to add an extra layer of result transformation logic (converting a result value to a string with a defined logic, e.g. MatlabResultFormatter for ISymbolicRegressionSolution)
  • extended the IResultJsonItem with two properties for result formatting
  • added a new control to selected a result formatter for a result value
  • refactored the Runner for the new result formatting process
File size: 10.8 KB
Line 
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using System.Linq;
5using System.Reflection;
6using System.Text;
7using System.Threading.Tasks;
8using HeuristicLab.Core;
9using HeuristicLab.Data;
10using HeuristicLab.Parameters;
11using Newtonsoft.Json.Linq;
12
13namespace HeuristicLab.JsonInterface {
14  public class RegressionProblemDataConverter : BaseConverter {
15    #region Constants
16    private const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
17    private const string TestPartition = "TestPartition";
18    private const string TrainingPartition = "TrainingPartition";
19    private const string TargetVariable = "TargetVariable";
20    private const string AllowedInputVariables = "AllowedInputVariables";
21    private const string Dataset = "Dataset";
22    private const string VariableValues = "variableValues";
23    private const string VariableNames = "variableNames";
24    private const string InputVariables = "InputVariables";
25    private const string Rows = "rows";
26    private const string Value = "value";
27    private const string Parameters = "parameters";
28    private const string CheckedItemList = "CheckedItemList";
29    #endregion
30
31    public override int Priority => 20;
32
33    // RegressionProblemData
34    public override Type ConvertableType => HEAL.Attic.Mapper.StaticCache.GetType(new Guid("EE612297-B1AF-42D2-BF21-AF9A2D42791C"));
35
36    public override bool CanConvertType(Type t) =>
37      ConvertableType.IsAssignableFrom(t);
38
39    public override void Inject(IItem item, IJsonItem data, IJsonItemConverter root) {
40
41      dynamic regressionProblemData = (dynamic)item;
42
43      DoubleMatrixJsonItem dataset = null;
44      StringJsonItem targetVariable = null;
45      IntRangeJsonItem testPartition = null;
46      IntRangeJsonItem trainingPartition = null;
47      StringArrayJsonItem allowedInputVariables = null;
48
49
50      // search first for the items (cache them, because the
51      // order is important for injection)
52      foreach (var child in data.Children) {
53
54        if (child.Path.EndsWith(Dataset))
55          dataset = child as DoubleMatrixJsonItem;
56        else if (child.Path.EndsWith(TargetVariable))
57          targetVariable = child as StringJsonItem;
58        else if (child.Path.EndsWith(TestPartition))
59          testPartition = child as IntRangeJsonItem;
60        else if (child.Path.EndsWith(TrainingPartition))
61          trainingPartition = child as IntRangeJsonItem;
62        else if (child.Path.EndsWith(AllowedInputVariables))
63          allowedInputVariables = child as StringArrayJsonItem;
64
65      }
66
67      // check data
68      if(!dataset.ColumnNames.Any(x => x == targetVariable.Value)) {
69        throw new Exception($"The value of the target variable ('{targetVariable.Value}') has no matching row name value of the dataset.");
70      }
71
72      foreach(var v in allowedInputVariables.Value) {
73        if(!dataset.ColumnNames.Any(x => x == v))
74          throw new Exception($"The value of the input variable ('{v}') has no matching row name value of the dataset.");
75      }
76
77      // inject the value of the items
78      SetDataset(regressionProblemData, dataset);
79      SetTargetVariable(regressionProblemData, targetVariable);
80      SetAllowedInputVariables(regressionProblemData, allowedInputVariables, dataset);
81      SetTestPartition(regressionProblemData, testPartition);
82      SetTrainingPartition(regressionProblemData, trainingPartition);
83
84    }
85
86    public override IJsonItem Extract(IItem value, IJsonItemConverter root) {
87      IJsonItem item = new EmptyJsonItem() {
88        Name = value.ItemName,
89        Description = value.ItemDescription
90      };
91
92      IJsonItem ds = GetDataset(value);
93      if(ds != null)
94        item.AddChildren(ds);
95
96      item.AddChildren(GetTestPartition(value));
97      item.AddChildren(GetTrainingPartition(value));
98      item.AddChildren(GetTargetVariable(value));
99      item.AddChildren(GetAllowedInputVariables(value));
100      return item;
101    }
102
103    #region Inject Helper
104    private void SetDataset(dynamic regressionProblemData, DoubleMatrixJsonItem item) {
105      if (item != null) {
106        var dictTmp = new Dictionary<string, IList>();
107        int c = 0;
108        foreach (var col in item.ColumnNames) {
109          dictTmp.Add(col, new List<double>(item.Value[c]));
110          ++c;
111        }
112
113        object dataset = (object)regressionProblemData.Dataset;
114        var rows = dataset.GetType().GetField(Rows, flags);
115        rows.SetValue(dataset, item.Value[0].Length);
116
117        var variableNames = dataset.GetType().GetField(VariableNames, flags);
118        variableNames.SetValue(dataset, item.ColumnNames);
119
120        var dataInfo = dataset.GetType().GetField(VariableValues, flags);
121        dataInfo.SetValue(dataset, dictTmp);
122      }
123    }
124
125    private void SetTestPartition(dynamic regressionProblemData, IntRangeJsonItem item) {
126      if (item != null) {
127        regressionProblemData.TestPartition.Start = item.MinValue;
128        regressionProblemData.TestPartition.End = item.MaxValue;
129      }
130    }
131
132    private void SetTrainingPartition(dynamic regressionProblemData, IntRangeJsonItem item) {
133      if (item != null) {
134        regressionProblemData.TrainingPartition.Start = item.MinValue;
135        regressionProblemData.TrainingPartition.End = item.MaxValue;
136      }
137    }
138
139    private void SetTargetVariable(dynamic regressionProblemData, StringJsonItem item) {
140      if (item != null) {
141        var param = (IConstrainedValueParameter<StringValue>)regressionProblemData.TargetVariableParameter;
142        StringValue v = param.Value;
143        FieldInfo fi = v.GetType().GetField(Value, flags);
144        fi.SetValue(v, item.Value);
145      }
146    }
147
148    private void SetAllowedInputVariables(dynamic regressionProblemData, StringArrayJsonItem item, IMatrixJsonItem matrix) {
149      if (item != null && regressionProblemData is IParameterizedItem p) {
150        var regProbDataType = ((ParameterizedNamedItem)regressionProblemData).GetType(); //RegressionProblemData
151
152        var parameterizedNamedItemType = regProbDataType.BaseType.BaseType;
153
154        // reset parameter
155        var parametersInfo = parameterizedNamedItemType.GetField(Parameters, flags);
156        ParameterCollection col = (ParameterCollection)parametersInfo.GetValue((object)regressionProblemData);
157        var oldParam = (FixedValueParameter<ReadOnlyCheckedItemList<StringValue>>)col[InputVariables];
158        var value = oldParam.Value;
159        PropertyInfo listInfo = value.GetType().GetProperty(CheckedItemList, flags);
160        CheckedItemList<StringValue> checkedItemList = (CheckedItemList<StringValue>)listInfo.GetValue(value);
161        checkedItemList.Clear();
162
163        // add list items and set their check state (based on allowed input variables)
164        foreach(var i in matrix.ColumnNames) {
165          bool isChecked = false;
166          foreach(var x in item.Value)
167            isChecked = isChecked || (x == i);
168          checkedItemList.Add(new StringValue(i).AsReadOnly(), isChecked);
169        }
170      }
171    }
172    #endregion
173
174    #region Extract Helper
175    private IJsonItem GetDataset(IItem item) {
176      dynamic val = (dynamic)item;
177      object dataset = (object)val.Dataset;
178      FieldInfo dataInfo = dataset.GetType().GetField(VariableValues, flags);
179
180      if (dataInfo.GetValue(dataset) is Dictionary<string, IList> dict) {
181        IEnumerator it = dict.Values.First()?.GetEnumerator();
182
183        if(it != null) {
184          if(it.MoveNext() && it.Current is double) {
185            CreateMatrix(dict, out IList<string> columnNames, out double[][] mat);
186            return new DoubleMatrixJsonItem() {
187              Name = Dataset,
188              Value = mat,
189              ColumnNames = columnNames,
190              Minimum = double.MinValue,
191              Maximum = double.MaxValue
192            };
193          } else if(it.Current is int) {
194            CreateMatrix(dict, out IList<string> columnNames, out int[][] mat);
195            return new IntMatrixJsonItem() {
196              Name = Dataset,
197              Value = mat,
198              ColumnNames = columnNames,
199              Minimum = int.MinValue,
200              Maximum = int.MaxValue
201            };
202          } else if (it.Current is bool) {
203            CreateMatrix(dict, out IList<string> columnNames, out bool[][] mat);
204            return new BoolMatrixJsonItem() {
205              Name = Dataset,
206              Value = mat,
207              ColumnNames = columnNames
208            };
209          }
210        }
211      }
212      return null;
213    }
214   
215    private void CreateMatrix<T>(Dictionary<string, IList> dict, out IList<string> columnNames, out T[][] matrix) {
216      int cols = dict.Count, rows = 0, c = 0;
217      columnNames = new List<string>();
218      matrix = new T[cols][];
219      foreach (var x in dict) {
220        rows = Math.Max(rows, x.Value.Count);
221        columnNames.Add(x.Key);
222
223        matrix[c] = new T[rows];
224
225        int r = 0;
226        foreach (var callValue in x.Value) {
227          matrix[c][r] = (T)callValue;
228          ++r;
229        }
230        ++c;
231      }
232    }
233
234    private IJsonItem GetTestPartition(IItem item) {
235      dynamic val = (dynamic)item;
236      var trainingPartition = (IntRange)val.TrainingPartition;
237      var testPartition = (IntRange)val.TestPartition;
238      return new IntRangeJsonItem() {
239        Name = TestPartition,
240        MinValue = testPartition.Start,
241        MaxValue = testPartition.End,
242        Minimum = 0,
243        Maximum = int.MaxValue //Math.Max(testPartition.End, trainingPartition.End)
244      };
245    }
246
247    private IJsonItem GetTrainingPartition(IItem item) {
248      dynamic val = (dynamic)item;
249      var trainingPartition = (IntRange)val.TrainingPartition;
250      var testPartition = (IntRange)val.TestPartition;
251      return new IntRangeJsonItem() {
252        Name = TrainingPartition,
253        MinValue = trainingPartition.Start,
254        MaxValue = trainingPartition.End,
255        Minimum = 0,
256        Maximum = int.MaxValue //Math.Max(testPartition.End, trainingPartition.End)
257      };
258    }
259
260
261    private IJsonItem GetTargetVariable(IItem item) {
262      var vars = (IEnumerable<StringValue>)((dynamic)item).InputVariables;
263      return new StringJsonItem() {
264        Name = TargetVariable,
265        Value = (string)((dynamic)item).TargetVariable,
266        ConcreteRestrictedItems = vars.Select(x => x.Value)
267      };
268    }
269
270    private IJsonItem GetAllowedInputVariables(IItem item) {
271      var vars = (IEnumerable<StringValue>)((dynamic)item).InputVariables;
272      return new StringArrayJsonItem() {
273        Name = AllowedInputVariables,
274        Value = ((IEnumerable<string>)((dynamic)item).AllowedInputVariables).ToArray(),
275        ConcreteRestrictedItems = vars.Select(x => x.Value)
276      };
277    }
278    #endregion
279  }
280}
Note: See TracBrowser for help on using the repository browser.