Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/SingleObjectiveGoalSeekingProblem.cs @ 14321

Last change on this file since 14321 was 14321, checked in by bburlacu, 8 years ago

#2679: Add goal seeking branch.

File size: 27.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Windows.Forms;
26using HeuristicLab.Collections;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Data;
30using HeuristicLab.Encodings.RealVectorEncoding;
31using HeuristicLab.Optimization;
32using HeuristicLab.Parameters;
33using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
34using HeuristicLab.Problems.DataAnalysis;
35
36namespace HeuristicLab.ProcessParameterOptimization {
37  [Item("Process parameter optimization problem (single-objective)", "Represents a single objective optimization problem which uses configurable regression solutions to evaluate targets from a given dataset.")]
38  [Creatable("Problems")]
39  [StorableClass]
40  public sealed class SingleObjectiveGoalSeekingProblem : SingleObjectiveBasicProblem<RealVectorEncoding>, IGoalSeekingProblem {
41    private const string ModifiableDatasetParameterName = "Dataset";
42    private const string ProblemDataParameterName = "ProblemData";
43    private const string ControllableParametersParameterName = "ControllableParameters";
44    private const string ControllableParameterBoundsParameterName = "ControllableParameterBounds";
45    private const string TargetGoalsParameterName = "TargetGoals";
46    private const string TargetsParameterName = "Targets";
47    private const string ModelCollectionParameterName = "ModelCollection";
48    private const string RowParameterName = "Row";
49    // these parameters are used by the pareto folding analyzer
50    private const string AllowedRangesParameterName = "AllowedRanges";
51    private const string QualitySumCutoffParameterName = "QualitySumCutoff";
52
53    #region parameters
54    public IValueParameter<RealVector> AllowedRangesParameter {
55      get { return (IValueParameter<RealVector>)Parameters[AllowedRangesParameterName]; }
56    }
57    public IFixedValueParameter<DoubleValue> QualitySumCutoffParameter {
58      get { return (IFixedValueParameter<DoubleValue>)Parameters[QualitySumCutoffParameterName]; }
59    }
60    public IValueParameter<IRegressionProblemData> ProblemDataParameter {
61      get { return (IValueParameter<IRegressionProblemData>)Parameters[ProblemDataParameterName]; }
62    }
63    public IValueParameter<IDataset> ModifiableDatasetParameter {
64      get { return (IValueParameter<IDataset>)Parameters[ModifiableDatasetParameterName]; }
65    }
66    public IValueParameter<CheckedItemList<StringValue>> ControllableParametersParameter {
67      get { return (IValueParameter<CheckedItemList<StringValue>>)Parameters[ControllableParametersParameterName]; }
68    }
69    public IValueParameter<DoubleMatrix> ControllableParameterBoundsParameter {
70      get { return (IValueParameter<DoubleMatrix>)Parameters[ControllableParameterBoundsParameterName]; }
71    }
72    public IFixedValueParameter<ItemCollection<IRegressionModel>> ModelCollectionParameter {
73      get { return (IFixedValueParameter<ItemCollection<IRegressionModel>>)Parameters[ModelCollectionParameterName]; }
74    }
75    public IValueParameter<CheckedItemList<StringValue>> TargetsParameter {
76      get { return (IValueParameter<CheckedItemList<StringValue>>)Parameters[TargetsParameterName]; }
77    }
78    public IValueParameter<DoubleMatrix> TargetGoalsParameter {
79      get { return (IValueParameter<DoubleMatrix>)Parameters[TargetGoalsParameterName]; }
80    }
81    public IFixedValueParameter<IntValue> RowParameter {
82      get { return (IFixedValueParameter<IntValue>)Parameters[RowParameterName]; }
83    }
84    #endregion
85
86    #region parameter properties
87    private IItemCollection<IRegressionModel> ModelCollection {
88      get { return ModelCollectionParameter.Value; }
89    }
90    public DoubleMatrix TargetGoals {
91      get { return TargetGoalsParameter.Value; }
92      set { TargetGoalsParameter.Value = value; }
93    }
94    // the AllowedRanges property is only used by the pareto folding analyzer
95    public RealVector AllowedRanges {
96      get { return AllowedRangesParameter.Value; }
97      set { AllowedRangesParameter.Value = value; }
98    }
99    public double QualitySumCutoff {
100      get { return QualitySumCutoffParameter.Value.Value; }
101      set { QualitySumCutoffParameter.Value.Value = value; }
102    }
103    #endregion
104
105    #region IProcessParameterOptimizationProblem properties
106    [Storable]
107    private IRegressionProblemData problemData;
108    public IRegressionProblemData ProblemData {
109      get { return problemData; }
110      set {
111        if (value == null || value == problemData) return;
112        var variables = value.Dataset.DoubleVariables.ToList();
113        if (Models.Any()) {
114          var targets = Models.Select(x => x.TargetVariable);
115          var hashset = new HashSet<string>(variables);
116          foreach (var target in targets) {
117            if (!hashset.Contains(target)) {
118              throw new ArgumentException(string.Format("Incompatible problem data. Target \"{0}\" is missing.", target));
119            }
120          }
121        }
122        problemData = value;
123        dataset = new ModifiableDataset(variables, variables.Select(x => new List<double> { ProblemData.Dataset.GetDoubleValue(x, Row) }));
124        ProblemDataParameter.Value = ProblemData;
125        UpdateControllableParameters();
126        UpdateTargetList();
127      }
128    }
129
130    public int Row {
131      get { return RowParameter.Value.Value; }
132      set { RowParameter.Value.Value = value; }
133    }
134
135    public IEnumerable<IRegressionModel> Models {
136      get { return ModelCollectionParameter.Value; }
137    }
138
139    #region targets
140    public IEnumerable<string> ActiveTargets {
141      get { return TargetList.CheckedItems.Select(x => x.Value.Value); }
142    }
143
144    public IEnumerable<string> Targets {
145      get { return TargetList.Select(x => x.Value); }
146    }
147
148    public ICheckedItemList<StringValue> TargetList {
149      get { return TargetsParameter.Value; }
150      set { TargetsParameter.Value = (CheckedItemList<StringValue>)value; }
151    }
152    #endregion
153
154    #region parameters
155    public IEnumerable<string> ActiveParameters {
156      get { return ControllableParameters.CheckedItems.Select(x => x.Value.Value); }
157    }
158
159    public ICheckedItemList<StringValue> ControllableParameters {
160      get { return ControllableParametersParameter.Value; }
161      set { ControllableParametersParameter.Value = (CheckedItemList<StringValue>)value; }
162    }
163
164    public DoubleMatrix ControllableParameterBounds {
165      get { return ControllableParameterBoundsParameter.Value; }
166      set { ControllableParameterBoundsParameter.Value = value; }
167    }
168    #endregion
169    #endregion
170
171    #region IProcessParameterOptimizationProblem methods
172    #region solutions
173    public double GetVariableValue(string variableName) {
174      return dataset.GetDoubleValue(variableName, 0);
175    }
176
177    public void SetVariableValue(string variableName, double variableValue) {
178      dataset.SetVariableValue(variableValue, variableName, 0); // will throw if the variable is not present in the dataset
179    }
180
181    public double[] GetEstimatedGoalValues(IEnumerable<double> parameters, bool round = false) {
182      var ds = (ModifiableDataset)dataset.Clone();
183      var estimatedValues = new double[ActiveTargets.Count()];
184      var e1 = parameters.GetEnumerator();
185      var e2 = ActiveParameters.GetEnumerator();
186      while (e1.MoveNext() && e2.MoveNext())
187        ds.SetVariableValue(e1.Current, e2.Current, 0);
188      var rows = new[] { 0 }; // actually just one row
189      int i = 0;
190      var models = ModelCollection.ToList();
191      foreach (var target in TargetList.CheckedItems) {
192        var average = 0d;
193        var count = 0;
194        var targetName = target.Value.Value;
195
196        foreach (var model in models) {
197          if (targetName != model.TargetVariable)
198            continue;
199          average += model.GetEstimatedValues(ds, rows).Single();
200          count++;
201        }
202        var estimatedValue = average / count;
203        if (round) {
204          var accuracy = GetTargetStepSize(targetName);
205          estimatedValues[i] = RoundToNearestStepMultiple(estimatedValue, accuracy);
206        } else {
207          estimatedValues[i] = estimatedValue;
208        }
209        ++i;
210      }
211      return estimatedValues;
212    }
213
214    public void AddModel(IRegressionModel model) {
215      var target = model.TargetVariable;
216      CheckIfDatasetContainsTarget(target);
217      ModelCollection.Add(model);
218      OnModelsChanged(this, EventArgs.Empty);
219    }
220
221    // method which throws an exception that can be caught in the event handler if the check fails
222    private void CheckIfDatasetContainsTarget(string target) {
223      if (dataset.DoubleVariables.All(x => x != target))
224        throw new ArgumentException(string.Format("Model target \"{0}\" does not exist in the dataset.", target));
225    }
226
227    public void RemoveModel(IRegressionModel model) {
228      ModelCollection.Remove(model);
229      OnModelsChanged(this, EventArgs.Empty);
230    }
231
232    public event EventHandler ModelsChanged;
233    private void OnModelsChanged(object sender, EventArgs args) {
234      var changed = ModelsChanged;
235      if (changed == null) return;
236      changed(sender, args);
237    }
238    #endregion
239
240    #region targets
241    public bool GetTargetActive(string target) {
242      var item = TargetList.SingleOrDefault(x => x.Value == target);
243      if (item == null)
244        throw new ArgumentException(string.Format("SetTargetActive: Invalid target name {0}", target));
245      return TargetList.ItemChecked(item);
246    }
247
248    public void SetTargetActive(string target, bool active) {
249      var item = TargetList.SingleOrDefault(x => x.Value == target);
250      if (item == null)
251        throw new ArgumentException(string.Format("SetTargetActive: Invalid target name {0}", target));
252      TargetList.SetItemCheckedState(item, active);
253      OnTargetsChanged(this, EventArgs.Empty);
254    }
255
256    public double GetTargetGoal(string target) {
257      if (!Targets.Contains(target))
258        throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
259      int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
260      return TargetGoals[i, 0];
261    }
262
263    public void SetTargetGoal(string target, double goal) {
264      if (!Targets.Contains(target))
265        throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
266      int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
267      TargetGoals[i, 0] = goal;
268      OnTargetsChanged(this, EventArgs.Empty);
269    }
270
271    public double GetTargetWeight(string target) {
272      if (!Targets.Contains(target))
273        throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
274      int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
275      return TargetGoals[i, 1];
276    }
277
278    public void SetTargetWeight(string target, double weight) {
279      if (!Targets.Contains(target))
280        throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
281      int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
282      TargetGoals[i, 1] = weight;
283      OnTargetsChanged(this, EventArgs.Empty);
284    }
285
286    public double GetTargetVariance(string target) {
287      if (!Targets.Contains(target))
288        throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
289      int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
290      return TargetGoals[i, 2];
291    }
292
293    public void SetTargetVariance(string target, double variance) {
294      if (!Targets.Contains(target))
295        throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
296      int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
297      TargetGoals[i, 2] = variance;
298      OnTargetsChanged(this, EventArgs.Empty);
299    }
300
301    public double GetTargetStepSize(string target) {
302      if (!Targets.Contains(target))
303        throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
304      int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
305      return TargetGoals[i, 3];
306    }
307
308    public void SetTargetStepSize(string target, double stepSize) {
309      if (!Targets.Contains(target))
310        throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
311      int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
312      TargetGoals[i, 3] = stepSize;
313      OnTargetsChanged(this, EventArgs.Empty);
314    }
315
316    public event EventHandler TargetsChanged;
317    private void OnTargetsChanged(object sender, EventArgs args) {
318      var changed = TargetsChanged;
319      if (changed == null) return;
320      changed(sender, args);
321    }
322    #endregion // targets
323
324    #region process parameters
325    public void SetParameterBounds(string parameterName, double min, double max, double step) {
326      int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameterName).Count();
327      if (i < ControllableParameterBounds.Rows) {
328        ControllableParameterBounds[i, 0] = min;
329        ControllableParameterBounds[i, 1] = max;
330        ControllableParameterBounds[i, 2] = step;
331        UpdateEncoding();
332        OnParametersChanged(this, EventArgs.Empty);
333      } else {
334        throw new ArgumentException(string.Format("SetParameterBounds: Invalid parameter name {0}", parameterName));
335      }
336    }
337
338    public double GetParameterStepSize(string parameter) {
339      int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameter).Count();
340      if (i < ControllableParameterBounds.Rows)
341        return ControllableParameterBounds[i, 2];
342      throw new ArgumentException(string.Format("GetParameterStepSize: Invalid parameter name {0}", parameter));
343    }
344
345    public void SetParameterStepSize(string parameter, double stepSize) {
346      int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameter).Count();
347      if (i < ControllableParameterBounds.Rows) {
348        ControllableParameterBounds[i, 2] = stepSize;
349        OnParametersChanged(this, EventArgs.Empty);
350      } else {
351        throw new ArgumentException(string.Format("SetParameterStepSize: Invalid parameter name {0}", parameter));
352      }
353    }
354
355    public bool GetParameterActive(string parameter) {
356      var item = ControllableParameters.SingleOrDefault(x => x.Value == parameter);
357      if (item == null)
358        throw new ArgumentException(string.Format("GetParameterActive: Invalid target name {0}", parameter));
359      return ControllableParameters.ItemChecked(item);
360    }
361
362    public void SetParameterActive(string parameter, bool active) {
363      var item = ControllableParameters.SingleOrDefault(x => x.Value == parameter);
364      if (item == null)
365        throw new ArgumentException(string.Format("SetParameterActive: Invalid target name {0}", parameter));
366      ControllableParameters.SetItemCheckedState(item, active);
367      OnParametersChanged(this, EventArgs.Empty);
368    }
369
370    /// <summary>
371    /// Returns the parameter bounds (min and max) and the step size for the specified parameter
372    /// </summary>
373    /// <param name="parameterName"></param>
374    /// <returns>A double array containing the values (min, max, step) in this order</returns>
375    public double[] GetParameterBounds(string parameterName) {
376      var index = ControllableParameters.TakeWhile(x => x.Value != parameterName).Count();
377      if (index < ControllableParameters.Count) {
378        var min = ControllableParameterBounds[index, 0];
379        var max = ControllableParameterBounds[index, 1];
380        var step = ControllableParameterBounds[index, 2];
381        return new[] { min, max, step };
382      }
383      throw new ArgumentException(string.Format("GetParameterBounds: Unknown parameter {0}.", parameterName));
384    }
385
386    public void SetControllableParameters(IEnumerable<string> parameterNames) {
387      ControllableParameters = new CheckedItemList<StringValue>();
388      foreach (var v in parameterNames) {
389        ControllableParameters.Add(new StringValue(v), false);
390      }
391      ControllableParameters.CheckedItemsChanged += ControllableParameters_OnItemsChanged;
392      ControllableParameterBounds = new DoubleMatrix(ControllableParameters.Count, 3);
393      ControllableParameterBounds.RowNames = GetControllableParameters();
394      ControllableParameterBounds.ColumnNames = new[] { "Min", "Max", "Step" };
395
396      for (int i = 0; i < ControllableParameters.Count; ++i) {
397        var itemName = ControllableParameters[i].Value;
398        var values = ProblemData.Dataset.GetReadOnlyDoubleValues(itemName).Where(x => !double.IsNaN(x) && !double.IsInfinity(x)).ToList();
399        if (!values.Any()) continue;
400
401        // add a 20% margin to allow the optimization algorithm more freedom of exploration
402        ControllableParameterBounds[i, 0] = 0.8 * values.Min(); // min
403        ControllableParameterBounds[i, 1] = 1.2 * values.Max(); // max
404        ControllableParameterBounds[i, 2] = 1e-6;               // step
405      }
406      OnParametersChanged(this, EventArgs.Empty);
407    }
408
409    public IEnumerable<string> GetControllableParameters() {
410      return ControllableParameters.Select(x => x.Value);
411    }
412
413    public event EventHandler ParametersChanged;
414    private void OnParametersChanged(object sender, EventArgs args) {
415      var changed = ParametersChanged;
416      if (changed == null) return;
417      changed(sender, args);
418    }
419    #endregion // process parameters
420    #endregion // IProcessParameterOprimizationProblem methods
421
422    #region data members
423    [Storable]
424    private ModifiableDataset dataset; // modifiable dataset
425
426    public override bool Maximization {
427      get { return true; }
428    }
429    #endregion
430
431    #region constructors
432    [StorableConstructor]
433    private SingleObjectiveGoalSeekingProblem(bool deserializing) : base(deserializing) { }
434
435    private SingleObjectiveGoalSeekingProblem(SingleObjectiveGoalSeekingProblem original, Cloner cloner)
436      : base(original, cloner) {
437      this.dataset = cloner.Clone(original.dataset);
438      this.problemData = cloner.Clone(original.problemData);
439
440      RegisterEvents();
441    }
442
443    public override IDeepCloneable Clone(Cloner cloner) {
444      return new SingleObjectiveGoalSeekingProblem(this, cloner);
445    }
446
447    [StorableHook(HookType.AfterDeserialization)]
448    private void AfterDeserialization() {
449      // backwards-compatibility
450      if (Parameters.ContainsKey("Models")) {
451        var solutions = ((IFixedValueParameter<ItemCollection<IRegressionSolution>>)Parameters["Models"]).Value;
452        var models = new ItemCollection<IRegressionModel>();
453        foreach (var solution in solutions) {
454          var model = solution.Model;
455          model.TargetVariable = solution.ProblemData.TargetVariable;
456          models.Add(model);
457        }
458        if (Parameters.ContainsKey(ModelCollectionParameterName))
459          Parameters.Remove(ModelCollectionParameterName);
460        Parameters.Add(new FixedValueParameter<ItemCollection<IRegressionModel>>(ModelCollectionParameterName, models));
461      }
462
463      RegisterEvents();
464    }
465
466    public SingleObjectiveGoalSeekingProblem() {
467      Parameters.Add(new ValueParameter<IRegressionProblemData>(ProblemDataParameterName, new RegressionProblemData()));
468      Parameters.Add(new ValueParameter<IDataset>(ModifiableDatasetParameterName, dataset) { Hidden = true });
469      Parameters.Add(new ValueParameter<CheckedItemList<StringValue>>(ControllableParametersParameterName));
470      Parameters.Add(new ValueParameter<CheckedItemList<StringValue>>(TargetsParameterName));
471      Parameters.Add(new ValueParameter<DoubleMatrix>(ControllableParameterBoundsParameterName));
472      Parameters.Add(new FixedValueParameter<ItemCollection<IRegressionModel>>(ModelCollectionParameterName, new ItemCollection<IRegressionModel>()));
473      Parameters.Add(new ValueParameter<DoubleMatrix>(TargetGoalsParameterName)); // model target weights
474      Parameters.Add(new FixedValueParameter<IntValue>(RowParameterName));
475
476      // when the problem is created, the problem data parameter will be set to a default value
477      // set the internal property to the same value
478      ProblemData = ProblemDataParameter.Value;
479
480      UpdateControllableParameters();
481      UpdateTargetList();
482      RegisterEvents();
483    }
484    #endregion
485
486    public override double Evaluate(Individual individual, IRandom random) {
487      var vector = individual.RealVector();
488      vector.ElementNames = ActiveParameters;
489
490      int i = 0;
491      // round vector according to parameter step sizes
492      foreach (var parameter in ControllableParameters.CheckedItems) {
493        var step = ControllableParameterBounds[parameter.Index, 2];
494        vector[i] = RoundToNearestStepMultiple(vector[i], step);
495        ++i;
496      }
497      i = 0;
498      var quality = 0d;
499      var estimatedValues = GetEstimatedGoalValues(vector, round: true);
500      // round target estimated values and calculate qualities
501      foreach (var target in ActiveTargets) {
502        var estimatedValue = estimatedValues[i];
503        var goal = GetTargetGoal(target);
504        var weight = GetTargetWeight(target);
505        var variance = GetTargetVariance(target);
506        quality += weight * Math.Pow(estimatedValue - goal, 2) / variance;
507        ++i;
508      }
509      return quality / i;
510    }
511
512    #region event handlers
513    private void RegisterEvents() {
514      ProblemDataParameter.ValueChanged += OnProblemDataChanged;
515      ModelCollectionParameter.Value.ItemsAdded += ModelCollection_OnItemsAdded;
516      ModelCollectionParameter.Value.ItemsRemoved += ModelCollection_OnItemsRemoved;
517      RowParameter.Value.ValueChanged += OnRowChanged;
518      ControllableParameters.CheckedItemsChanged += ControllableParameters_OnItemsChanged;
519      ControllableParameterBounds.ItemChanged += ControllableParameterBounds_ItemChanged;
520    }
521
522    private void OnRowChanged(object o, EventArgs e) {
523      // set variables in the modifiable dataset according to the new row
524      foreach (var v in dataset.DoubleVariables)
525        dataset.SetVariableValue(ProblemData.Dataset.GetDoubleValue(v, Row), v, 0);
526      // set the correct targets
527      UpdateTargetList();
528    }
529
530    private void OnProblemDataChanged(object o, EventArgs e) {
531      try {
532        ProblemData = ProblemDataParameter.Value;
533      }
534      catch (ArgumentException exception) {
535        MessageBox.Show(exception.Message, "Update Problem Data", MessageBoxButtons.OK, MessageBoxIcon.Error);
536        ProblemDataParameter.Value = problemData;
537      }
538    }
539
540    private void ModelCollection_OnItemsAdded(object sender, CollectionItemsChangedEventArgs<IRegressionModel> e) {
541      if (e.Items == null) return;
542
543      var collection = (IObservableCollection<IRegressionModel>)sender;
544      var newItems = e.Items.ToList();
545
546      foreach (var model in e.Items) {
547        try {
548          CheckIfDatasetContainsTarget(model.TargetVariable);
549        }
550        catch (ArgumentException exception) {
551          MessageBox.Show(exception.Message, "Add Model", MessageBoxButtons.OK, MessageBoxIcon.Error);
552          newItems.Remove(model);
553          collection.Remove(model);
554        }
555      }
556      UpdateTargetList();
557      OnModelsChanged(this, EventArgs.Empty);
558    }
559
560    private void ModelCollection_OnItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRegressionModel> e) {
561      if (e.Items == null) return;
562      UpdateTargetList();
563      OnModelsChanged(this, EventArgs.Empty);
564    }
565
566    private void ControllableParameters_OnItemsChanged(object o, CollectionItemsChangedEventArgs<IndexedItem<StringValue>> e) {
567      UpdateEncoding();
568    }
569
570    private void ControllableParameterBounds_ItemChanged(object o, EventArgs e) {
571      UpdateEncoding();
572    }
573    #endregion
574
575    #region helper methods
576    private void UpdateControllableParameters() {
577      if (ProblemData == null) return;
578      SetControllableParameters(ProblemData.Dataset.DoubleVariables);
579    }
580
581    private void UpdateTargetList() {
582      if (ProblemData == null) return;
583      if (!Models.Any()) {
584        TargetGoals = new DoubleMatrix();
585        TargetList = new CheckedItemList<StringValue>();
586        return;
587      }
588      var targetNames = Models.Select(x => x.TargetVariable).Distinct().ToList();
589      var oldTargetGoals = (DoubleMatrix)TargetGoals.Clone();
590      var oldRowIndices = oldTargetGoals.RowNames.Select((x, i) => new { x, i }).ToDictionary(x => x.x, x => x.i);
591      TargetGoals = new DoubleMatrix(targetNames.Count, 4);
592      TargetGoals.RowNames = targetNames;
593      TargetGoals.ColumnNames = new[] { "Goal", "Weight", "Variance", "Step size" };
594
595      TargetList = new CheckedItemList<StringValue>();
596      for (int i = 0; i < targetNames.Count; ++i) {
597        TargetList.Add(new StringValue(targetNames[i]), true);
598        int rowIndex;
599        if (oldRowIndices.TryGetValue(targetNames[i], out rowIndex)) {
600          for (int j = 0; j < TargetGoals.Columns; ++j)
601            TargetGoals[i, j] = oldTargetGoals[rowIndex, j];
602        } else {
603          TargetGoals[i, 0] = ProblemData.Dataset.GetDoubleValue(targetNames[i], Row);
604          TargetGoals[i, 1] = 1.0;
605          TargetGoals[i, 2] = ProblemData.Dataset.GetReadOnlyDoubleValues(targetNames[i]).Variance();
606          TargetGoals[i, 3] = 1e-6;
607        }
608      }
609    }
610
611    private void UpdateEncoding() {
612      var activeParameters = ActiveParameters.ToList();
613      if (Encoding == null)
614        Encoding = new RealVectorEncoding(activeParameters.Count);
615      else
616        Encoding.Length = activeParameters.Count;
617
618      Encoding.Bounds = new DoubleMatrix(activeParameters.Count, 2); // only two columns: min and max
619      Encoding.Bounds.RowNames = activeParameters;
620      Encoding.Bounds.ColumnNames = new[] { "Min.", "Max." };
621
622      int i = 0;
623      foreach (var item in ControllableParameters.CheckedItems) {
624        var index = item.Index;
625        Encoding.Bounds[i, 0] = ControllableParameterBounds[index, 0];
626        Encoding.Bounds[i, 1] = ControllableParameterBounds[index, 1];
627        ++i;
628      }
629    }
630    #endregion
631
632    #region util
633    private static double RoundToNearestStepMultiple(double value, double step) {
634      return step * (long)Math.Round(value / step);
635    }
636    #endregion
637  }
638}
Note: See TracBrowser for help on using the repository browser.