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

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

#3026:

  • added new converter: BatchRunConverter, ExperimentConverter
  • fixed a bug with the path of the .hl file in JCGenerator
  • fixed a bug with a redundant search for a suitable converter in JsonItemConverter
  • added a restriction for TargetVariable and AllowedInputVariables in RegressionProblemDataConverter
  • removed unnecessary code in Runner
File size: 10.6 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 void Inject(IItem item, IJsonItem data, IJsonItemConverter root) {
37
38      dynamic regressionProblemData = (dynamic)item;
39
40      DoubleMatrixJsonItem dataset = null;
41      StringJsonItem targetVariable = null;
42      IntRangeJsonItem testPartition = null;
43      IntRangeJsonItem trainingPartition = null;
44      StringArrayJsonItem allowedInputVariables = null;
45
46
47      // search first for the items (cache them, because the
48      // order is important for injection)
49      foreach (var child in data.Children) {
50
51        if (child.Path.EndsWith(Dataset))
52          dataset = child as DoubleMatrixJsonItem;
53        else if (child.Path.EndsWith(TargetVariable))
54          targetVariable = child as StringJsonItem;
55        else if (child.Path.EndsWith(TestPartition))
56          testPartition = child as IntRangeJsonItem;
57        else if (child.Path.EndsWith(TrainingPartition))
58          trainingPartition = child as IntRangeJsonItem;
59        else if (child.Path.EndsWith(AllowedInputVariables))
60          allowedInputVariables = child as StringArrayJsonItem;
61
62      }
63
64      // check data
65      if(!dataset.RowNames.Any(x => x == targetVariable.Value)) {
66        throw new Exception($"The value of the target variable ('{targetVariable.Value}') has no matching row name value of the dataset.");
67      }
68
69      foreach(var v in allowedInputVariables.Value) {
70        if(!dataset.RowNames.Any(x => x == v))
71          throw new Exception($"The value of the input variable ('{v}') has no matching row name value of the dataset.");
72      }
73
74      // inject the value of the items
75      SetDataset(regressionProblemData, dataset);
76      SetTargetVariable(regressionProblemData, targetVariable);
77      SetAllowedInputVariables(regressionProblemData, allowedInputVariables, dataset);
78      SetTestPartition(regressionProblemData, testPartition);
79      SetTrainingPartition(regressionProblemData, trainingPartition);
80
81    }
82
83    public override IJsonItem Extract(IItem value, IJsonItemConverter root) {
84      IJsonItem item = new EmptyJsonItem() {
85        Name = value.ItemName,
86        Description = value.ItemDescription
87      };
88
89      IJsonItem ds = GetDataset(value);
90      if(ds != null)
91        item.AddChildren(ds);
92
93      item.AddChildren(GetTestPartition(value));
94      item.AddChildren(GetTrainingPartition(value));
95      item.AddChildren(GetTargetVariable(value));
96      item.AddChildren(GetAllowedInputVariables(value));
97      return item;
98    }
99
100    #region Inject Helper
101    private void SetDataset(dynamic regressionProblemData, DoubleMatrixJsonItem item) {
102      if (item != null) {
103        var dictTmp = new Dictionary<string, IList>();
104        int c = 0;
105        foreach (var col in item.RowNames) {
106          dictTmp.Add(col, new List<double>(item.Value[c]));
107          ++c;
108        }
109
110        object dataset = (object)regressionProblemData.Dataset;
111        var rows = dataset.GetType().GetField(Rows, flags);
112        rows.SetValue(dataset, item.Value[0].Length);
113
114        var variableNames = dataset.GetType().GetField(VariableNames, flags);
115        variableNames.SetValue(dataset, item.RowNames);
116
117        var dataInfo = dataset.GetType().GetField(VariableValues, flags);
118        dataInfo.SetValue(dataset, dictTmp);
119      }
120    }
121
122    private void SetTestPartition(dynamic regressionProblemData, IntRangeJsonItem item) {
123      if (item != null) {
124        regressionProblemData.TestPartition.Start = item.MinValue;
125        regressionProblemData.TestPartition.End = item.MaxValue;
126      }
127    }
128
129    private void SetTrainingPartition(dynamic regressionProblemData, IntRangeJsonItem item) {
130      if (item != null) {
131        regressionProblemData.TrainingPartition.Start = item.MinValue;
132        regressionProblemData.TrainingPartition.End = item.MaxValue;
133      }
134    }
135
136    private void SetTargetVariable(dynamic regressionProblemData, StringJsonItem item) {
137      if (item != null) {
138        var param = (IConstrainedValueParameter<StringValue>)regressionProblemData.TargetVariableParameter;
139        StringValue v = param.Value;
140        FieldInfo fi = v.GetType().GetField(Value, flags);
141        fi.SetValue(v, item.Value);
142      }
143    }
144
145    private void SetAllowedInputVariables(dynamic regressionProblemData, StringArrayJsonItem item, IMatrixJsonItem matrix) {
146      if (item != null && regressionProblemData is IParameterizedItem p) {
147        var regProbDataType = ((ParameterizedNamedItem)regressionProblemData).GetType(); //RegressionProblemData
148
149        var parameterizedNamedItemType = regProbDataType.BaseType.BaseType;
150
151        // reset parameter
152        var parametersInfo = parameterizedNamedItemType.GetField(Parameters, flags);
153        ParameterCollection col = (ParameterCollection)parametersInfo.GetValue((object)regressionProblemData);
154        var oldParam = (FixedValueParameter<ReadOnlyCheckedItemList<StringValue>>)col[InputVariables];
155        var value = oldParam.Value;
156        PropertyInfo listInfo = value.GetType().GetProperty(CheckedItemList, flags);
157        CheckedItemList<StringValue> checkedItemList = (CheckedItemList<StringValue>)listInfo.GetValue(value);
158        checkedItemList.Clear();
159
160        // add list items and set their check state (based on allowed input variables)
161        foreach(var i in matrix.RowNames) {
162          bool isChecked = false;
163          foreach(var x in item.Value)
164            isChecked = isChecked || (x == i);
165          checkedItemList.Add(new StringValue(i).AsReadOnly(), isChecked);
166        }
167      }
168    }
169    #endregion
170
171    #region Extract Helper
172    private IJsonItem GetDataset(IItem item) {
173      dynamic val = (dynamic)item;
174      object dataset = (object)val.Dataset;
175      FieldInfo dataInfo = dataset.GetType().GetField(VariableValues, flags);
176
177      if (dataInfo.GetValue(dataset) is Dictionary<string, IList> dict) {
178        IEnumerator it = dict.Values.First()?.GetEnumerator();
179
180        if(it != null) {
181          if(it.MoveNext() && it.Current is double) {
182            CreateMatrix(dict, out IList<string> rowNames, out double[][] mat);
183            return new DoubleMatrixJsonItem() {
184              Name = Dataset,
185              Value = mat,
186              RowNames = rowNames,
187              Minimum = double.MinValue,
188              Maximum = double.MaxValue
189            };
190          } else if(it.Current is int) {
191            CreateMatrix(dict, out IList<string> rowNames, out int[][] mat);
192            return new IntMatrixJsonItem() {
193              Name = Dataset,
194              Value = mat,
195              RowNames = rowNames,
196              Minimum = int.MinValue,
197              Maximum = int.MaxValue
198            };
199          } else if (it.Current is bool) {
200            CreateMatrix(dict, out IList<string> rowNames, out bool[][] mat);
201            return new BoolMatrixJsonItem() {
202              Name = Dataset,
203              Value = mat,
204              RowNames = rowNames
205            };
206          }
207        }
208      }
209      return null;
210    }
211   
212    private void CreateMatrix<T>(Dictionary<string, IList> dict, out IList<string> rowNames, out T[][] matrix) {
213      int cols = dict.Count, rows = 0, c = 0;
214      rowNames = new List<string>();
215      matrix = new T[cols][];
216      foreach (var x in dict) {
217        rows = Math.Max(rows, x.Value.Count);
218        rowNames.Add(x.Key);
219
220        matrix[c] = new T[rows];
221        int r = 0;
222
223        foreach (var rowValue in x.Value) {
224          matrix[c][r] = (T)rowValue;
225          ++r;
226        }
227        ++c;
228      }
229    }
230
231    private IJsonItem GetTestPartition(IItem item) {
232      dynamic val = (dynamic)item;
233      var trainingPartition = (IntRange)val.TrainingPartition;
234      var testPartition = (IntRange)val.TestPartition;
235      return new IntRangeJsonItem() {
236        Name = TestPartition,
237        MinValue = testPartition.Start,
238        MaxValue = testPartition.End,
239        Minimum = 0,
240        Maximum = Math.Max(testPartition.End, trainingPartition.End)
241      };
242    }
243
244    private IJsonItem GetTrainingPartition(IItem item) {
245      dynamic val = (dynamic)item;
246      var trainingPartition = (IntRange)val.TrainingPartition;
247      var testPartition = (IntRange)val.TestPartition;
248      return new IntRangeJsonItem() {
249        Name = TrainingPartition,
250        MinValue = trainingPartition.Start,
251        MaxValue = trainingPartition.End,
252        Minimum = 0,
253        Maximum = Math.Max(testPartition.End, trainingPartition.End)
254      };
255    }
256
257
258    private IJsonItem GetTargetVariable(IItem item) {
259      var vars = (IEnumerable<StringValue>)((dynamic)item).InputVariables;
260      return new StringJsonItem() {
261        Name = TargetVariable,
262        Value = (string)((dynamic)item).TargetVariable,
263        ConcreteRestrictedItems = vars.Select(x => x.Value)
264      };
265    }
266
267    private IJsonItem GetAllowedInputVariables(IItem item) {
268      var vars = (IEnumerable<StringValue>)((dynamic)item).InputVariables;
269      return new StringArrayJsonItem() {
270        Name = AllowedInputVariables,
271        Value = ((IEnumerable<string>)((dynamic)item).AllowedInputVariables).ToArray(),
272        ConcreteRestrictedItems = vars.Select(x => x.Value)
273      };
274    }
275    #endregion
276  }
277}
Note: See TracBrowser for help on using the repository browser.