Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
10/14/16 15:51:10 (8 years ago)
Author:
bburlacu
Message:

#2679: Refactor problems and extract common functionality in static util class.

Location:
branches/HeuristicLab.GoalSeekingProblem
Files:
15 added
5 edited
2 copied

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem.Views/3.4/Plugin.cs

    r14329 r14333  
    2222using HeuristicLab.PluginInfrastructure;
    2323
    24 namespace HeuristicLab.GoalSeekingProblem {
    25   [Plugin("HeuristicLab.GoalSeekingProblem", "3.4.0.0")]
    26   [PluginFile("HeuristicLab.GoalSeekingProblem-3.4.dll", PluginFileType.Assembly)]
    27   [PluginDependency("HeuristicLab.Collections", "3.3")]
     24namespace HeuristicLab.GoalSeekingProblem.Views {
     25  [Plugin("HeuristicLab.GoalSeekingProblem.Views", "3.4.0.0")]
     26  [PluginFile("HeuristicLab.GoalSeekingProblem.Views-3.4.dll", PluginFileType.Assembly)]
    2827  [PluginDependency("HeuristicLab.Common", "3.3")]
    2928  [PluginDependency("HeuristicLab.Core", "3.3")]
    30   [PluginDependency("HeuristicLab.Data", "3.3")]
    31   [PluginDependency("HeuristicLab.Encodings.RealVectorEncoding", "3.3")]
    32   [PluginDependency("HeuristicLab.Operators", "3.3")]
    33   [PluginDependency("HeuristicLab.Optimization", "3.3")]
    34   [PluginDependency("HeuristicLab.Parameters", "3.3")]
    35   [PluginDependency("HeuristicLab.Persistence", "3.3")]
    36   [PluginDependency("HeuristicLab.Problems.DataAnalysis", "3.4")]
    37   [PluginDependency("HeuristicLab.Problems.DataAnalysis.Symbolic", "3.4")]
    38   [PluginDependency("HeuristicLab.Problems.DataAnalysis.Symbolic.Regression", "3.4")]
     29  [PluginDependency("HeuristicLab.MainForm", "3.3")]
     30  [PluginDependency("HeuristicLab.MainForm.WindowsForms", "3.3")]
     31
    3932  public class HeuristicLabProcessParameterOptimizationPlugin : PluginBase {
    4033  }
  • branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem.Views/3.4/Plugin.cs.frame

    r14329 r14333  
    2222using HeuristicLab.PluginInfrastructure;
    2323
    24 namespace HeuristicLab.GoalSeekingProblem {
    25   [Plugin("HeuristicLab.GoalSeekingProblem", "3.4.0.0")]
    26   [PluginFile("HeuristicLab.GoalSeekingProblem-3.4.dll", PluginFileType.Assembly)]
    27   [PluginDependency("HeuristicLab.Collections", "3.3")]
     24namespace HeuristicLab.GoalSeekingProblem.Views {
     25  [Plugin("HeuristicLab.GoalSeekingProblem.Views", "3.4.0.0")]
     26  [PluginFile("HeuristicLab.GoalSeekingProblem.Views-3.4.dll", PluginFileType.Assembly)]
    2827  [PluginDependency("HeuristicLab.Common", "3.3")]
    2928  [PluginDependency("HeuristicLab.Core", "3.3")]
    30   [PluginDependency("HeuristicLab.Data", "3.3")]
    31   [PluginDependency("HeuristicLab.Encodings.RealVectorEncoding", "3.3")]
    32   [PluginDependency("HeuristicLab.Operators", "3.3")]
    33   [PluginDependency("HeuristicLab.Optimization", "3.3")]
    34   [PluginDependency("HeuristicLab.Parameters", "3.3")]
    35   [PluginDependency("HeuristicLab.Persistence", "3.3")]
    36   [PluginDependency("HeuristicLab.Problems.DataAnalysis", "3.4")]
    37   [PluginDependency("HeuristicLab.Problems.DataAnalysis.Symbolic", "3.4")]
    38   [PluginDependency("HeuristicLab.Problems.DataAnalysis.Symbolic.Regression", "3.4")]
     29  [PluginDependency("HeuristicLab.MainForm", "3.3")]
     30  [PluginDependency("HeuristicLab.MainForm.WindowsForms", "3.3")]
     31
    3932  public class HeuristicLabProcessParameterOptimizationPlugin : PluginBase {
    4033  }
  • branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/GoalSeekingProblem.csproj

    r14324 r14333  
    189189    <None Include="Plugin.cs.frame" />
    190190    <Compile Include="Analyzers\BestSolutionAnalyzer.cs" />
     191    <Compile Include="GoalParameter.cs" />
     192    <Compile Include="GoalSeekingUtil.cs" />
     193    <Compile Include="InputParameter.cs" />
    191194    <Compile Include="IGoalSeekingProblem.cs" />
    192195    <Compile Include="Plugin.cs" />
  • branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/IGoalSeekingProblem.cs

    r14324 r14333  
    2222using System;
    2323using System.Collections.Generic;
    24 using HeuristicLab.Core;
    25 using HeuristicLab.Data;
    2624using HeuristicLab.Optimization;
    2725using HeuristicLab.Problems.DataAnalysis;
     
    2927namespace HeuristicLab.GoalSeeking {
    3028  public interface IGoalSeekingProblem : IProblem {
    31     IRegressionProblemData ProblemData { get; set; }
    32 
     29    void Configure(IRegressionProblemData problemData, int row);
    3330    //rounding ?
    3431    IEnumerable<double> GetEstimatedGoalValues(IEnumerable<double> parameterValues, bool round = false);
    35     int Row { get; set; }
    3632
    3733    //Models?
     
    3935    void AddModel(IRegressionModel model);
    4036    void RemoveModel(IRegressionModel model);
     37
     38    //targets and parameters
     39    IEnumerable<GoalParameter> Goals { get; }
     40    IEnumerable<InputParameter> Inputs { get; }
     41
     42    //events
    4143    event EventHandler ModelsChanged;
    42 
    43     #region targets
    44     double GetTargetGoal(string target);
    45     void SetTargetGoal(string target, double goal);
    46 
    47     //variance ?
    48     double GetTargetWeight(string target);
    49     void SetTargetWeight(string target, double weight);
    50 
    51     double GetTargetVariance(string target);
    52     void SetTargetVariance(string target, double variance);
    53 
    54     double GetTargetStepSize(string target);
    55     void SetTargetStepSize(string target, double stepSize);
    56 
    5744    event EventHandler TargetsChanged;
    58     #endregion
    59 
    60     #region parameters
    61     ICheckedItemList<StringValue> ControllableParameters { get; }
    62     DoubleMatrix ControllableParameterBounds { get; }
    63 
    64     IEnumerable<string> GetControllableParameters();
    65     void SetControllableParameters(IEnumerable<string> parameterNames);
    66 
    67     bool GetParameterActive(string parameter);
    68     void SetParameterActive(string parameter, bool active);
    69 
    70     double[] GetParameterBounds(string parameterName);
    71     void SetParameterBounds(string parameterName, double min, double max, double step);
    72     // set get ParameterStepSize, set get parameters active
    73     // parameters changed event
    74     double GetParameterStepSize(string parameter);
    75     void SetParameterStepSize(string parameter, double stepSize);
    76 
    7745    event EventHandler ParametersChanged;
    78     #endregion
    7946  }
    8047}
  • branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/MultiObjectiveGoalSeekingProblem.cs

    r14325 r14333  
    2323using System.Collections.Generic;
    2424using System.Linq;
    25 using System.Windows.Forms;
    2625using HeuristicLab.Collections;
    2726using HeuristicLab.Common;
     
    3938  [StorableClass]
    4039  public sealed class MultiObjectiveGoalSeekingProblem : MultiObjectiveBasicProblem<RealVectorEncoding>, IGoalSeekingProblem {
     40    #region parameter names
    4141    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
     42    private const string InputsParameterName = "Inputs";
     43    private const string GoalsParameterName = "Goals";
     44    private const string ModelsParameterName = "Models";
    5045    private const string QualitySumCutoffParameterName = "QualitySumCutoff";
     46    #endregion
    5147
    5248    #region parameters
     49    public IValueParameter<CheckedItemList<InputParameter>> InputsParameter {
     50      get { return (IValueParameter<CheckedItemList<InputParameter>>)Parameters[InputsParameterName]; }
     51    }
     52    public IValueParameter<CheckedItemList<GoalParameter>> GoalsParameter {
     53      get { return (IValueParameter<CheckedItemList<GoalParameter>>)Parameters[GoalsParameterName]; }
     54    }
     55    public IFixedValueParameter<ItemCollection<IRegressionModel>> ModelsParameter {
     56      get { return (IFixedValueParameter<ItemCollection<IRegressionModel>>)Parameters[ModelsParameterName]; }
     57    }
    5358    public IFixedValueParameter<DoubleValue> QualitySumCutoffParameter {
    5459      get { return (IFixedValueParameter<DoubleValue>)Parameters[QualitySumCutoffParameterName]; }
    5560    }
    56     public IValueParameter<IRegressionProblemData> ProblemDataParameter {
    57       get { return (IValueParameter<IRegressionProblemData>)Parameters[ProblemDataParameterName]; }
    58     }
    59     public IValueParameter<CheckedItemList<StringValue>> ControllableParametersParameter {
    60       get { return (IValueParameter<CheckedItemList<StringValue>>)Parameters[ControllableParametersParameterName]; }
    61     }
    62     public IValueParameter<DoubleMatrix> ControllableParameterBoundsParameter {
    63       get { return (IValueParameter<DoubleMatrix>)Parameters[ControllableParameterBoundsParameterName]; }
    64     }
    65     public IFixedValueParameter<ItemCollection<IRegressionModel>> ModelCollectionParameter {
    66       get { return (IFixedValueParameter<ItemCollection<IRegressionModel>>)Parameters[ModelCollectionParameterName]; }
    67     }
    68     public IValueParameter<CheckedItemList<StringValue>> TargetsParameter {
    69       get { return (IValueParameter<CheckedItemList<StringValue>>)Parameters[TargetsParameterName]; }
    70     }
    71     public IValueParameter<DoubleMatrix> TargetGoalsParameter {
    72       get { return (IValueParameter<DoubleMatrix>)Parameters[TargetGoalsParameterName]; }
    73     }
    74     public IFixedValueParameter<IntValue> RowParameter {
    75       get { return (IFixedValueParameter<IntValue>)Parameters[RowParameterName]; }
    76     }
    77     #endregion
    78 
    79     #region parameter properties
    80     private IItemCollection<IRegressionModel> ModelCollection {
    81       get { return ModelCollectionParameter.Value; }
    82     }
    83     public DoubleMatrix TargetGoals {
    84       get { return TargetGoalsParameter.Value; }
    85       set { TargetGoalsParameter.Value = value; }
    86     }
    87     public double QualitySumCutoff {
    88       get { return QualitySumCutoffParameter.Value.Value; }
    89       set { QualitySumCutoffParameter.Value.Value = value; }
    90     }
    91     #endregion
    92 
    93     #region IProcessParameterOptimizationProblem properties
    94     [Storable]
    95     private IRegressionProblemData problemData;
    96     public IRegressionProblemData ProblemData {
    97       get { return problemData; }
    98       set {
    99         if (value == null || value == problemData) return;
    100         var variables = value.Dataset.DoubleVariables.ToList();
    101         if (Models.Any()) {
    102           var targets = Models.Select(x => x.TargetVariable);
    103           var hashset = new HashSet<string>(variables);
    104           foreach (var target in targets) {
    105             if (!hashset.Contains(target)) {
    106               throw new ArgumentException(string.Format("Incompatible problem data. Target \"{0}\" is missing.", target));
    107             }
    108           }
    109         }
    110         problemData = value;
    111         dataset = new ModifiableDataset(variables, variables.Select(x => new List<double> { ProblemData.Dataset.GetDoubleValue(x, Row) }));
    112         ProblemDataParameter.Value = ProblemData;
    113         UpdateControllableParameters();
    114         UpdateTargetList();
    115       }
    116     }
    117 
    118     public int Row {
    119       get { return RowParameter.Value.Value; }
    120       set { RowParameter.Value.Value = value; }
    121     }
    122 
     61    #endregion
     62
     63    #region IGoalSeekingProblem implementation
    12364    public IEnumerable<IRegressionModel> Models {
    124       get { return ModelCollectionParameter.Value; }
    125     }
    126 
    127     #region targets
    128     public ICheckedItemList<StringValue> TargetList {
    129       get { return TargetsParameter.Value; }
    130       set { TargetsParameter.Value = (CheckedItemList<StringValue>)value; }
    131     }
    132     // convenience method
    133     private IEnumerable<string> ActiveTargets {
    134       get { return TargetList.CheckedItems.Select(x => x.Value.Value); }
    135     }
    136     #endregion
    137 
    138     #region parameters
    139     public ICheckedItemList<StringValue> ControllableParameters {
    140       get { return ControllableParametersParameter.Value; }
    141       set { ControllableParametersParameter.Value = (CheckedItemList<StringValue>)value; }
    142     }
    143     // convenience method
    144     private IEnumerable<string> ActiveParameters {
    145       get { return ControllableParameters.CheckedItems.Select(x => x.Value.Value); }
    146     }
    147     public DoubleMatrix ControllableParameterBounds {
    148       get { return ControllableParameterBoundsParameter.Value; }
    149       set { ControllableParameterBoundsParameter.Value = value; }
    150     }
    151     #endregion
    152     #endregion
    153 
    154     #region IProcessParameterOptimizationProblem methods
    155     #region models
     65      get { return ModelsParameter.Value; }
     66    }
     67
     68    public IEnumerable<GoalParameter> Goals {
     69      get { return GoalsParameter.Value; }
     70    }
     71
     72    public IEnumerable<InputParameter> Inputs {
     73      get { return InputsParameter.Value; }
     74    }
     75
     76    public void AddModel(IRegressionModel model) {
     77      var models = ModelsParameter.Value;
     78      models.Add(model);
     79      GoalSeekingUtil.RaiseEvent(this, ModelsChanged);
     80    }
     81
     82    public void RemoveModel(IRegressionModel model) {
     83      var models = ModelsParameter.Value;
     84      models.Remove(model);
     85      GoalSeekingUtil.RaiseEvent(this, ModelsChanged);
     86    }
     87
     88    public void Configure(IRegressionProblemData problemData, int row) {
     89      GoalSeekingUtil.Configure(Goals, Inputs, problemData, row);
     90    }
     91
    15692    public IEnumerable<double> GetEstimatedGoalValues(IEnumerable<double> parameterValues, bool round = false) {
    15793      var ds = (ModifiableDataset)dataset.Clone();
    158       foreach (var parameter in ActiveParameters.Zip(parameterValues, (p, v) => new { Name = p, Value = v })) {
     94      foreach (var parameter in ActiveInputs.Zip(parameterValues, (p, v) => new { Name = p.Name, Value = v })) {
    15995        ds.SetVariableValue(parameter.Value, parameter.Name, 0);
    16096      }
    16197      var rows = new[] { 0 }; // actually just one row
    162 
    16398      var estimatedValues =
    164         round ? ActiveTargets.Select(t => RoundToNearestStepMultiple(GetModels(t).Average(m => m.GetEstimatedValues(ds, rows).Single()), GetTargetStepSize(t)))
    165               : ActiveTargets.Select(t => GetModels(t).Average(m => m.GetEstimatedValues(ds, rows).Single()));
     99        round ? ActiveGoals.Select(t => RoundToNearestStepMultiple(GetModels(t.Name).Average(m => m.GetEstimatedValues(ds, rows).Single()), t.Step))
     100              : ActiveGoals.Select(t => GetModels(t.Name).Average(m => m.GetEstimatedValues(ds, rows).Single()));
    166101      return estimatedValues;
    167102    }
    168103
    169     public void AddModel(IRegressionModel model) {
    170       var target = model.TargetVariable;
    171       CheckIfDatasetContainsTarget(target);
    172       ModelCollection.Add(model);
    173       OnModelsChanged(this, EventArgs.Empty);
    174     }
    175 
    176     // method which throws an exception that can be caught in the event handler if the check fails
    177     private void CheckIfDatasetContainsTarget(string target) {
    178       if (dataset.DoubleVariables.All(x => x != target))
    179         throw new ArgumentException(string.Format("Model target \"{0}\" does not exist in the dataset.", target));
    180     }
    181 
    182     public void RemoveModel(IRegressionModel model) {
    183       ModelCollection.Remove(model);
    184       OnModelsChanged(this, EventArgs.Empty);
    185     }
    186 
    187104    public event EventHandler ModelsChanged;
    188     private void OnModelsChanged(object sender, EventArgs args) {
    189       var changed = ModelsChanged;
    190       if (changed == null) return;
    191       changed(sender, args);
    192     }
    193     #endregion
    194 
    195     #region targets
    196     public bool GetTargetActive(string target) {
    197       var item = TargetList.SingleOrDefault(x => x.Value == target);
    198       if (item == null)
    199         throw new ArgumentException(string.Format("SetTargetActive: Invalid target name {0}", target));
    200       return TargetList.ItemChecked(item);
    201     }
    202 
    203     public void SetTargetActive(string target, bool active) {
    204       var item = TargetList.SingleOrDefault(x => x.Value == target);
    205       if (item == null)
    206         throw new ArgumentException(string.Format("SetTargetActive: Invalid target name {0}", target));
    207       TargetList.SetItemCheckedState(item, active);
    208       OnTargetsChanged(this, EventArgs.Empty);
    209     }
    210 
    211     public double GetTargetGoal(string target) {
    212       if (!IsValidTarget(target))
    213         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
    214       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
    215       return TargetGoals[i, 0];
    216     }
    217 
    218     public void SetTargetGoal(string target, double goal) {
    219       if (!IsValidTarget(target))
    220         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
    221       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
    222       TargetGoals[i, 0] = goal;
    223       OnTargetsChanged(this, EventArgs.Empty);
    224     }
    225 
    226     public double GetTargetWeight(string target) {
    227       if (!IsValidTarget(target))
    228         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
    229       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
    230       return TargetGoals[i, 1];
    231     }
    232 
    233     public void SetTargetWeight(string target, double weight) {
    234       if (!IsValidTarget(target))
    235         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
    236       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
    237       TargetGoals[i, 1] = weight;
    238       OnTargetsChanged(this, EventArgs.Empty);
    239     }
    240 
    241     public double GetTargetVariance(string target) {
    242       if (!IsValidTarget(target))
    243         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
    244       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
    245       return TargetGoals[i, 2];
    246     }
    247 
    248     public void SetTargetVariance(string target, double variance) {
    249       if (!IsValidTarget(target))
    250         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
    251       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
    252       TargetGoals[i, 2] = variance;
    253       OnTargetsChanged(this, EventArgs.Empty);
    254     }
    255 
    256     public double GetTargetStepSize(string target) {
    257       if (!IsValidTarget(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, 3];
    261     }
    262 
    263     public void SetTargetStepSize(string target, double stepSize) {
    264       if (!IsValidTarget(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, 3] = stepSize;
    268       OnTargetsChanged(this, EventArgs.Empty);
    269     }
    270 
    271105    public event EventHandler TargetsChanged;
    272     private void OnTargetsChanged(object sender, EventArgs args) {
    273       var changed = TargetsChanged;
    274       if (changed == null) return;
    275       changed(sender, args);
    276     }
    277     #endregion // targets
    278 
    279     #region process parameters
    280     /// <summary>
    281     /// Returns the parameter bounds (min and max) and the step size for the specified parameter
    282     /// </summary>
    283     /// <param name="parameterName"></param>
    284     /// <returns>A double array containing the values (min, max, step) in this order</returns>
    285     public double[] GetParameterBounds(string parameterName) {
    286       var index = ControllableParameters.TakeWhile(x => x.Value != parameterName).Count();
    287       if (index < ControllableParameters.Count) {
    288         var min = ControllableParameterBounds[index, 0];
    289         var max = ControllableParameterBounds[index, 1];
    290         var step = ControllableParameterBounds[index, 2];
    291         return new[] { min, max, step };
    292       }
    293       throw new ArgumentException(string.Format("GetParameterBounds: Unknown parameter {0}.", parameterName));
    294     }
    295 
    296     public void SetParameterBounds(string parameterName, double min, double max, double step) {
    297       int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameterName).Count();
    298       if (i < ControllableParameterBounds.Rows) {
    299         ControllableParameterBounds[i, 0] = min;
    300         ControllableParameterBounds[i, 1] = max;
    301         ControllableParameterBounds[i, 2] = step;
    302         UpdateEncoding();
    303         OnParametersChanged(this, EventArgs.Empty);
    304       } else {
    305         throw new ArgumentException(string.Format("SetParameterBounds: Invalid parameter name {0}", parameterName));
    306       }
    307 
    308     }
    309 
    310     public double GetParameterStepSize(string parameter) {
    311       int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameter).Count();
    312       if (i < ControllableParameterBounds.Rows)
    313         return ControllableParameterBounds[i, 2];
    314       throw new ArgumentException(string.Format("GetParameterStepSize: Invalid parameter name {0}", parameter));
    315     }
    316 
    317     public void SetParameterStepSize(string parameter, double stepSize) {
    318       int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameter).Count();
    319       if (i < ControllableParameterBounds.Rows) {
    320         ControllableParameterBounds[i, 2] = stepSize;
    321         OnParametersChanged(this, EventArgs.Empty);
    322         return;
    323       }
    324       throw new ArgumentException(string.Format("SetParameterStepSize: Invalid parameter name {0}", parameter));
    325     }
    326 
    327     public bool GetParameterActive(string parameter) {
    328       var item = ControllableParameters.SingleOrDefault(x => x.Value == parameter);
    329       if (item == null)
    330         throw new ArgumentException(string.Format("GetParameterActive: Invalid target name {0}", parameter));
    331       return ControllableParameters.ItemChecked(item);
    332     }
    333 
    334     public void SetParameterActive(string parameter, bool active) {
    335       var item = ControllableParameters.SingleOrDefault(x => x.Value == parameter);
    336       if (item == null)
    337         throw new ArgumentException(string.Format("SetParameterActive: Invalid target name {0}", parameter));
    338       ControllableParameters.SetItemCheckedState(item, active);
    339       OnParametersChanged(this, EventArgs.Empty);
    340     }
    341 
    342     public void SetControllableParameters(IEnumerable<string> parameterNames) {
    343       ControllableParameters = new CheckedItemList<StringValue>();
    344       foreach (var v in parameterNames) {
    345         ControllableParameters.Add(new StringValue(v), false);
    346       }
    347       ControllableParameters.CheckedItemsChanged += ControllableParameters_OnItemsChanged;
    348       ControllableParameterBounds = new DoubleMatrix(ControllableParameters.Count, 3);
    349       ControllableParameterBounds.RowNames = GetControllableParameters();
    350       ControllableParameterBounds.ColumnNames = new[] { "Min", "Max", "Step" };
    351 
    352       for (int i = 0; i < ControllableParameters.Count; ++i) {
    353         var itemName = ControllableParameters[i].Value;
    354         var values = ProblemData.Dataset.GetReadOnlyDoubleValues(itemName).Where(x => !double.IsNaN(x) && !double.IsInfinity(x)).ToList();
    355         if (!values.Any()) continue;
    356 
    357         // add a 20% margin to allow the optimization algorithm more freedom of exploration
    358         ControllableParameterBounds[i, 0] = 0.8 * values.Min(); // min
    359         ControllableParameterBounds[i, 1] = 1.2 * values.Max(); // max
    360         ControllableParameterBounds[i, 2] = 1e-6;               // step
    361       }
    362       OnParametersChanged(this, EventArgs.Empty);
    363     }
    364 
    365     public IEnumerable<string> GetControllableParameters() {
    366       return ControllableParameters.Select(x => x.Value);
    367     }
    368 
    369106    public event EventHandler ParametersChanged;
    370     private void OnParametersChanged(object sender, EventArgs args) {
    371       var changed = ParametersChanged;
    372       if (changed == null) return;
    373       changed(sender, args);
    374     }
    375     #endregion // process parameters
    376     #endregion // IGoalSeekingProblem methods
    377 
    378     #region data members
     107    #endregion
     108
     109    private IEnumerable<GoalParameter> ActiveGoals {
     110      get { return Goals.Where(x => x.Active); }
     111    }
     112    private IEnumerable<InputParameter> ActiveInputs {
     113      get { return Inputs.Where(x => x.Active); }
     114    }
     115    private double QualitySumCutoff {
     116      get { return QualitySumCutoffParameter.Value.Value; }
     117    }
     118
    379119    [Storable]
    380120    private ModifiableDataset dataset; // modifiable dataset
     
    389129      get { return (ValueParameter<BoolArray>)Parameters["Maximization"]; }
    390130    }
    391     #endregion
    392131
    393132    #region constructors
     
    397136    private MultiObjectiveGoalSeekingProblem(MultiObjectiveGoalSeekingProblem original, Cloner cloner) : base(original, cloner) {
    398137      this.dataset = cloner.Clone(original.dataset);
    399       this.problemData = cloner.Clone(original.problemData);
    400138
    401139      RegisterEvents();
     
    408146    [StorableHook(HookType.AfterDeserialization)]
    409147    private void AfterDeserialization() {
    410       if (Parameters.ContainsKey("Accuracy"))
    411         Parameters.Remove("Accuracy");
    412 
    413       if (!Parameters.ContainsKey(QualitySumCutoffParameterName)) {
    414         Parameters.Add(new FixedValueParameter<DoubleValue>(QualitySumCutoffParameterName, new DoubleValue(0.2)));
    415         QualitySumCutoffParameter.Hidden = true;
    416       }
    417 
    418       if (ProblemData == null && Parameters.ContainsKey(ProblemDataParameterName)) {
    419         ProblemData = ProblemDataParameter.Value;
    420       }
    421 
    422       if (!Parameters.ContainsKey(ModifiableDatasetParameterName)) {
    423         Parameters.Add(new ValueParameter<IDataset>(ModifiableDatasetParameterName, dataset) { Hidden = true });
    424       }
    425 
    426       // backwards-compatibility
    427       if (Parameters.ContainsKey("Models")) {
    428         var solutions = ((IFixedValueParameter<ItemCollection<IRegressionSolution>>)Parameters["Models"]).Value;
    429         var models = new ItemCollection<IRegressionModel>();
    430         foreach (var solution in solutions) {
    431           var model = solution.Model;
    432           model.TargetVariable = solution.ProblemData.TargetVariable;
    433           models.Add(model);
    434         }
    435         if (Parameters.ContainsKey(ModelCollectionParameterName))
    436           Parameters.Remove(ModelCollectionParameterName);
    437         Parameters.Add(new FixedValueParameter<ItemCollection<IRegressionModel>>(ModelCollectionParameterName, models));
    438       }
    439 
    440148      RegisterEvents();
    441149    }
    442150
    443151    public MultiObjectiveGoalSeekingProblem() {
    444       Parameters.Add(new ValueParameter<IRegressionProblemData>(ProblemDataParameterName, new RegressionProblemData()));
     152      dataset = new ModifiableDataset();
    445153      Parameters.Add(new ValueParameter<IDataset>(ModifiableDatasetParameterName, dataset) { Hidden = true });
    446       Parameters.Add(new ValueParameter<CheckedItemList<StringValue>>(ControllableParametersParameterName));
    447       Parameters.Add(new ValueParameter<CheckedItemList<StringValue>>(TargetsParameterName));
    448       Parameters.Add(new ValueParameter<DoubleMatrix>(ControllableParameterBoundsParameterName));
    449       Parameters.Add(new FixedValueParameter<ItemCollection<IRegressionModel>>(ModelCollectionParameterName, new ItemCollection<IRegressionModel>()));
    450       Parameters.Add(new ValueParameter<DoubleMatrix>(TargetGoalsParameterName)); // model target weights
    451       Parameters.Add(new FixedValueParameter<IntValue>(RowParameterName));
     154      Parameters.Add(new ValueParameter<CheckedItemList<InputParameter>>(InputsParameterName));
     155      Parameters.Add(new ValueParameter<CheckedItemList<GoalParameter>>(GoalsParameterName));
     156      Parameters.Add(new FixedValueParameter<ItemCollection<IRegressionModel>>(ModelsParameterName, new ItemCollection<IRegressionModel>()));
    452157      Parameters.Add(new FixedValueParameter<DoubleValue>(QualitySumCutoffParameterName, new DoubleValue(0.2)));
    453 
    454158      QualitySumCutoffParameter.Hidden = true;
    455 
    456       // when the problem is created, the problem data parameter will be set to a default value
    457       // set the internal property to the same value
    458       ProblemData = ProblemDataParameter.Value;
    459 
    460       UpdateControllableParameters();
    461       UpdateTargetList();
     159      EncodingParameter.Hidden = true;
     160      EvaluatorParameter.Hidden = true;
     161      SolutionCreatorParameter.Hidden = true;
     162      MaximizationParameter.Hidden = true;
     163      GoalSeekingUtil.UpdateInputs(InputsParameter.Value, Models, InputParameterChanged);
     164      Encoding = GoalSeekingUtil.CreateEncoding(ActiveInputs);
     165      GoalSeekingUtil.UpdateTargets(GoalsParameter.Value, Models, GoalParameterChanged);
    462166      RegisterEvents();
    463167    }
     
    466170    public override double[] Evaluate(Individual individual, IRandom random) {
    467171      var vector = individual.RealVector();
    468       vector.ElementNames = ActiveParameters;
    469 
     172      vector.ElementNames = ActiveInputs.Select(x => x.Name);
    470173      int i = 0;
    471174      // round vector according to parameter step sizes
    472       foreach (var parameter in ControllableParameters.CheckedItems) {
    473         var step = ControllableParameterBounds[parameter.Index, 2];
    474         vector[i] = RoundToNearestStepMultiple(vector[i], step);
     175      foreach (var parameter in ActiveInputs) {
     176        vector[i] = RoundToNearestStepMultiple(vector[i], parameter.Step);
    475177        ++i;
    476178      }
    477179      var estimatedValues = GetEstimatedGoalValues(vector, round: true);
    478       var qualities = TargetList.CheckedItems.Zip(estimatedValues, (t, v) => new { Name = t.Value.Value, Index = t.Index, EstimatedValue = v })
    479                                 .Select(target => {
    480                                   var goal = TargetGoals[target.Index, 0];
    481                                   var weight = TargetGoals[target.Index, 1];
    482                                   var variance = TargetGoals[target.Index, 2];
    483                                   return weight * Math.Pow(target.EstimatedValue - goal, 2) / variance;
    484                                 });
     180      var qualities = ActiveGoals.Zip(estimatedValues, (t, v) => new { Target = t, EstimatedValue = v })
     181                                 .Select(x => x.Target.Weight * Math.Pow(x.EstimatedValue - x.Target.Goal, 2) / x.Target.Variance);
    485182      return qualities.ToArray();
    486183    }
    487184
     185    #region pareto analyzer
    488186    public override void Analyze(Individual[] individuals, double[][] qualities, ResultCollection results, IRandom random) {
    489187      var matrix = FilterFrontsByQualitySum(individuals, qualities, Math.Max(QualitySumCutoff, qualities.Min(x => x.Sum())));
     
    498196
    499197    private DoubleMatrix FilterFrontsByQualitySum(Individual[] individuals, double[][] qualities, double qualitySumCutoff) {
    500       var activeParameters = ActiveParameters.ToList();
    501       var activeTargets = ActiveTargets.ToList();
     198      var activeParameters = ActiveInputs.ToList();
     199      var activeGoals = ActiveGoals.ToList();
    502200      var filteredModels = new List<double[]>();
    503201      var rowNames = new List<string>();
    504202      // build list of column names by combining target and parameter names (with their respective original and estimated values)
    505203      var columnNames = new List<string> { "Quality Sum" };
    506       foreach (var target in activeTargets) {
    507         columnNames.Add(target);
    508         columnNames.Add(target + " (estimated)");
    509       }
    510       foreach (var controllableParameter in activeParameters) {
    511         columnNames.Add(controllableParameter);
    512         columnNames.Add(controllableParameter + " (estimated)");
    513         columnNames.Add(controllableParameter + " (deviation)");
     204      foreach (var target in activeGoals) {
     205        columnNames.Add(target.Name);
     206        columnNames.Add(target.Name + " (estimated)");
     207      }
     208      foreach (var parameter in activeParameters) {
     209        columnNames.Add(parameter.Name);
     210        columnNames.Add(parameter.Name + " (estimated)");
     211        columnNames.Add(parameter.Name + " (deviation)");
    514212      }
    515213      // filter models based on their quality sum; remove duplicate models
     
    524222        rowValues[0] = qualitySum;
    525223        int offset = 1;
    526         for (int j = 0; j < activeTargets.Count * 2; j += 2) {
     224        for (int j = 0; j < activeGoals.Count * 2; j += 2) {
    527225          int k = j + offset;
    528           var goal = GetTargetGoal(activeTargets[j / 2]);
     226          var goal = activeGoals[j / 2].Goal;
    529227          rowValues[k] = goal; // original value
    530228          rowValues[k + 1] = estimatedValues[j / 2]; // estimated value
    531229        }
    532         offset += activeTargets.Count * 2;
     230        offset += activeGoals.Count * 2;
    533231        for (int j = 0; j < activeParameters.Count * 3; j += 3) {
    534232          int k = j + offset;
    535           rowValues[k] = problemData.Dataset.GetDoubleValue(columnNames[k], Row);
     233          rowValues[k] = 0; // TODO: figure this out and fix
    536234          rowValues[k + 1] = vector[j / 3];
    537235          rowValues[k + 2] = rowValues[k + 1] - rowValues[k];
     
    550248      return matrix;
    551249    }
     250    #endregion
    552251
    553252    #region event handlers
    554253    private void RegisterEvents() {
    555       ProblemDataParameter.ValueChanged += OnProblemDataChanged;
    556       ModelCollectionParameter.Value.ItemsAdded += ModelCollection_OnItemsAdded;
    557       ModelCollectionParameter.Value.ItemsRemoved += ModelCollection_OnItemsRemoved;
    558       RowParameter.Value.ValueChanged += OnRowChanged;
    559       ControllableParameters.CheckedItemsChanged += ControllableParameters_OnItemsChanged;
    560       ControllableParameterBounds.ItemChanged += ControllableParameterBounds_ItemChanged;
    561     }
    562 
    563     private void OnRowChanged(object o, EventArgs e) {
    564       // set variables in the modifiable dataset according to the new row
    565       foreach (var v in dataset.DoubleVariables)
    566         dataset.SetVariableValue(ProblemData.Dataset.GetDoubleValue(v, Row), v, 0);
    567       // set the correct targets
    568       UpdateTargetList();
    569     }
    570 
    571     private void OnProblemDataChanged(object o, EventArgs e) {
    572       try {
    573         ProblemData = ProblemDataParameter.Value;
    574       }
    575       catch (ArgumentException exception) {
    576         MessageBox.Show(exception.Message, "Update Problem Data", MessageBoxButtons.OK, MessageBoxIcon.Error);
    577         ProblemDataParameter.Value = problemData;
    578       }
    579     }
    580 
    581     private void ModelCollection_OnItemsAdded(object sender, CollectionItemsChangedEventArgs<IRegressionModel> e) {
    582       if (e.Items == null) return;
    583 
    584       var collection = (IObservableCollection<IRegressionModel>)sender;
    585       var newItems = e.Items.ToList();
    586 
    587       foreach (var model in e.Items) {
    588         try {
    589           CheckIfDatasetContainsTarget(model.TargetVariable);
    590         }
    591         catch (ArgumentException exception) {
    592           MessageBox.Show(exception.Message, "Add Model", MessageBoxButtons.OK, MessageBoxIcon.Error);
    593           newItems.Remove(model);
    594           collection.Remove(model);
    595         }
    596       }
    597       UpdateTargetList();
    598       OnModelsChanged(this, EventArgs.Empty);
    599     }
    600 
    601     private void ModelCollection_OnItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRegressionModel> e) {
    602       if (e.Items == null) return;
    603       UpdateTargetList();
    604       OnModelsChanged(this, EventArgs.Empty);
    605     }
    606 
    607     private void ControllableParameters_OnItemsChanged(object o, CollectionItemsChangedEventArgs<IndexedItem<StringValue>> e) {
    608       UpdateEncoding();
    609     }
    610 
    611     private void ControllableParameterBounds_ItemChanged(object o, EventArgs e) {
    612       UpdateEncoding();
     254      ModelsParameter.Value.ItemsAdded += ModelCollection_ItemsChanged;
     255      ModelsParameter.Value.ItemsRemoved += ModelCollection_ItemsChanged;
     256      GoalsParameter.Value.CheckedItemsChanged += GoalSeekingUtil.Goals_CheckedItemsChanged;
     257      InputsParameter.Value.CheckedItemsChanged += GoalSeekingUtil.Inputs_CheckedItemsChanged;
     258    }
     259
     260    private void ModelCollection_ItemsChanged(object sender, CollectionItemsChangedEventArgs<IRegressionModel> e) {
     261      if (e.Items == null || !e.Items.Any()) return;
     262      GoalSeekingUtil.UpdateInputs(InputsParameter.Value, Models, InputParameterChanged);
     263      Encoding = GoalSeekingUtil.CreateEncoding(ActiveInputs);
     264      GoalSeekingUtil.UpdateTargets(GoalsParameter.Value, Models, GoalParameterChanged);
     265      GoalSeekingUtil.RaiseEvent(this, ModelsChanged);
     266    }
     267
     268    private void InputParameterChanged(object sender, EventArgs args) {
     269      var inputParameter = (InputParameter)sender;
     270      var inputs = InputsParameter.Value;
     271      if (inputs.ItemChecked(inputParameter) != inputParameter.Active)
     272        inputs.SetItemCheckedState(inputParameter, inputParameter.Active);
     273      Encoding = GoalSeekingUtil.CreateEncoding(ActiveInputs);
     274    }
     275
     276    private void GoalParameterChanged(object sender, EventArgs args) {
     277      var goalParameter = (GoalParameter)sender;
     278      var goals = GoalsParameter.Value;
     279      if (goals.ItemChecked(goalParameter) != goalParameter.Active)
     280        goals.SetItemCheckedState(goalParameter, goalParameter.Active);
    613281    }
    614282    #endregion
    615283
    616284    #region helper methods
    617     private void UpdateControllableParameters() {
    618       if (ProblemData == null) return;
    619       var variablesUsedForPrediction = ModelCollection.Any()
    620         ? ModelCollection.SelectMany(x => x.VariablesUsedForPrediction).Distinct()
    621         : ProblemData.Dataset.DoubleVariables;
    622       SetControllableParameters(variablesUsedForPrediction);
    623     }
    624 
    625     private void UpdateTargetList() {
    626       if (ProblemData == null) return;
    627       if (!Models.Any()) {
    628         TargetGoals = new DoubleMatrix();
    629         maximization = new[] { false };
    630         MaximizationParameter.Value = (BoolArray)new BoolArray(maximization).AsReadOnly();
    631         TargetList = new CheckedItemList<StringValue>();
    632         return;
    633       }
    634 
    635       var targetNames = Models.Select(x => x.TargetVariable).Distinct().ToList();
    636       var oldTargetGoals = (DoubleMatrix)TargetGoals.Clone();
    637       var oldRowIndices = oldTargetGoals.RowNames.Select((x, i) => new { x, i }).ToDictionary(x => x.x, x => x.i);
    638       TargetGoals = new DoubleMatrix(targetNames.Count, 4);
    639       TargetGoals.RowNames = targetNames;
    640       TargetGoals.ColumnNames = new[] { "Goal", "Weight", "Variance", "Step size" };
    641 
    642       TargetList = new CheckedItemList<StringValue>();
    643       for (int i = 0; i < targetNames.Count; ++i) {
    644         TargetList.Add(new StringValue(targetNames[i]), true);
    645         int rowIndex;
    646         if (oldRowIndices.TryGetValue(targetNames[i], out rowIndex)) {
    647           for (int j = 0; j < TargetGoals.Columns; ++j)
    648             TargetGoals[i, j] = oldTargetGoals[rowIndex, j];
    649         } else {
    650           TargetGoals[i, 0] = ProblemData.Dataset.GetDoubleValue(targetNames[i], Row);
    651           TargetGoals[i, 1] = 1.0;
    652           TargetGoals[i, 2] = ProblemData.Dataset.GetReadOnlyDoubleValues(targetNames[i]).Variance();
    653           TargetGoals[i, 3] = 1e-6;
    654         }
    655       }
    656       maximization = new bool[targetNames.Count];
    657       MaximizationParameter.Value = (BoolArray)new BoolArray(maximization).AsReadOnly();
    658     }
    659 
    660     private void UpdateEncoding() {
    661       var activeParameters = ActiveParameters.ToList();
    662       if (Encoding == null)
    663         Encoding = new RealVectorEncoding(activeParameters.Count);
    664       else
    665         Encoding.Length = activeParameters.Count;
    666 
    667       Encoding.Bounds = new DoubleMatrix(activeParameters.Count, 2); // only two columns: min and max
    668       Encoding.Bounds.RowNames = activeParameters;
    669       Encoding.Bounds.ColumnNames = new[] { "Min.", "Max." };
    670 
    671       int i = 0;
    672       foreach (var item in ControllableParameters.CheckedItems) {
    673         var index = item.Index;
    674         Encoding.Bounds[i, 0] = ControllableParameterBounds[index, 0];
    675         Encoding.Bounds[i, 1] = ControllableParameterBounds[index, 1];
    676         ++i;
    677       }
    678     }
    679 
    680     private bool IsValidTarget(string target) {
    681       return TargetList.Any(x => x.Value == target);
     285    // method which throws an exception that can be caught in the event handler if the check fails
     286    private void CheckIfDatasetContainsTarget(string target) {
     287      if (dataset.DoubleVariables.All(x => x != target))
     288        throw new ArgumentException(string.Format("Model target \"{0}\" does not exist in the dataset.", target));
    682289    }
    683290    private static double RoundToNearestStepMultiple(double value, double step) {
     
    685292    }
    686293    private IEnumerable<IRegressionModel> GetModels(string target) {
    687       return ModelCollection.Where(x => x.TargetVariable == target);
     294      return Models.Where(x => x.TargetVariable == target);
    688295    }
    689296    private class DoubleEqualityComparer : IEqualityComparer<double> {
  • branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/Properties/AssemblyInfo.cs

    r14324 r14333  
    5454// [assembly: AssemblyVersion("1.0.*")]
    5555[assembly: AssemblyVersion("3.3.0.0")]
    56 [assembly: AssemblyFileVersion("3.3.11.14321")]
     56[assembly: AssemblyFileVersion("3.3.11.14325")]
  • branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/SingleObjectiveGoalSeekingProblem.cs

    r14324 r14333  
    2323using System.Collections.Generic;
    2424using System.Linq;
    25 using System.Windows.Forms;
    2625using HeuristicLab.Collections;
    2726using HeuristicLab.Common;
    2827using HeuristicLab.Core;
    29 using HeuristicLab.Data;
    3028using HeuristicLab.Encodings.RealVectorEncoding;
    3129using HeuristicLab.Optimization;
     
    4139    #region parameter names
    4240    private const string ModifiableDatasetParameterName = "Dataset";
    43     private const string ProblemDataParameterName = "ProblemData";
    44     private const string ControllableParametersParameterName = "ControllableParameters";
    45     private const string ControllableParameterBoundsParameterName = "ControllableParameterBounds";
    46     private const string TargetGoalsParameterName = "TargetGoals";
    47     private const string TargetsParameterName = "Targets";
    48     private const string ModelCollectionParameterName = "ModelCollection";
    49     private const string RowParameterName = "Row";
    50     // these parameters are used by the pareto folding analyzer
    51     private const string AllowedRangesParameterName = "AllowedRanges";
    52     private const string QualitySumCutoffParameterName = "QualitySumCutoff";
     41    private const string InputsParameterName = "Inputs";
     42    private const string GoalsParameterName = "Goals";
     43    private const string ModelsParameterName = "Models";
    5344    #endregion
    5445
    5546    #region parameters
    56     public IValueParameter<RealVector> AllowedRangesParameter {
    57       get { return (IValueParameter<RealVector>)Parameters[AllowedRangesParameterName]; }
    58     }
    59     public IFixedValueParameter<DoubleValue> QualitySumCutoffParameter {
    60       get { return (IFixedValueParameter<DoubleValue>)Parameters[QualitySumCutoffParameterName]; }
    61     }
    62     public IValueParameter<IRegressionProblemData> ProblemDataParameter {
    63       get { return (IValueParameter<IRegressionProblemData>)Parameters[ProblemDataParameterName]; }
    64     }
    65     public IValueParameter<CheckedItemList<StringValue>> ControllableParametersParameter {
    66       get { return (IValueParameter<CheckedItemList<StringValue>>)Parameters[ControllableParametersParameterName]; }
    67     }
    68     public IValueParameter<DoubleMatrix> ControllableParameterBoundsParameter {
    69       get { return (IValueParameter<DoubleMatrix>)Parameters[ControllableParameterBoundsParameterName]; }
    70     }
    71     public IFixedValueParameter<ItemCollection<IRegressionModel>> ModelCollectionParameter {
    72       get { return (IFixedValueParameter<ItemCollection<IRegressionModel>>)Parameters[ModelCollectionParameterName]; }
    73     }
    74     public IValueParameter<CheckedItemList<StringValue>> TargetsParameter {
    75       get { return (IValueParameter<CheckedItemList<StringValue>>)Parameters[TargetsParameterName]; }
    76     }
    77     public IValueParameter<DoubleMatrix> TargetGoalsParameter {
    78       get { return (IValueParameter<DoubleMatrix>)Parameters[TargetGoalsParameterName]; }
    79     }
    80     public IFixedValueParameter<IntValue> RowParameter {
    81       get { return (IFixedValueParameter<IntValue>)Parameters[RowParameterName]; }
    82     }
    83     #endregion
    84 
    85     #region parameter properties
    86     private IItemCollection<IRegressionModel> ModelCollection {
    87       get { return ModelCollectionParameter.Value; }
    88     }
    89     public DoubleMatrix TargetGoals {
    90       get { return TargetGoalsParameter.Value; }
    91       set { TargetGoalsParameter.Value = value; }
    92     }
    93     #endregion
    94 
    95     #region IProcessParameterOptimizationProblem properties
    96     [Storable]
    97     private IRegressionProblemData problemData;
    98     public IRegressionProblemData ProblemData {
    99       get { return problemData; }
    100       set {
    101         if (value == null || value == problemData) return;
    102         var variables = value.Dataset.DoubleVariables.ToList();
    103         if (Models.Any()) {
    104           var targets = Models.Select(x => x.TargetVariable);
    105           var hashset = new HashSet<string>(variables);
    106           foreach (var target in targets) {
    107             if (!hashset.Contains(target)) {
    108               throw new ArgumentException(string.Format("Incompatible problem data. Target \"{0}\" is missing.", target));
    109             }
    110           }
    111         }
    112         problemData = value;
    113         dataset = new ModifiableDataset(variables, variables.Select(x => new List<double> { ProblemData.Dataset.GetDoubleValue(x, Row) }));
    114         ProblemDataParameter.Value = ProblemData;
    115         UpdateControllableParameters();
    116         UpdateTargetList();
    117       }
    118     }
    119 
    120     public int Row {
    121       get { return RowParameter.Value.Value; }
    122       set { RowParameter.Value.Value = value; }
    123     }
    124 
     47    public IValueParameter<CheckedItemList<InputParameter>> InputsParameter {
     48      get { return (IValueParameter<CheckedItemList<InputParameter>>)Parameters[InputsParameterName]; }
     49    }
     50    public IValueParameter<CheckedItemList<GoalParameter>> GoalsParameter {
     51      get { return (IValueParameter<CheckedItemList<GoalParameter>>)Parameters[GoalsParameterName]; }
     52    }
     53    public IFixedValueParameter<ItemCollection<IRegressionModel>> ModelsParameter {
     54      get { return (IFixedValueParameter<ItemCollection<IRegressionModel>>)Parameters[ModelsParameterName]; }
     55    }
     56    #endregion
     57
     58    #region IGoalSeekingProblem implementation
    12559    public IEnumerable<IRegressionModel> Models {
    126       get { return ModelCollectionParameter.Value; }
    127     }
    128 
    129     #region targets
    130     public ICheckedItemList<StringValue> TargetList {
    131       get { return TargetsParameter.Value; }
    132       set { TargetsParameter.Value = (CheckedItemList<StringValue>)value; }
    133     }
    134     private IEnumerable<string> ActiveTargets {
    135       get { return TargetList.CheckedItems.Select(x => x.Value.Value); }
    136     }
    137     #endregion
    138 
    139     #region parameters
    140     private IEnumerable<string> ActiveParameters {
    141       get { return ControllableParameters.CheckedItems.Select(x => x.Value.Value); }
    142     }
    143     public ICheckedItemList<StringValue> ControllableParameters {
    144       get { return ControllableParametersParameter.Value; }
    145       set { ControllableParametersParameter.Value = (CheckedItemList<StringValue>)value; }
    146     }
    147     public DoubleMatrix ControllableParameterBounds {
    148       get { return ControllableParameterBoundsParameter.Value; }
    149       set { ControllableParameterBoundsParameter.Value = value; }
    150     }
    151     #endregion
    152     #endregion
    153 
    154     #region IProcessParameterOptimizationProblem methods
    155     #region solutions
     60      get { return ModelsParameter.Value; }
     61    }
     62
     63    public IEnumerable<GoalParameter> Goals {
     64      get { return GoalsParameter.Value; }
     65    }
     66
     67    public IEnumerable<InputParameter> Inputs {
     68      get { return InputsParameter.Value; }
     69    }
     70
     71    public void AddModel(IRegressionModel model) {
     72      var models = ModelsParameter.Value;
     73      models.Add(model);
     74      GoalSeekingUtil.RaiseEvent(this, ModelsChanged);
     75    }
     76
     77    public void RemoveModel(IRegressionModel model) {
     78      var models = ModelsParameter.Value;
     79      models.Remove(model);
     80      GoalSeekingUtil.RaiseEvent(this, ModelsChanged);
     81    }
     82
     83    public void Configure(IRegressionProblemData problemData, int row) {
     84      GoalSeekingUtil.Configure(Goals, Inputs, problemData, row);
     85    }
     86
    15687    public IEnumerable<double> GetEstimatedGoalValues(IEnumerable<double> parameterValues, bool round = false) {
    15788      var ds = (ModifiableDataset)dataset.Clone();
    158       foreach (var parameter in ActiveParameters.Zip(parameterValues, (p, v) => new { Name = p, Value = v })) {
     89      foreach (var parameter in ActiveInputs.Zip(parameterValues, (p, v) => new { Name = p.Name, Value = v })) {
    15990        ds.SetVariableValue(parameter.Value, parameter.Name, 0);
    16091      }
    16192      var rows = new[] { 0 }; // actually just one row
    162 
    16393      var estimatedValues =
    164         round ? ActiveTargets.Select(t => RoundToNearestStepMultiple(GetModels(t).Average(m => m.GetEstimatedValues(ds, rows).Single()), GetTargetStepSize(t)))
    165               : ActiveTargets.Select(t => GetModels(t).Average(m => m.GetEstimatedValues(ds, rows).Single()));
    166 
     94        round ? ActiveGoals.Select(t => RoundToNearestStepMultiple(GetModels(t.Name).Average(m => m.GetEstimatedValues(ds, rows).Single()), t.Step))
     95              : ActiveGoals.Select(t => GetModels(t.Name).Average(m => m.GetEstimatedValues(ds, rows).Single()));
    16796      return estimatedValues;
    16897    }
    16998
    170     public void AddModel(IRegressionModel model) {
    171       var target = model.TargetVariable;
    172       CheckIfDatasetContainsTarget(target);
    173       ModelCollection.Add(model);
    174       OnModelsChanged(this, EventArgs.Empty);
    175     }
    176 
     99    public event EventHandler ModelsChanged;
     100    public event EventHandler TargetsChanged;
     101    public event EventHandler ParametersChanged;
     102    #endregion
     103
     104    private IEnumerable<GoalParameter> ActiveGoals {
     105      get { return Goals.Where(x => x.Active); }
     106    }
     107    private IEnumerable<InputParameter> ActiveInputs {
     108      get { return Inputs.Where(x => x.Active); }
     109    }
     110
     111    [Storable]
     112    private ModifiableDataset dataset; // modifiable dataset
     113
     114    public override bool Maximization {
     115      get { return false; }
     116    }
     117
     118    #region constructors
     119    [StorableConstructor]
     120    private SingleObjectiveGoalSeekingProblem(bool deserializing) : base(deserializing) { }
     121
     122    private SingleObjectiveGoalSeekingProblem(SingleObjectiveGoalSeekingProblem original, Cloner cloner) : base(original, cloner) {
     123      this.dataset = cloner.Clone(original.dataset);
     124      RegisterEvents();
     125    }
     126
     127    public override IDeepCloneable Clone(Cloner cloner) {
     128      return new SingleObjectiveGoalSeekingProblem(this, cloner);
     129    }
     130
     131    [StorableHook(HookType.AfterDeserialization)]
     132    private void AfterDeserialization() {
     133      RegisterEvents();
     134    }
     135
     136    public SingleObjectiveGoalSeekingProblem() {
     137      dataset = new ModifiableDataset();
     138      Parameters.Add(new ValueParameter<IDataset>(ModifiableDatasetParameterName, dataset) { Hidden = true });
     139      Parameters.Add(new ValueParameter<CheckedItemList<InputParameter>>(InputsParameterName));
     140      Parameters.Add(new ValueParameter<CheckedItemList<GoalParameter>>(GoalsParameterName));
     141      Parameters.Add(new FixedValueParameter<ItemCollection<IRegressionModel>>(ModelsParameterName, new ItemCollection<IRegressionModel>()));
     142      EncodingParameter.Hidden = true;
     143      EvaluatorParameter.Hidden = true;
     144      SolutionCreatorParameter.Hidden = true;
     145      GoalSeekingUtil.UpdateInputs(InputsParameter.Value, Models, InputParameterChanged);
     146      Encoding = GoalSeekingUtil.CreateEncoding(ActiveInputs);
     147      GoalSeekingUtil.UpdateTargets(GoalsParameter.Value, Models, GoalParameterChanged);
     148      RegisterEvents();
     149    }
     150    #endregion
     151
     152    public override double Evaluate(Individual individual, IRandom random) {
     153      var vector = individual.RealVector();
     154      vector.ElementNames = ActiveInputs.Select(x => x.Name);
     155      int i = 0;
     156      // round vector according to parameter step sizes
     157      foreach (var parameter in ActiveInputs) {
     158        vector[i] = RoundToNearestStepMultiple(vector[i], parameter.Step);
     159        ++i;
     160      }
     161      var estimatedValues = GetEstimatedGoalValues(vector, round: true);
     162      var quality = ActiveGoals.Zip(estimatedValues, (t, v) => new { Target = t, EstimatedValue = v })
     163                               .Average(x => x.Target.Weight * Math.Pow(x.EstimatedValue - x.Target.Goal, 2) / x.Target.Variance);
     164      return quality;
     165    }
     166    #region event handlers
     167
     168    private void RegisterEvents() {
     169      ModelsParameter.Value.ItemsAdded += ModelCollection_ItemsChanged;
     170      ModelsParameter.Value.ItemsRemoved += ModelCollection_ItemsChanged;
     171      GoalsParameter.Value.CheckedItemsChanged += GoalSeekingUtil.Goals_CheckedItemsChanged;
     172      InputsParameter.Value.CheckedItemsChanged += GoalSeekingUtil.Inputs_CheckedItemsChanged;
     173    }
     174
     175    private void ModelCollection_ItemsChanged(object sender, CollectionItemsChangedEventArgs<IRegressionModel> e) {
     176      if (e.Items == null || !e.Items.Any()) return;
     177      GoalSeekingUtil.UpdateInputs(InputsParameter.Value, Models, InputParameterChanged);
     178      Encoding = GoalSeekingUtil.CreateEncoding(ActiveInputs);
     179      GoalSeekingUtil.UpdateTargets(GoalsParameter.Value, Models, GoalParameterChanged);
     180      GoalSeekingUtil.RaiseEvent(this, ModelsChanged);
     181    }
     182
     183    private void InputParameterChanged(object sender, EventArgs args) {
     184      var inputParameter = (InputParameter)sender;
     185      var inputs = InputsParameter.Value;
     186      if (inputs.ItemChecked(inputParameter) != inputParameter.Active)
     187        inputs.SetItemCheckedState(inputParameter, inputParameter.Active);
     188      Encoding = GoalSeekingUtil.CreateEncoding(ActiveInputs);
     189    }
     190
     191    private void GoalParameterChanged(object sender, EventArgs args) {
     192      var goalParameter = (GoalParameter)sender;
     193      var goals = GoalsParameter.Value;
     194      if (goals.ItemChecked(goalParameter) != goalParameter.Active)
     195        goals.SetItemCheckedState(goalParameter, goalParameter.Active);
     196    }
     197    #endregion
     198
     199    #region helper methods
    177200    // method which throws an exception that can be caught in the event handler if the check fails
    178201    private void CheckIfDatasetContainsTarget(string target) {
     
    181204    }
    182205
    183     public void RemoveModel(IRegressionModel model) {
    184       ModelCollection.Remove(model);
    185       OnModelsChanged(this, EventArgs.Empty);
    186     }
    187 
    188     public event EventHandler ModelsChanged;
    189     private void OnModelsChanged(object sender, EventArgs args) {
    190       var changed = ModelsChanged;
    191       if (changed == null) return;
    192       changed(sender, args);
    193     }
    194     #endregion
    195 
    196     #region targets
    197     public bool GetTargetActive(string target) {
    198       var item = TargetList.SingleOrDefault(x => x.Value == target);
    199       if (item == null)
    200         throw new ArgumentException(string.Format("SetTargetActive: Invalid target name {0}", target));
    201       return TargetList.ItemChecked(item);
    202     }
    203 
    204     public void SetTargetActive(string target, bool active) {
    205       var item = TargetList.SingleOrDefault(x => x.Value == target);
    206       if (item == null)
    207         throw new ArgumentException(string.Format("SetTargetActive: Invalid target name {0}", target));
    208       TargetList.SetItemCheckedState(item, active);
    209       OnTargetsChanged(this, EventArgs.Empty);
    210     }
    211 
    212     public double GetTargetGoal(string target) {
    213       if (!IsValidTarget(target))
    214         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
    215       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
    216       return TargetGoals[i, 0];
    217     }
    218 
    219     public void SetTargetGoal(string target, double goal) {
    220       if (!IsValidTarget(target))
    221         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
    222       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
    223       TargetGoals[i, 0] = goal;
    224       OnTargetsChanged(this, EventArgs.Empty);
    225     }
    226 
    227     public double GetTargetWeight(string target) {
    228       if (!IsValidTarget(target))
    229         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
    230       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
    231       return TargetGoals[i, 1];
    232     }
    233 
    234     public void SetTargetWeight(string target, double weight) {
    235       if (!IsValidTarget(target))
    236         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
    237       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
    238       TargetGoals[i, 1] = weight;
    239       OnTargetsChanged(this, EventArgs.Empty);
    240     }
    241 
    242     public double GetTargetVariance(string target) {
    243       if (!IsValidTarget(target))
    244         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
    245       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
    246       return TargetGoals[i, 2];
    247     }
    248 
    249     public void SetTargetVariance(string target, double variance) {
    250       if (!IsValidTarget(target))
    251         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
    252       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
    253       TargetGoals[i, 2] = variance;
    254       OnTargetsChanged(this, EventArgs.Empty);
    255     }
    256 
    257     public double GetTargetStepSize(string target) {
    258       if (!IsValidTarget(target))
    259         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
    260       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
    261       return TargetGoals[i, 3];
    262     }
    263 
    264     public void SetTargetStepSize(string target, double stepSize) {
    265       if (!IsValidTarget(target))
    266         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
    267       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
    268       TargetGoals[i, 3] = stepSize;
    269       OnTargetsChanged(this, EventArgs.Empty);
    270     }
    271 
    272     public event EventHandler TargetsChanged;
    273     private void OnTargetsChanged(object sender, EventArgs args) {
    274       var changed = TargetsChanged;
    275       if (changed == null) return;
    276       changed(sender, args);
    277     }
    278     #endregion // targets
    279 
    280     #region process parameters
    281     /// <summary>
    282     /// Returns the parameter bounds (min and max) and the step size for the specified parameter
    283     /// </summary>
    284     /// <param name="parameterName"></param>
    285     /// <returns>A double array containing the values (min, max, step) in this order</returns>
    286     public double[] GetParameterBounds(string parameterName) {
    287       var index = ControllableParameters.TakeWhile(x => x.Value != parameterName).Count();
    288       if (index < ControllableParameters.Count) {
    289         var min = ControllableParameterBounds[index, 0];
    290         var max = ControllableParameterBounds[index, 1];
    291         var step = ControllableParameterBounds[index, 2];
    292         return new[] { min, max, step };
    293       }
    294       throw new ArgumentException(string.Format("GetParameterBounds: Unknown parameter {0}.", parameterName));
    295     }
    296 
    297     public void SetParameterBounds(string parameterName, double min, double max, double step) {
    298       int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameterName).Count();
    299       if (i < ControllableParameterBounds.Rows) {
    300         ControllableParameterBounds[i, 0] = min;
    301         ControllableParameterBounds[i, 1] = max;
    302         ControllableParameterBounds[i, 2] = step;
    303         UpdateEncoding();
    304         OnParametersChanged(this, EventArgs.Empty);
    305       } else {
    306         throw new ArgumentException(string.Format("SetParameterBounds: Invalid parameter name {0}", parameterName));
    307       }
    308     }
    309 
    310     public double GetParameterStepSize(string parameter) {
    311       int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameter).Count();
    312       if (i < ControllableParameterBounds.Rows)
    313         return ControllableParameterBounds[i, 2];
    314       throw new ArgumentException(string.Format("GetParameterStepSize: Invalid parameter name {0}", parameter));
    315     }
    316 
    317     public void SetParameterStepSize(string parameter, double stepSize) {
    318       int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameter).Count();
    319       if (i < ControllableParameterBounds.Rows) {
    320         ControllableParameterBounds[i, 2] = stepSize;
    321         OnParametersChanged(this, EventArgs.Empty);
    322         return;
    323       }
    324       throw new ArgumentException(string.Format("SetParameterStepSize: Invalid parameter name {0}", parameter));
    325     }
    326 
    327     public bool GetParameterActive(string parameter) {
    328       var item = ControllableParameters.SingleOrDefault(x => x.Value == parameter);
    329       if (item == null)
    330         throw new ArgumentException(string.Format("GetParameterActive: Invalid target name {0}", parameter));
    331       return ControllableParameters.ItemChecked(item);
    332     }
    333 
    334     public void SetParameterActive(string parameter, bool active) {
    335       var item = ControllableParameters.SingleOrDefault(x => x.Value == parameter);
    336       if (item == null)
    337         throw new ArgumentException(string.Format("SetParameterActive: Invalid target name {0}", parameter));
    338       ControllableParameters.SetItemCheckedState(item, active);
    339       OnParametersChanged(this, EventArgs.Empty);
    340     }
    341 
    342     public void SetControllableParameters(IEnumerable<string> parameterNames) {
    343       ControllableParameters = new CheckedItemList<StringValue>();
    344       foreach (var v in parameterNames) {
    345         ControllableParameters.Add(new StringValue(v), false);
    346       }
    347       ControllableParameters.CheckedItemsChanged += ControllableParameters_OnItemsChanged;
    348       ControllableParameterBounds = new DoubleMatrix(ControllableParameters.Count, 3);
    349       ControllableParameterBounds.RowNames = GetControllableParameters();
    350       ControllableParameterBounds.ColumnNames = new[] { "Min", "Max", "Step" };
    351 
    352       for (int i = 0; i < ControllableParameters.Count; ++i) {
    353         var itemName = ControllableParameters[i].Value;
    354         var values = ProblemData.Dataset.GetReadOnlyDoubleValues(itemName).Where(x => !double.IsNaN(x) && !double.IsInfinity(x)).ToList();
    355         if (!values.Any()) continue;
    356 
    357         // add a 20% margin to allow the optimization algorithm more freedom of exploration
    358         ControllableParameterBounds[i, 0] = 0.8 * values.Min(); // min
    359         ControllableParameterBounds[i, 1] = 1.2 * values.Max(); // max
    360         ControllableParameterBounds[i, 2] = 1e-6;               // step
    361       }
    362       OnParametersChanged(this, EventArgs.Empty);
    363     }
    364 
    365     public IEnumerable<string> GetControllableParameters() {
    366       return ControllableParameters.Select(x => x.Value);
    367     }
    368 
    369     public event EventHandler ParametersChanged;
    370     private void OnParametersChanged(object sender, EventArgs args) {
    371       var changed = ParametersChanged;
    372       if (changed == null) return;
    373       changed(sender, args);
    374     }
    375     #endregion // process parameters
    376     #endregion // IGoalSeekingProblem methods
    377 
    378     #region data members
    379     [Storable]
    380     private ModifiableDataset dataset; // modifiable dataset
    381 
    382     public override bool Maximization {
    383       get { return false; }
    384     }
    385     #endregion
    386 
    387     #region constructors
    388     [StorableConstructor]
    389     private SingleObjectiveGoalSeekingProblem(bool deserializing) : base(deserializing) { }
    390 
    391     private SingleObjectiveGoalSeekingProblem(SingleObjectiveGoalSeekingProblem original, Cloner cloner) : base(original, cloner) {
    392       this.dataset = cloner.Clone(original.dataset);
    393       this.problemData = cloner.Clone(original.problemData);
    394 
    395       RegisterEvents();
    396     }
    397 
    398     public override IDeepCloneable Clone(Cloner cloner) {
    399       return new SingleObjectiveGoalSeekingProblem(this, cloner);
    400     }
    401 
    402     [StorableHook(HookType.AfterDeserialization)]
    403     private void AfterDeserialization() {
    404       // backwards-compatibility
    405       if (Parameters.ContainsKey("Models")) {
    406         var solutions = ((IFixedValueParameter<ItemCollection<IRegressionSolution>>)Parameters["Models"]).Value;
    407         var models = new ItemCollection<IRegressionModel>();
    408         foreach (var solution in solutions) {
    409           var model = solution.Model;
    410           model.TargetVariable = solution.ProblemData.TargetVariable;
    411           models.Add(model);
    412         }
    413         if (Parameters.ContainsKey(ModelCollectionParameterName))
    414           Parameters.Remove(ModelCollectionParameterName);
    415         Parameters.Add(new FixedValueParameter<ItemCollection<IRegressionModel>>(ModelCollectionParameterName, models));
    416       }
    417 
    418       RegisterEvents();
    419     }
    420 
    421     public SingleObjectiveGoalSeekingProblem() {
    422       Parameters.Add(new ValueParameter<IRegressionProblemData>(ProblemDataParameterName, new RegressionProblemData()));
    423       Parameters.Add(new ValueParameter<IDataset>(ModifiableDatasetParameterName, dataset) { Hidden = true });
    424       Parameters.Add(new ValueParameter<CheckedItemList<StringValue>>(ControllableParametersParameterName));
    425       Parameters.Add(new ValueParameter<CheckedItemList<StringValue>>(TargetsParameterName));
    426       Parameters.Add(new ValueParameter<DoubleMatrix>(ControllableParameterBoundsParameterName));
    427       Parameters.Add(new FixedValueParameter<ItemCollection<IRegressionModel>>(ModelCollectionParameterName, new ItemCollection<IRegressionModel>()));
    428       Parameters.Add(new ValueParameter<DoubleMatrix>(TargetGoalsParameterName)); // model target weights
    429       Parameters.Add(new FixedValueParameter<IntValue>(RowParameterName));
    430 
    431       // when the problem is created, the problem data parameter will be set to a default value
    432       // set the internal property to the same value
    433       ProblemData = ProblemDataParameter.Value;
    434 
    435       UpdateControllableParameters();
    436       UpdateTargetList();
    437       RegisterEvents();
    438     }
    439     #endregion
    440 
    441     public override double Evaluate(Individual individual, IRandom random) {
    442       var vector = individual.RealVector();
    443       vector.ElementNames = ActiveParameters;
    444       int i = 0;
    445       // round vector according to parameter step sizes
    446       foreach (var parameter in ControllableParameters.CheckedItems) {
    447         var step = ControllableParameterBounds[parameter.Index, 2];
    448         vector[i] = RoundToNearestStepMultiple(vector[i], step);
    449         ++i;
    450       }
    451       var estimatedValues = GetEstimatedGoalValues(vector, round: true);
    452       var quality = TargetList.CheckedItems.Zip(estimatedValues, (t, v) => new { Name = t.Value.Value, Index = t.Index, EstimatedValue = v })
    453                                 .Average(target => {
    454                                   var goal = TargetGoals[target.Index, 0];
    455                                   var weight = TargetGoals[target.Index, 1];
    456                                   var variance = TargetGoals[target.Index, 2];
    457                                   return weight * Math.Pow(target.EstimatedValue - goal, 2) / variance;
    458                                 });
    459       return quality;
    460     }
    461 
    462     #region event handlers
    463     private void RegisterEvents() {
    464       ProblemDataParameter.ValueChanged += OnProblemDataChanged;
    465       ModelCollectionParameter.Value.ItemsAdded += ModelCollection_OnItemsAdded;
    466       ModelCollectionParameter.Value.ItemsRemoved += ModelCollection_OnItemsRemoved;
    467       RowParameter.Value.ValueChanged += OnRowChanged;
    468       ControllableParameters.CheckedItemsChanged += ControllableParameters_OnItemsChanged;
    469       ControllableParameterBounds.ItemChanged += ControllableParameterBounds_ItemChanged;
    470     }
    471 
    472     private void OnRowChanged(object o, EventArgs e) {
    473       // set variables in the modifiable dataset according to the new row
    474       foreach (var v in dataset.DoubleVariables)
    475         dataset.SetVariableValue(ProblemData.Dataset.GetDoubleValue(v, Row), v, 0);
    476       // set the correct targets
    477       UpdateTargetList();
    478     }
    479 
    480     private void OnProblemDataChanged(object o, EventArgs e) {
    481       try {
    482         ProblemData = ProblemDataParameter.Value;
    483       }
    484       catch (ArgumentException exception) {
    485         MessageBox.Show(exception.Message, "Update Problem Data", MessageBoxButtons.OK, MessageBoxIcon.Error);
    486         ProblemDataParameter.Value = problemData;
    487       }
    488     }
    489 
    490     private void ModelCollection_OnItemsAdded(object sender, CollectionItemsChangedEventArgs<IRegressionModel> e) {
    491       if (e.Items == null) return;
    492 
    493       var collection = (IObservableCollection<IRegressionModel>)sender;
    494       var newItems = e.Items.ToList();
    495 
    496       foreach (var model in e.Items) {
    497         try {
    498           CheckIfDatasetContainsTarget(model.TargetVariable);
    499         }
    500         catch (ArgumentException exception) {
    501           MessageBox.Show(exception.Message, "Add Model", MessageBoxButtons.OK, MessageBoxIcon.Error);
    502           newItems.Remove(model);
    503           collection.Remove(model);
    504         }
    505       }
    506       UpdateTargetList();
    507       OnModelsChanged(this, EventArgs.Empty);
    508     }
    509 
    510     private void ModelCollection_OnItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRegressionModel> e) {
    511       if (e.Items == null) return;
    512       UpdateTargetList();
    513       OnModelsChanged(this, EventArgs.Empty);
    514     }
    515 
    516     private void ControllableParameters_OnItemsChanged(object o, CollectionItemsChangedEventArgs<IndexedItem<StringValue>> e) {
    517       UpdateEncoding();
    518     }
    519 
    520     private void ControllableParameterBounds_ItemChanged(object o, EventArgs e) {
    521       UpdateEncoding();
    522     }
    523     #endregion
    524 
    525     #region helper methods
    526     private void UpdateControllableParameters() {
    527       if (ProblemData == null) return;
    528       var variablesUsedForPrediction = ModelCollection.Any()
    529         ? ModelCollection.SelectMany(x => x.VariablesUsedForPrediction).Distinct()
    530         : ProblemData.Dataset.DoubleVariables;
    531       SetControllableParameters(variablesUsedForPrediction);
    532     }
    533 
    534     private void UpdateTargetList() {
    535       if (ProblemData == null) return;
    536       if (!Models.Any()) {
    537         TargetGoals = new DoubleMatrix();
    538         TargetList = new CheckedItemList<StringValue>();
    539         return;
    540       }
    541       var targetNames = Models.Select(x => x.TargetVariable).Distinct().ToList();
    542       var oldTargetGoals = (DoubleMatrix)TargetGoals.Clone();
    543       var oldRowIndices = oldTargetGoals.RowNames.Select((x, i) => new { x, i }).ToDictionary(x => x.x, x => x.i);
    544       TargetGoals = new DoubleMatrix(targetNames.Count, 4);
    545       TargetGoals.RowNames = targetNames;
    546       TargetGoals.ColumnNames = new[] { "Goal", "Weight", "Variance", "Step size" };
    547 
    548       TargetList = new CheckedItemList<StringValue>();
    549       for (int i = 0; i < targetNames.Count; ++i) {
    550         TargetList.Add(new StringValue(targetNames[i]), true);
    551         int rowIndex;
    552         if (oldRowIndices.TryGetValue(targetNames[i], out rowIndex)) {
    553           for (int j = 0; j < TargetGoals.Columns; ++j)
    554             TargetGoals[i, j] = oldTargetGoals[rowIndex, j];
    555         } else {
    556           TargetGoals[i, 0] = ProblemData.Dataset.GetDoubleValue(targetNames[i], Row);
    557           TargetGoals[i, 1] = 1.0;
    558           TargetGoals[i, 2] = ProblemData.Dataset.GetReadOnlyDoubleValues(targetNames[i]).Variance();
    559           TargetGoals[i, 3] = 1e-6;
    560         }
    561       }
    562     }
    563 
    564     private void UpdateEncoding() {
    565       var activeParameters = ActiveParameters.ToList();
    566       if (Encoding == null)
    567         Encoding = new RealVectorEncoding(activeParameters.Count);
    568       else
    569         Encoding.Length = activeParameters.Count;
    570 
    571       Encoding.Bounds = new DoubleMatrix(activeParameters.Count, 2); // only two columns: min and max
    572       Encoding.Bounds.RowNames = activeParameters;
    573       Encoding.Bounds.ColumnNames = new[] { "Min.", "Max." };
    574 
    575       int i = 0;
    576       foreach (var item in ControllableParameters.CheckedItems) {
    577         var index = item.Index;
    578         Encoding.Bounds[i, 0] = ControllableParameterBounds[index, 0];
    579         Encoding.Bounds[i, 1] = ControllableParameterBounds[index, 1];
    580         ++i;
    581       }
    582     }
    583     private bool IsValidTarget(string target) {
    584       return TargetList.Any(x => x.Value == target);
    585     }
     206    private IEnumerable<IRegressionModel> GetModels(string target) {
     207      return Models.Where(x => x.TargetVariable == target);
     208    }
     209
    586210    private static double RoundToNearestStepMultiple(double value, double step) {
    587211      return step * (long)Math.Round(value / step);
    588212    }
    589     private IEnumerable<IRegressionModel> GetModels(string target) {
    590       return ModelCollection.Where(x => x.TargetVariable == target);
    591     }
    592213    #endregion
    593214  }
Note: See TracChangeset for help on using the changeset viewer.