Changeset 6489


Ignore:
Timestamp:
06/27/11 23:56:35 (8 years ago)
Author:
cneumuel
Message:

#1215

  • fixed issue with multiple problems (by introducing valuesReadOnly to IOptimizable)
  • fixed error message when removing last problem instance
  • made quality measure name configurable
Location:
branches/HeuristicLab.MetaOptimization
Files:
1 added
13 edited

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.MetaOptimization/HeuristicLab.MetaOptimization.Test/Program.cs

    r6473 r6489  
    2424using HeuristicLab.Problems.MetaOptimization;
    2525using HeuristicLab.Problems.TestFunctions;
    26 using HeuristicLab.Problems.TravelingSalesman;
    2726using HeuristicLab.Random;
    2827using HeuristicLab.Selection;
     
    4948    //private static double mutationProbability = 0.10;
    5049
    51     private static int metaAlgorithmPopulationSize = 30;
     50    private static int metaAlgorithmPopulationSize = 3;
    5251    private static int metaAlgorithmMaxGenerations = 10;
    5352    private static double metaAlgorithmMutationProbability = 0.10;
    54     private static int metaProblemRepetitions = 3;
    55     private static int baseAlgorithmMaxGenerations = 20;
    56     private static int baseAlgorithmPopulationSize = 100;
     53    private static int metaProblemRepetitions = 2;
     54    private static int baseAlgorithmMaxGenerations = 1;
     55    private static int baseAlgorithmPopulationSize = 5;
    5756
    5857    public override void Run() {
     
    8786
    8887      //TestSymbolicDataAnalysisGrammar(); return;
    89       TestObjectGraphObjectsTraversal(); return;
     88      //TestObjectGraphObjectsTraversal(); return;
    9089      //TestParameterizedItem(); return;
    9190
     
    9392      //var algorithmVc = metaOptimizationProblem.ParameterConfigurationTree;
    9493
    95       var metaOptimizationProblem = new MetaOptimizationProblem();
    96       var algorithmVc = SetupGAAlgorithm(typeof(GeneticAlgorithm), metaOptimizationProblem);
     94      //var metaOptimizationProblem = new MetaOptimizationProblem();
     95      //var algorithmVc = SetupGAAlgorithm(typeof(GeneticAlgorithm), metaOptimizationProblem);
     96
     97      // import classification 4 problems
     98      var metaOptimizationProblem = ((MetaOptimizationProblem)ContentManager.Load("MetaOpt GA,OSGA,Classification (melanoma,respiratory,wisconsin,prostata),MSE-Evaluator_test.hl"));
     99      metaOptimizationProblem.QualityMeasureNameParameter.Value.Value = "Best training solution.Mean squared error (test)";
    97100
    98101      metaOptimizationProblem.Repetitions = new IntValue(metaProblemRepetitions);
    99       //GeneticAlgorithm metaLevelAlgorithm = GetSequentialMetaGA(metaOptimizationProblem);
    100       GeneticAlgorithm metaLevelAlgorithm = GetParallelMetaGA(metaOptimizationProblem);
     102      GeneticAlgorithm metaLevelAlgorithm = GetSequentialMetaGA(metaOptimizationProblem);
     103      //GeneticAlgorithm metaLevelAlgorithm = GetParallelMetaGA(metaOptimizationProblem);
    101104      //GeneticAlgorithm metaLevelAlgorithm = GetHiveParallelMetaGA(metaOptimizationProblem);
    102105      //EvolutionStrategy metaLevelAlgorithm = GetMetaES(metaOptimizationProblem);
     
    105108      //TestConfiguration(algorithmVc, typeof(GeneticAlgorithm), metaOptimizationProblem.Problems.First());
    106109
    107       Console.WriteLine("Press enter to start"); Console.ReadLine();
     110      //Console.WriteLine("Press enter to start"); Console.ReadLine();
    108111      TestOptimization(metaLevelAlgorithm);
    109112
     
    809812
    810813      // tsp
    811       metaOptimizationProblem.ProblemType.Value = typeof(TravelingSalesmanProblem);
     814      //metaOptimizationProblem.ProblemType.Value = typeof(TravelingSalesmanProblem);
    812815
    813816      ParameterConfigurationTree algorithmVc = metaOptimizationProblem.ParameterConfigurationTree;
     
    815818      ((IntValue)algorithmVc.AlgorithmConfiguration.ParameterConfigurations.Single(x => x.Name == "PopulationSize").ActualValue.Value).Value = baseAlgorithmPopulationSize;
    816819
    817       ConfigurePopulationSize(algorithmVc, 10, 100, 1);
    818       ConfigureMutationRate(algorithmVc, 0.0, 1.0, 0.01);
    819       ConfigureMutationOperator(algorithmVc);
    820       ConfigureElites(algorithmVc, 0, 10, 1);
    821       ConfigureSelectionOperator(algorithmVc, true);
     820      //ConfigurePopulationSize(algorithmVc, 10, 100, 1);
     821      //ConfigureMutationRate(algorithmVc, 0.0, 1.0, 0.01);
     822      //ConfigureMutationOperator(algorithmVc);
     823      //ConfigureElites(algorithmVc, 0, 5, 1);
     824      //ConfigureSelectionOperator(algorithmVc, true);
    822825
    823826      //ConfigureSymbolicExpressionGrammar(algorithmVc);
     
    10521055
    10531056        StringBuilder sb1 = new StringBuilder();
    1054         sb1.AppendFormat("Meta.PopulationSize: {0}\n", metaAlgorithmPopulationSize);
    1055         sb1.AppendFormat("Meta.MaxGenerations: {0}\n", metaAlgorithmMaxGenerations);
    1056         sb1.AppendFormat("Meta.Repetitions   : {0}\n", metaProblemRepetitions);
    1057         sb1.AppendFormat("Meta.MutProb       : {0}\n", ((GeneticAlgorithm)metaLevelAlgorithm).MutationProbability.Value);
    1058         sb1.AppendFormat("Meta.Seed          : {0}\n", ((GeneticAlgorithm)metaLevelAlgorithm).Seed.Value);
    1059         sb1.AppendFormat("Base.MaxGenerations: {0}\n", baseAlgorithmMaxGenerations);
     1057        sb1.AppendFormat("Meta-PopulationSize: {0}\n", metaAlgorithmPopulationSize);
     1058        sb1.AppendFormat("Meta-MaxGenerations: {0}\n", metaAlgorithmMaxGenerations);
     1059        sb1.AppendFormat("Meta-Repetitions   : {0}\n", metaProblemRepetitions);
     1060        sb1.AppendFormat("Meta-MutProb       : {0}\n", ((GeneticAlgorithm)metaLevelAlgorithm).MutationProbability.Value);
     1061        sb1.AppendFormat("Meta-Seed          : {0}\n", ((GeneticAlgorithm)metaLevelAlgorithm).Seed.Value);
     1062        sb1.AppendFormat("Base-MaxGenerations: {0}\n", baseAlgorithmMaxGenerations);
    10601063
    10611064        sb1.AppendLine("Problems:");
  • branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization.Views/3.3/HeuristicLab.Problems.MetaOptimization.Views-3.3.csproj

    r5655 r6489  
    153153      <DependentUpon>ItemDictionaryView.cs</DependentUpon>
    154154    </Compile>
     155    <Compile Include="MessageItem.cs" />
    155156    <Compile Include="MetaOptimizationProblemView.cs">
    156157      <SubType>UserControl</SubType>
  • branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization.Views/3.3/OptimizableView.cs

    r5927 r6489  
    7979        } else {
    8080          this.viewHost.ViewsLabelVisible = false;
    81           this.viewHost.Content = Content.ActualValue;
     81          if (Content.ValuesReadOnly) {
     82            this.viewHost.Content = new MessageItem("Cannot modify value directly. Please modify the value in the list of problems.");
     83          } else {
     84            this.viewHost.Content = Content.ActualValue;
     85          }
    8286        }
    8387      }
  • branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/PMOBestSolutionHistoryAnalyzer.cs

    r6197 r6489  
    7575        bestSolutionHistory = results[key].Value as RunCollection;
    7676      }
    77       if (bestSolutionHistory.Count == 0 || best.ParameterInfoString != ((StringValue)bestSolutionHistory.Last().Results["Meta.ParameterInfoString"]).Value) {
     77      if (bestSolutionHistory.Count == 0 || best.ParameterInfoString != ((StringValue)bestSolutionHistory.Last().Results["Meta-ParameterInfoString"]).Value) {
    7878        IRun run = best.ToRun(string.Format("{0}: {1}", currentGeneration, best.ParameterInfoString), false);
    79         run.Results.Add("Meta.Generation", new IntValue(currentGeneration));
    80         run.Results.Add("Meta.ParameterInfoString", new StringValue(best.ParameterInfoString));
     79        run.Results.Add("Meta-Generation", new IntValue(currentGeneration));
     80        run.Results.Add("Meta-ParameterInfoString", new StringValue(best.ParameterInfoString));
    8181        bestSolutionHistory.Add(run);
    8282      }
  • branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Analyzers/SolutionCacheAnalyzer.cs

    r6090 r6489  
    7474          var runCollection = allRuns.Single(x => x.Key.Value == key).Value;
    7575          foreach (var run in solution.Runs) {
    76             if (!((BoolValue)run.Results["Meta.FromCache"]).Value || first) {
    77               run.Results["Meta.FromCache"] = new BoolValue(true);
     76            if (!((BoolValue)run.Results["Meta-FromCache"]).Value || first) {
     77              run.Results["Meta-FromCache"] = new BoolValue(true);
    7878              runCollection.Add(run);
    7979            }
  • branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterCombinationsEnumerator.cs

    r5653 r6489  
    2222      get {
    2323        if (!initialized)
    24           throw new SystemException("Enumeration not started. Call MoveNext!");
     24          throw new InvalidOperationException("Enumeration not started. Call MoveNext!");
    2525        return Current;
    2626      }
  • branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurationTree.cs

    r6421 r6489  
    161161      this.parameterConfigurations.Add(new SingleValuedParameterConfiguration("Algorithm", algproblemitem.AlgorithmParameter));
    162162      this.parameterConfigurations.Add(new SingleValuedParameterConfiguration("Problem", algproblemitem.ProblemParameter));
     163
     164      // problems can be modified in the list of problem instances, so the parameters which are not Optimize=true,
     165      // must not be modifiable in the parameter configuration tree. otherwise the parameter values would be ambiguous
     166      ProblemConfiguration.ValuesReadOnly = true;
    163167    }
    164168    public ParameterConfigurationTree() { }
     
    190194    [StorableHook(HookType.AfterDeserialization)]
    191195    private void AfterDeserialization() {
     196      if(ProblemConfiguration != null) ProblemConfiguration.ValuesReadOnly = true;
    192197    }
    193198    #endregion
  • branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurations/ParameterConfiguration.cs

    r6486 r6489  
    146146    }
    147147
     148    [Storable]
     149    protected bool valuesReadOnly = false;
     150    public virtual bool ValuesReadOnly {
     151      get { return valuesReadOnly; }
     152      set {
     153        if (value != this.valuesReadOnly) {
     154          this.valuesReadOnly = value;
     155          foreach (var vc in this.valueConfigurations) {
     156            vc.ValuesReadOnly = value;
     157          }
     158        }
     159      }
     160    }
    148161
    149162    #region Constructors and Cloning
     
    220233      this.discoverValidValues = original.discoverValidValues;
    221234      this.AutoPopulateValueConfigurations = original.AutoPopulateValueConfigurations;
     235      this.valuesReadOnly = original.valuesReadOnly;
    222236    }
    223237
     
    485499
    486500    public void Parameterize(IValueParameter parameter) {
     501      if (!Optimize && ValuesReadOnly)
     502        return;
     503
    487504      if (Optimize) {
    488505        if (this.ActualValue.Value is IParameterizedItem) {
  • branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ValueConfigurations/ParameterizedValueConfiguration.cs

    r5927 r6489  
    4646      get { return discoverValidValues; }
    4747      set { discoverValidValues = value; }
     48    }
     49
     50    public override bool ValuesReadOnly {
     51      set {
     52        if (value != this.valuesReadOnly) {
     53          this.valuesReadOnly = value;
     54          foreach (var pc in this.parameterConfigurations) {
     55            pc.ValuesReadOnly = value;
     56          }
     57        }
     58      }
    4859    }
    4960
  • branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ValueConfigurations/ValueConfiguration.cs

    r5927 r6489  
    7373    }
    7474
     75    [Storable]
     76    protected bool valuesReadOnly = false;
     77    public virtual bool ValuesReadOnly {
     78      get { return valuesReadOnly; }
     79      set {
     80        if (value != this.valuesReadOnly) {
     81          this.valuesReadOnly = value;
     82        }
     83      }
     84    }
     85
    7586    #region Constructors and Cloning
    7687    public ValueConfiguration(IItem value, Type valueDataType) {
     
    8899      this.optimize = original.optimize;
    89100      this.number = original.number;
     101      this.valuesReadOnly = original.valuesReadOnly;
    90102      RegisterActualValueEvents();
    91103    }
  • branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Evaluators/AlgorithmRunsAnalyzer.cs

    r6473 r6489  
    6969    public IScope CurrentScope {
    7070      get { return CurrentScopeParameter.ActualValue; }
     71    }
     72    public LookupParameter<StringValue> QualityMeasureNameParameter {
     73      get { return (LookupParameter<StringValue>)Parameters[MetaOptimizationProblem.QualityMeasureNameName]; }
    7174    }
    7275    #endregion
     
    9396      Parameters.Add(new LookupParameter<DoubleValue>(MetaOptimizationProblem.StandardDeviationWeightParameterName));
    9497      Parameters.Add(new LookupParameter<DoubleValue>(MetaOptimizationProblem.EvaluatedSolutionsWeightParameterName));
     98      Parameters.Add(new LookupParameter<StringValue>(MetaOptimizationProblem.QualityMeasureNameName));
    9599      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope whose sub-scopes represent the parents."));
    96100    }
     
    104108    private void AfterDeserialization() {
    105109      if (!Parameters.ContainsKey("CurrentScope")) Parameters.Add(new ScopeParameter("CurrentScope", "The current scope whose sub-scopes represent the parents.")); // backwards compatibility
     110      if (!Parameters.ContainsKey(MetaOptimizationProblem.QualityMeasureNameName)) Parameters.Add(new LookupParameter<StringValue>(MetaOptimizationProblem.QualityMeasureNameName)); // backwards compatibility
    106111    }
    107112
     
    118123      double standardDeviationWeight = StandardDeviationWeightParameter.ActualValue.Value;
    119124      double evaluatedSolutionsWeight = EvaluatedSolutionsWeightParameter.ActualValue.Value;
    120       var resultNames = new List<string> { "BestQuality", "Execution Time", "EvaluatedSolutions" };
     125      string qualityMeasureName = QualityMeasureNameParameter.ActualValue.Value;
     126      var resultNames = new List<string> { qualityMeasureName, "Execution Time", "EvaluatedSolutions" };
    121127      int currentGeneration = GenerationsParameter.ActualValue != null ? GenerationsParameter.ActualValue.Value : 0;
    122128      double[] referenceQualityAverages;
     
    146152          MetaOptimizationUtil.ClearResults(run, resultNames);
    147153          MetaOptimizationUtil.ClearParameters(run, parameterNames);
    148           run.Results.Add("Meta.FromCache", new BoolValue(false));
    149           run.Results.Add("Meta.Generation", new IntValue(currentGeneration));
    150           run.Results.Add("Meta.ProblemIndex", new IntValue(problemIndex));
     154          run.Results.Add("Meta-FromCache", new BoolValue(false));
     155          run.Results.Add("Meta-Generation", new IntValue(currentGeneration));
     156          run.Results.Add("Meta-ProblemIndex", new IntValue(problemIndex));
    151157          run.Name = string.Format("{0} Problem {1} Run {2}", parameterConfiguration.ParameterInfoString, problemIndex, repetitionIndex);
    152           qualities[problemIndex][repetitionIndex] = (((DoubleValue)run.Results["BestQuality"]).Value);
     158         
     159          qualities[problemIndex][repetitionIndex] = GetResultValue<DoubleValue>(run.Results, qualityMeasureName).Value;
    153160          executionTimes[problemIndex][repetitionIndex] = (((TimeSpanValue)run.Results["Execution Time"]).Value);
    154161          evaluatedSolutions[problemIndex][repetitionIndex] = (((IntValue)run.Results["EvaluatedSolutions"]).Value);
     
    203210     
    204211      return base.Apply();
     212    }
     213
     214    private T1 GetResultValue<T1>(IDictionary<string, IItem> results, string resultName) {
     215      return (T1)results[resultName];
     216
     217      //string separator = ".";
     218      //string[] tokens = resultName.Split(separator.ToCharArray());
     219
     220      //IDictionary<string, IItem> currentResults = results;
     221      //IItem currentResult = null;
     222      //for (int i = 0; i < tokens.Length; i++) {
     223      //  if(currentResults == null)
     224      //    throw new KeyNotFoundException("Result value " + resultName + " was not found");
     225      //  if (currentResults.ContainsKey(tokens[i])) {
     226      //    currentResult = currentResults[tokens[i]];
     227      //    currentResults = currentResult as IDictionary<string, IItem>;
     228      //  } else {
     229      //    throw new KeyNotFoundException("Result value " + resultName + " was not found");
     230      //  }
     231      //}
     232      //return (T1)currentResult;
    205233    }
    206234
  • branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Interfaces/IOptimizable.cs

    r5653 r6489  
    2626    event EventHandler IsOptimizableChanged;
    2727    event EventHandler OptimizeChanged;
     28
     29    /// <summary>
     30    /// indicates if the actualvalues are modifiable
     31    /// </summary>
     32    bool ValuesReadOnly { get; set; }
    2833  }
    2934}
  • branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/MetaOptimizationProblem.cs

    r6090 r6489  
    4040  public sealed class MetaOptimizationProblem : SingleObjectiveHeuristicOptimizationProblem<IParameterConfigurationEvaluator, IParameterConfigurationCreator>, IStorableContent {
    4141    public string Filename { get; set; }
    42    
     42
    4343    public const string AlgorithmTypeParameterName = "AlgorithmType";
    4444    public const string ProblemTypeParameterName = "ProblemType";
     
    4646    public const string ParameterConfigurationTreeParameterName = "ParameterConfiguration";
    4747    public const string RepetitionsParameterName = "Repetitions";
     48    public const string QualityMeasureNameName = "QualityMeasureName";
    4849
    4950    public const string IntValueManipulatorParameterName = "IntValueManipulator";
     
    6768    }
    6869    public IValueParameter<ParameterConfigurationTree> ParameterConfigurationTreeParameter {
    69       get { return (ValueParameter<ParameterConfigurationTree>)Parameters[ParameterConfigurationTreeParameterName]; }
     70      get { return (OptionalValueParameter<ParameterConfigurationTree>)Parameters[ParameterConfigurationTreeParameterName]; }
    7071    }
    7172    public IValueParameter<IntValue> RepetitionsParameter {
     
    7980    public IValueParameter<IDoubleValueManipulator> DoubleValueManipulatorParameter {
    8081      get { return (ValueParameter<IDoubleValueManipulator>)Parameters[DoubleValueManipulatorParameterName]; }
     82    }
     83    public IValueParameter<StringValue> QualityMeasureNameParameter {
     84      get { return (ValueParameter<StringValue>)Parameters[QualityMeasureNameName]; }
    8185    }
    8286    #endregion
     
    131135      Parameters.Add(new ValueParameter<ConstrainedTypeValue<IProblem>>(ProblemTypeParameterName, "The problem type.", new ConstrainedTypeValue<IProblem>()));
    132136      Parameters.Add(new ValueParameter<ConstrainedItemList<IProblem>>(ProblemsParameterName, "The problems that should be evaluated.", new ConstrainedItemList<IProblem>()));
    133       Parameters.Add(new ValueParameter<ParameterConfigurationTree>(ParameterConfigurationTreeParameterName, "Tree of algorithm parameters that should be optimized."));
     137      Parameters.Add(new OptionalValueParameter<ParameterConfigurationTree>(ParameterConfigurationTreeParameterName, "Tree of algorithm parameters that should be optimized.")); // needs to be optional, when last problem is removed from list, it must be set null
    134138      Parameters.Add(new ValueParameter<IntValue>(RepetitionsParameterName, "The number of evaluations for each problem.", new IntValue(3)));
     139      Parameters.Add(new ValueParameter<StringValue>(QualityMeasureNameName, "The name of the quality result of the base-level algorithm. Subresults can be accessed by dot separator.", new StringValue("BestQuality")));
    135140
    136141      var validIntManipulators = new ItemSet<IIntValueManipulator>(ApplicationManager.Manager.GetInstances<IIntValueManipulator>());
     
    174179    [StorableHook(HookType.AfterDeserialization)]
    175180    private void AfterDeserializationHook() {
     181      if(!Parameters.ContainsKey(QualityMeasureNameName)) Parameters.Add(new ValueParameter<StringValue>(QualityMeasureNameName, "The name of the quality result of the base-level algorithm. Subresults can be accessed by dot separator.", new StringValue("BestQuality"))); // backwards compatibility
    176182      RegisterParameterEvents();
    177183    }
     
    211217      if (RunsAnalyzer != null) {
    212218        RunsAnalyzer.ParameterConfigurationParameter.ActualName = ((RandomParameterConfigurationCreator)SolutionCreator).ParameterConfigurationParameter.ActualName;
    213       } 
     219      }
    214220      if (PMOPopulationDiversityAnalyzer != null) {
    215221        PMOPopulationDiversityAnalyzer.SolutionParameter.ActualName = ((RandomParameterConfigurationCreator)SolutionCreator).ParameterConfigurationParameter.ActualName;
     
    260266      IAlgorithm instance = (IAlgorithm)Activator.CreateInstance(AlgorithmType.Value);
    261267      this.ProblemType.ValidTypes = ApplicationManager.Manager.GetTypes(instance.ProblemType, true).ToList();
    262       this.ProblemType.Value = this.ProblemType.ValidTypes.SingleOrDefault(t => t == typeof(SingleObjectiveTestFunctionProblem)) ?? this.ProblemType.ValidTypes.Where(t => t != typeof(MetaOptimizationProblem)).FirstOrDefault();
    263       // ProblemType_ValueChanged will add one problem and create ParameterConfigurationTree
     268      var newProblemType = this.ProblemType.ValidTypes.SingleOrDefault(t => t == typeof(SingleObjectiveTestFunctionProblem)) ?? this.ProblemType.ValidTypes.Where(t => t != typeof(MetaOptimizationProblem)).FirstOrDefault();
     269      if (this.ProblemType.Value != newProblemType)
     270        this.ProblemType.Value = newProblemType; // ProblemType_ValueChanged will add one problem and create ParameterConfigurationTree
     271      else
     272        ProblemType_ValueChanged(this, EventArgs.Empty); // call explicitly
    264273    }
    265274
     
    274283    }
    275284
    276     private void Problems_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<IndexedItem<IProblem>> e) {
     285    private void Problems_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IProblem>> e) {
    277286      // the first problem in the list is always the instance for the algorithm - this way some basic wiring between problem and algorithm can be sustained
    278287      if (e.Items.Single().Index == 0) {
     
    287296    }
    288297
    289     private void Problems_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<IndexedItem<IProblem>> e) {
     298    private void Problems_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IProblem>> e) {
    290299      if (e.Items.Single().Index == 0) {
    291300        ParameterConfigurationTreeParameter.ActualValue = null;
Note: See TracChangeset for help on using the changeset viewer.