public RunCollectionChartAggregationView() {
   InitializeComponent();
   runMapping = new Dictionary<IRun, IEnumerable<DataRow>>();
   combinedDataTable = new DataTable("Combined DataTable", "A data table containing data rows from multiple runs.");
   viewHost.Content = combinedDataTable;
   suppressUpdates = false;
 }
    public override IOperation Apply() {
      var results = ResultCollectionParameter.ActualValue;

      if (!results.ContainsKey(RegressionSolutionQualitiesResultName)) {
        var newDataTable = new DataTable(RegressionSolutionQualitiesResultName);
        results.Add(new Result(RegressionSolutionQualitiesResultName, "Chart displaying the training and test qualities of the regression solutions.", newDataTable));
      }

      var dataTable = (DataTable)results[RegressionSolutionQualitiesResultName].Value;
      foreach (var result in results.Where(r => r.Value is IRegressionSolution)) {
        var solution = (IRegressionSolution)result.Value;

        var trainingR2 = result.Name + Environment.NewLine + "Training R²";
        if (!dataTable.Rows.ContainsKey(trainingR2))
          dataTable.Rows.Add(new DataRow(trainingR2));

        var testR2 = result.Name + Environment.NewLine + " Test R²";
        if (!dataTable.Rows.ContainsKey(testR2))
          dataTable.Rows.Add(new DataRow(testR2));

        dataTable.Rows[trainingR2].Values.Add(solution.TrainingRSquared);
        dataTable.Rows[testR2].Values.Add(solution.TestRSquared);
      }

      return base.Apply();
    }
    public override IOperation Apply() {
      ItemArray<StringValue> exceptions = ExceptionTreeParameter.ActualValue;
      double count = exceptions.Count();
      ResultCollection results = ResultsParameter.ActualValue;
      DataTable exceptionFrequencies = ExceptionFrequenciesParameter.ActualValue;
      if (exceptionFrequencies == null) {
        exceptionFrequencies = new DataTable("Exception frequencies", "Relative frequency of exception aggregated over the whole population.");
        exceptionFrequencies.VisualProperties.YAxisTitle = "Relative Exception Frequency";

        ExceptionFrequenciesParameter.ActualValue = exceptionFrequencies;
        results.Add(new Result("Exception frequencies", exceptionFrequencies));
      }

      // all rows must have the same number of values so we can just take the first
      int numberOfValues = exceptionFrequencies.Rows.Select(r => r.Values.Count).DefaultIfEmpty().First();

      foreach (var pair in exceptions.GroupBy(x => x.Value).ToDictionary(g => g.Key, g => (double)g.Count() / count)) {
        string key = String.IsNullOrEmpty(pair.Key) ? "No Exception" : pair.Key;
        if (!exceptionFrequencies.Rows.ContainsKey(key)) {
          // initialize a new row for the symbol and pad with zeros
          DataRow row = new DataRow(key, "", Enumerable.Repeat(0.0, numberOfValues));
          row.VisualProperties.StartIndexZero = true;
          exceptionFrequencies.Rows.Add(row);
        }
        exceptionFrequencies.Rows[key].Values.Add(Math.Round(pair.Value, 3));
      }

      // add a zero for each data row that was not modified in the previous loop 
      foreach (var row in exceptionFrequencies.Rows.Where(r => r.Values.Count != numberOfValues + 1))
        row.Values.Add(0.0);
      return base.Apply();
    }
    public override IOperation Apply() {
      ItemArray<ISymbolicExpressionTree> expressions = SymbolicExpressionTreeParameter.ActualValue;
      ResultCollection results = ResultCollection;
      DataTable datatable;
      if (VariableFrequenciesParameter.ActualValue == null) {
        datatable = new DataTable("Variable frequencies", "Relative frequency of variable references aggregated over the whole population.");
        datatable.VisualProperties.XAxisTitle = "Generation";
        datatable.VisualProperties.YAxisTitle = "Relative Variable Frequency";
        VariableFrequenciesParameter.ActualValue = datatable;
        results.Add(new Result("Variable frequencies", "Relative frequency of variable references aggregated over the whole population.", datatable));
        results.Add(new Result("Variable impacts", "The relative variable relevance calculated as the average relative variable frequency over the whole run.", new DoubleMatrix()));
      }

      datatable = VariableFrequenciesParameter.ActualValue;
      // all rows must have the same number of values so we can just take the first
      int numberOfValues = datatable.Rows.Select(r => r.Values.Count).DefaultIfEmpty().First();

      foreach (var pair in SymbolicDataAnalysisVariableFrequencyAnalyzer.CalculateVariableFrequencies(expressions, AggregateLaggedVariables.Value)) {
        if (!datatable.Rows.ContainsKey(pair.Key)) {
          // initialize a new row for the variable and pad with zeros
          DataRow row = new DataRow(pair.Key, "", Enumerable.Repeat(0.0, numberOfValues));
          row.VisualProperties.StartIndexZero = true;
          datatable.Rows.Add(row);
        }
        datatable.Rows[pair.Key].Values.Add(Math.Round(pair.Value, 3));
      }

      // add a zero for each data row that was not modified in the previous loop 
      foreach (var row in datatable.Rows.Where(r => r.Values.Count != numberOfValues + 1))
        row.Values.Add(0.0);

      // update variable impacts matrix
      var orderedImpacts = (from row in datatable.Rows
                            select new { Name = row.Name, Impact = Math.Round(datatable.Rows[row.Name].Values.Average(), 3) })
                           .OrderByDescending(p => p.Impact)
                           .ToList();
      var impacts = new DoubleMatrix();
      var matrix = impacts as IStringConvertibleMatrix;
      matrix.Rows = orderedImpacts.Count;
      matrix.RowNames = orderedImpacts.Select(x => x.Name);
      matrix.Columns = 1;
      matrix.ColumnNames = new string[] { "Relative variable relevance" };
      int i = 0;
      foreach (var p in orderedImpacts) {
        matrix.SetValue(p.Impact.ToString(), i++, 0);
      }

      VariableImpactsParameter.ActualValue = impacts;
      results["Variable impacts"].Value = impacts;
      return base.Apply();
    }
    private static IEnumerable<double> CalcCummulativeAverage(DataTable parent, DataTable other) {
      IEnumerable<double> avg = Enumerable.Repeat(0.0, parent.Rows.First().Values.Count);
      IEnumerable<double> real = Enumerable.Repeat(0.0, parent.Rows.First().Values.Count);

      foreach (var rowName in parent.Rows.Select(x => x.Name)) {
        var symboleParentRow = parent.Rows[rowName];
        var symboleOtherRow = other.Rows[rowName];

        avg = avg.Zip(symboleParentRow.Values, (x, y) => x + y);
        real = real.Zip(symboleParentRow.Values.Zip(symboleOtherRow.Values, (x, y) => x * y), (x, y) => x + y);
      }

      return real.Zip(avg, (x, y) => x / y);
    }
    public override IOperation Apply() {
      DataTable table = DataTableParameter.ActualValue;
      if (table == null) {
        table = new DataTable(DataTableParameter.ActualName);
        DataTableParameter.ActualValue = table;
      }

      foreach (IParameter param in CollectedValues) {
        ILookupParameter lookupParam = param as ILookupParameter;
        string name = lookupParam != null ? lookupParam.TranslatedName : param.Name;

        if (param.ActualValue is DoubleValue) {
          AddValue(table, (param.ActualValue as DoubleValue).Value, name, param.Description);
        } else if (param.ActualValue is IntValue) {
          AddValue(table, (param.ActualValue as IntValue).Value, name, param.Description);
        } else if (param.ActualValue is IEnumerable<DoubleValue>) {
          IEnumerable<DoubleValue> values = (IEnumerable<DoubleValue>)param.ActualValue;
          if (values.Count() <= 1) {
            foreach (DoubleValue data in values)
              AddValue(table, data != null ? data.Value : double.NaN, name, param.Description);
          } else {
            int counter = 1;
            foreach (DoubleValue data in values) {
              AddValue(table, data != null ? data.Value : double.NaN, name + " " + counter.ToString(), param.Description);
              counter++;
            }
          }
        } else if (param.ActualValue is IEnumerable<IntValue>) {
          IEnumerable<IntValue> values = (IEnumerable<IntValue>)param.ActualValue;
          if (values.Count() <= 1) {
            foreach (IntValue data in values)
              AddValue(table, data != null ? data.Value : double.NaN, name, param.Description);
          } else {
            int counter = 1;
            foreach (IntValue data in values) {
              AddValue(table, data != null ? data.Value : double.NaN, name + " " + counter.ToString(), param.Description);
              counter++;
            }
          }
        } else {
          AddValue(table, double.NaN, name, param.Description);
        }
      }
      return base.Apply();
    }
    protected override void Run(CancellationToken cancellationToken) {
      // Set up the algorithm
      if (SetSeedRandomly) Seed = new System.Random().Next();
      var rand = new MersenneTwister((uint)Seed);

      // Set up the results display
      var iterations = new IntValue(0);
      Results.Add(new Result("Iterations", iterations));

      var table = new DataTable("Qualities");
      table.Rows.Add(new DataRow("R² (train)"));
      table.Rows.Add(new DataRow("R² (test)"));
      Results.Add(new Result("Qualities", table));
      var curLoss = new DoubleValue();
      var curTestLoss = new DoubleValue();
      Results.Add(new Result("R² (train)", curLoss));
      Results.Add(new Result("R² (test)", curTestLoss));
      var runCollection = new RunCollection();
      if (StoreRuns)
        Results.Add(new Result("Runs", runCollection));

      // init
      var problemData = Problem.ProblemData;
      var targetVarName = problemData.TargetVariable;
      var activeVariables = problemData.AllowedInputVariables.Concat(new string[] { problemData.TargetVariable });
      var modifiableDataset = new ModifiableDataset(
        activeVariables,
        activeVariables.Select(v => problemData.Dataset.GetDoubleValues(v).ToList()));

      var trainingRows = problemData.TrainingIndices;
      var testRows = problemData.TestIndices;
      var yPred = new double[trainingRows.Count()];
      var yPredTest = new double[testRows.Count()];
      var y = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TrainingIndices).ToArray();
      var curY = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TrainingIndices).ToArray();

      var yTest = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TestIndices).ToArray();
      var curYTest = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TestIndices).ToArray();
      var nu = Nu;
      var mVars = (int)Math.Ceiling(M * problemData.AllowedInputVariables.Count());
      var rRows = (int)Math.Ceiling(R * problemData.TrainingIndices.Count());
      var alg = RegressionAlgorithm;
      List<IRegressionModel> models = new List<IRegressionModel>();
      try {

        // Loop until iteration limit reached or canceled.
        for (int i = 0; i < Iterations; i++) {
          cancellationToken.ThrowIfCancellationRequested();

          modifiableDataset.RemoveVariable(targetVarName);
          modifiableDataset.AddVariable(targetVarName, curY.Concat(curYTest));

          SampleTrainingData(rand, modifiableDataset, rRows, problemData.Dataset, curY, problemData.TargetVariable, problemData.TrainingIndices); // all training indices from the original problem data are allowed 
          var modifiableProblemData = new RegressionProblemData(modifiableDataset,
            problemData.AllowedInputVariables.SampleRandomWithoutRepetition(rand, mVars),
            problemData.TargetVariable);
          modifiableProblemData.TrainingPartition.Start = 0;
          modifiableProblemData.TrainingPartition.End = rRows;
          modifiableProblemData.TestPartition.Start = problemData.TestPartition.Start;
          modifiableProblemData.TestPartition.End = problemData.TestPartition.End;

          if (!TrySetProblemData(alg, modifiableProblemData))
            throw new NotSupportedException("The algorithm cannot be used with GBM.");

          IRegressionModel model;
          IRun run;

          // try to find a model. The algorithm might fail to produce a model. In this case we just retry until the iterations are exhausted
          if (TryExecute(alg, rand.Next(), RegressionAlgorithmResult, out model, out run)) {
            int row = 0;
            // update predictions for training and test
            // update new targets (in the case of squared error loss we simply use negative residuals)
            foreach (var pred in model.GetEstimatedValues(problemData.Dataset, trainingRows)) {
              yPred[row] = yPred[row] + nu * pred;
              curY[row] = y[row] - yPred[row];
              row++;
            }
            row = 0;
            foreach (var pred in model.GetEstimatedValues(problemData.Dataset, testRows)) {
              yPredTest[row] = yPredTest[row] + nu * pred;
              curYTest[row] = yTest[row] - yPredTest[row];
              row++;
            }
            // determine quality
            OnlineCalculatorError error;
            var trainR = OnlinePearsonsRCalculator.Calculate(yPred, y, out error);
            var testR = OnlinePearsonsRCalculator.Calculate(yPredTest, yTest, out error);

            // iteration results
            curLoss.Value = error == OnlineCalculatorError.None ? trainR * trainR : 0.0;
            curTestLoss.Value = error == OnlineCalculatorError.None ? testR * testR : 0.0;

            models.Add(model);


          }

          if (StoreRuns)
            runCollection.Add(run);
          table.Rows["R² (train)"].Values.Add(curLoss.Value);
          table.Rows["R² (test)"].Values.Add(curTestLoss.Value);
          iterations.Value = i + 1;
        }

        // produce solution 
        if (CreateSolution) {
          // when all our models are symbolic models we can easily combine them to a single model
          if (models.All(m => m is ISymbolicRegressionModel)) {
            Results.Add(new Result("Solution", CreateSymbolicSolution(models, Nu, (IRegressionProblemData)problemData.Clone())));
          }
          // just produce an ensemble solution for now (TODO: correct scaling or linear regression for ensemble model weights)

          var ensembleSolution = CreateEnsembleSolution(models, (IRegressionProblemData)problemData.Clone());
          Results.Add(new Result("EnsembleSolution", ensembleSolution));
        }
      }
      finally {
        // reset everything
        alg.Prepare(true);
      }
    }
Exemple #8
0
 protected DataTable(DataTable original, Cloner cloner)
   : base(original, cloner) {
   VisualProperties = (DataTableVisualProperties)cloner.Clone(original.visualProperties);
   Rows = cloner.Clone(original.rows);
 }
    protected override void Run(CancellationToken cancellationToken) {
      // Set up the algorithm
      if (SetSeedRandomly) Seed = new System.Random().Next();
      pyramid = new List<Population>();
      seen.Clear();
      random.Reset(Seed);
      tracker = new EvaluationTracker(Problem, MaximumEvaluations);

      // Set up the results display
      Results.Add(new Result("Iterations", new IntValue(0)));
      Results.Add(new Result("Evaluations", new IntValue(0)));
      Results.Add(new Result("Best Solution", new BinaryVector(tracker.BestSolution)));
      Results.Add(new Result("Best Quality", new DoubleValue(tracker.BestQuality)));
      Results.Add(new Result("Evaluation Best Solution Was Found", new IntValue(tracker.BestFoundOnEvaluation)));
      var table = new DataTable("Qualities");
      table.Rows.Add(new DataRow("Best Quality"));
      var iterationRows = new DataRow("Iteration Quality");
      iterationRows.VisualProperties.LineStyle = DataRowVisualProperties.DataRowLineStyle.Dot;
      table.Rows.Add(iterationRows);
      Results.Add(new Result("Qualities", table));

      table = new DataTable("Pyramid Levels");
      table.Rows.Add(new DataRow("Levels"));
      Results.Add(new Result("Pyramid Levels", table));

      table = new DataTable("Stored Solutions");
      table.Rows.Add(new DataRow("Solutions"));
      Results.Add(new Result("Stored Solutions", table));

      // Loop until iteration limit reached or canceled.
      for (ResultsIterations = 0; ResultsIterations < MaximumIterations; ResultsIterations++) {
        double fitness = double.NaN;

        try {
          fitness = iterate();
          cancellationToken.ThrowIfCancellationRequested();
        } finally {
          ResultsEvaluations = tracker.Evaluations;
          ResultsBestSolution = new BinaryVector(tracker.BestSolution);
          ResultsBestQuality = tracker.BestQuality;
          ResultsBestFoundOnEvaluation = tracker.BestFoundOnEvaluation;
          ResultsQualitiesBest.Values.Add(tracker.BestQuality);
          ResultsQualitiesIteration.Values.Add(fitness);
          ResultsLevels.Values.Add(pyramid.Count);
          ResultsSolutions.Values.Add(seen.Count);
        }
      }
    }
    protected override void Run(CancellationToken cancellationToken) {
      // Set up the algorithm
      if (SetSeedRandomly) Seed = new System.Random().Next();

      // Set up the results display
      var iterations = new IntValue(0);
      Results.Add(new Result("Iterations", iterations));

      var table = new DataTable("Qualities");
      table.Rows.Add(new DataRow("Loss (train)"));
      table.Rows.Add(new DataRow("Loss (test)"));
      Results.Add(new Result("Qualities", table));
      var curLoss = new DoubleValue();
      Results.Add(new Result("Loss (train)", curLoss));

      // init
      var problemData = (IRegressionProblemData)Problem.ProblemData.Clone();
      var lossFunction = LossFunctionParameter.Value;
      var state = GradientBoostedTreesAlgorithmStatic.CreateGbmState(problemData, lossFunction, (uint)Seed, MaxSize, R, M, Nu);

      var updateInterval = UpdateIntervalParameter.Value.Value;
      // Loop until iteration limit reached or canceled.
      for (int i = 0; i < Iterations; i++) {
        cancellationToken.ThrowIfCancellationRequested();

        GradientBoostedTreesAlgorithmStatic.MakeStep(state);

        // iteration results
        if (i % updateInterval == 0) {
          curLoss.Value = state.GetTrainLoss();
          table.Rows["Loss (train)"].Values.Add(curLoss.Value);
          table.Rows["Loss (test)"].Values.Add(state.GetTestLoss());
          iterations.Value = i;
        }
      }

      // final results
      iterations.Value = Iterations;
      curLoss.Value = state.GetTrainLoss();
      table.Rows["Loss (train)"].Values.Add(curLoss.Value);
      table.Rows["Loss (test)"].Values.Add(state.GetTestLoss());

      // produce variable relevance
      var orderedImpacts = state.GetVariableRelevance().Select(t => new { name = t.Key, impact = t.Value }).ToList();

      var impacts = new DoubleMatrix();
      var matrix = impacts as IStringConvertibleMatrix;
      matrix.Rows = orderedImpacts.Count;
      matrix.RowNames = orderedImpacts.Select(x => x.name);
      matrix.Columns = 1;
      matrix.ColumnNames = new string[] { "Relative variable relevance" };

      int rowIdx = 0;
      foreach (var p in orderedImpacts) {
        matrix.SetValue(string.Format("{0:N2}", p.impact), rowIdx++, 0);
      }

      Results.Add(new Result("Variable relevance", impacts));
      Results.Add(new Result("Loss (test)", new DoubleValue(state.GetTestLoss())));

      // produce solution 
      if (CreateSolution) {
        var model = state.GetModel();

        // for logistic regression we produce a classification solution
        if (lossFunction is LogisticRegressionLoss) {
          var classificationModel = new DiscriminantFunctionClassificationModel(model,
            new AccuracyMaximizationThresholdCalculator());
          var classificationProblemData = new ClassificationProblemData(problemData.Dataset,
            problemData.AllowedInputVariables, problemData.TargetVariable, problemData.Transformations);
          classificationModel.RecalculateModelParameters(classificationProblemData, classificationProblemData.TrainingIndices);

          var classificationSolution = new DiscriminantFunctionClassificationSolution(classificationModel, classificationProblemData);
          Results.Add(new Result("Solution", classificationSolution));
        } else {
          // otherwise we produce a regression solution
          Results.Add(new Result("Solution", new RegressionSolution(model, problemData)));
        }
      }
    }
    public override IOperation Apply() {
      int updateInterval = UpdateIntervalParameter.Value.Value;
      IntValue updateCounter = UpdateCounterParameter.ActualValue;
      // if counter does not yet exist then initialize it with update interval
      // to make sure the solutions are analyzed on the first application of this operator
      if (updateCounter == null) {
        updateCounter = new IntValue(updateInterval);
        UpdateCounterParameter.ActualValue = updateCounter;
      } else updateCounter.Value++;

      //analyze solutions only every 'updateInterval' times
      if (updateCounter.Value == updateInterval) {
        updateCounter.Value = 0;

        bool max = MaximizationParameter.ActualValue.Value;
        ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
        bool storeHistory = StoreHistoryParameter.Value.Value;
        int count = CurrentScopeParameter.ActualValue.SubScopes.Count;

        if (count > 1) {
          // calculate solution similarities
          var similarityMatrix = SimilarityCalculator.CalculateSolutionCrowdSimilarity(CurrentScopeParameter.ActualValue);

          // sort similarities by quality
          double[][] sortedSimilarityMatrix = null;
          if (max)
            sortedSimilarityMatrix = similarityMatrix
              .Select((x, index) => new { Solutions = x, Quality = qualities[index] })
              .OrderByDescending(x => x.Quality)
              .Select(x => x.Solutions)
              .ToArray();
          else
            sortedSimilarityMatrix = similarityMatrix
              .Select((x, index) => new { Solutions = x, Quality = qualities[index] })
              .OrderBy(x => x.Quality)
              .Select(x => x.Solutions)
              .ToArray();

          double[,] similarities = new double[similarityMatrix.Length, similarityMatrix[0].Length];
          for (int i = 0; i < similarityMatrix.Length; i++)
            for (int j = 0; j < similarityMatrix[0].Length; j++)
              similarities[i, j] = similarityMatrix[i][j];

          // calculate minimum, average and maximum similarities
          double similarity;
          double[] minSimilarities = new double[count];
          double[] avgSimilarities = new double[count];
          double[] maxSimilarities = new double[count];
          for (int i = 0; i < count; i++) {
            minSimilarities[i] = 1;
            avgSimilarities[i] = 0;
            maxSimilarities[i] = 0;
            for (int j = 0; j < count; j++) {
              if (i != j) {
                similarity = similarities[i, j];

                if ((similarity < 0) || (similarity > 1))
                  throw new InvalidOperationException("Solution similarities have to be in the interval [0;1].");

                if (minSimilarities[i] > similarity) minSimilarities[i] = similarity;
                avgSimilarities[i] += similarity;
                if (maxSimilarities[i] < similarity) maxSimilarities[i] = similarity;
              }
            }
            avgSimilarities[i] = avgSimilarities[i] / (count - 1);
          }
          double avgMinSimilarity = minSimilarities.Average();
          double avgAvgSimilarity = avgSimilarities.Average();
          double avgMaxSimilarity = maxSimilarities.Average();

          // fetch results collection
          ResultCollection results;
          if (!ResultsParameter.ActualValue.ContainsKey(Name + " Results")) {
            results = new ResultCollection();
            ResultsParameter.ActualValue.Add(new Result(Name + " Results", results));
          } else {
            results = (ResultCollection)ResultsParameter.ActualValue[Name + " Results"].Value;
          }

          // store similarities
          HeatMap similaritiesHeatMap = new HeatMap(similarities, "Solution Similarities", 0.0, 1.0);
          if (!results.ContainsKey("Solution Similarities"))
            results.Add(new Result("Solution Similarities", similaritiesHeatMap));
          else
            results["Solution Similarities"].Value = similaritiesHeatMap;

          // store similarities history
          if (storeHistory) {
            if (!results.ContainsKey("Solution Similarities History")) {
              HeatMapHistory history = new HeatMapHistory();
              history.Add(similaritiesHeatMap);
              results.Add(new Result("Solution Similarities History", history));
            } else {
              ((HeatMapHistory)results["Solution Similarities History"].Value).Add(similaritiesHeatMap);
            }
          }

          // store average minimum, average and maximum similarity
          if (!results.ContainsKey("Average Minimum Solution Similarity"))
            results.Add(new Result("Average Minimum Solution Similarity", new DoubleValue(avgMinSimilarity)));
          else
            ((DoubleValue)results["Average Minimum Solution Similarity"].Value).Value = avgMinSimilarity;

          if (!results.ContainsKey("Average Average Solution Similarity"))
            results.Add(new Result("Average Average Solution Similarity", new DoubleValue(avgAvgSimilarity)));
          else
            ((DoubleValue)results["Average Average Solution Similarity"].Value).Value = avgAvgSimilarity;

          if (!results.ContainsKey("Average Maximum Solution Similarity"))
            results.Add(new Result("Average Maximum Solution Similarity", new DoubleValue(avgMaxSimilarity)));
          else
            ((DoubleValue)results["Average Maximum Solution Similarity"].Value).Value = avgMaxSimilarity;

          // store average minimum, average and maximum solution similarity data table
          DataTable minAvgMaxSimilarityDataTable;
          if (!results.ContainsKey("Average Minimum/Average/Maximum Solution Similarity")) {
            minAvgMaxSimilarityDataTable = new DataTable("Average Minimum/Average/Maximum Solution Similarity");
            minAvgMaxSimilarityDataTable.VisualProperties.XAxisTitle = "Iteration";
            minAvgMaxSimilarityDataTable.VisualProperties.YAxisTitle = "Solution Similarity";
            minAvgMaxSimilarityDataTable.Rows.Add(new DataRow("Average Minimum Solution Similarity", null));
            minAvgMaxSimilarityDataTable.Rows["Average Minimum Solution Similarity"].VisualProperties.StartIndexZero = true;
            minAvgMaxSimilarityDataTable.Rows.Add(new DataRow("Average Average Solution Similarity", null));
            minAvgMaxSimilarityDataTable.Rows["Average Average Solution Similarity"].VisualProperties.StartIndexZero = true;
            minAvgMaxSimilarityDataTable.Rows.Add(new DataRow("Average Maximum Solution Similarity", null));
            minAvgMaxSimilarityDataTable.Rows["Average Maximum Solution Similarity"].VisualProperties.StartIndexZero = true;
            results.Add(new Result("Average Minimum/Average/Maximum Solution Similarity", minAvgMaxSimilarityDataTable));
          } else {
            minAvgMaxSimilarityDataTable = (DataTable)results["Average Minimum/Average/Maximum Solution Similarity"].Value;
          }
          minAvgMaxSimilarityDataTable.Rows["Average Minimum Solution Similarity"].Values.Add(avgMinSimilarity);
          minAvgMaxSimilarityDataTable.Rows["Average Average Solution Similarity"].Values.Add(avgAvgSimilarity);
          minAvgMaxSimilarityDataTable.Rows["Average Maximum Solution Similarity"].Values.Add(avgMaxSimilarity);

          // store minimum, average, maximum similarities data table
          DataTable minAvgMaxSimilaritiesDataTable = new DataTable("Minimum/Average/Maximum Solution Similarities");
          minAvgMaxSimilaritiesDataTable.VisualProperties.XAxisTitle = "Solution Index";
          minAvgMaxSimilaritiesDataTable.VisualProperties.YAxisTitle = "Solution Similarity";
          minAvgMaxSimilaritiesDataTable.Rows.Add(new DataRow("Minimum Solution Similarity", null, minSimilarities));
          minAvgMaxSimilaritiesDataTable.Rows["Minimum Solution Similarity"].VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
          minAvgMaxSimilaritiesDataTable.Rows.Add(new DataRow("Average Solution Similarity", null, avgSimilarities));
          minAvgMaxSimilaritiesDataTable.Rows["Average Solution Similarity"].VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
          minAvgMaxSimilaritiesDataTable.Rows.Add(new DataRow("Maximum Solution Similarity", null, maxSimilarities));
          minAvgMaxSimilaritiesDataTable.Rows["Maximum Solution Similarity"].VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
          if (!results.ContainsKey("Minimum/Average/Maximum Solution Similarities")) {
            results.Add(new Result("Minimum/Average/Maximum Solution Similarities", minAvgMaxSimilaritiesDataTable));
          } else {
            results["Minimum/Average/Maximum Solution Similarities"].Value = minAvgMaxSimilaritiesDataTable;
          }

          // store minimum, average, maximum similarities history
          if (storeHistory) {
            if (!results.ContainsKey("Minimum/Average/Maximum Solution Similarities History")) {
              DataTableHistory history = new DataTableHistory();
              history.Add(minAvgMaxSimilaritiesDataTable);
              results.Add(new Result("Minimum/Average/Maximum Solution Similarities History", history));
            } else {
              ((DataTableHistory)results["Minimum/Average/Maximum Solution Similarities History"].Value).Add(minAvgMaxSimilaritiesDataTable);
            }
          }
        }
      }
      return base.Apply();
    }
    private void AddAverageTableEntry(IntValue[] values, string tableName) {
      if (!ResultCollection.ContainsKey(tableName)) {
        var newTable = new DataTable(tableName, "");
        newTable.VisualProperties.YAxisTitle = "Average";
        newTable.VisualProperties.YAxisMaximumAuto = false;

        DataRow row = new DataRow("Average");
        row.VisualProperties.StartIndexZero = true;
        newTable.Rows.Add(row);

        ResultCollection.Add(new Result(tableName, newTable));
      }
      var table = ((DataTable)ResultCollection[tableName].Value);
      table.Rows["Average"].Values.Add(values.Select(x => x.Value).Average());
    }
    public override IOperation Apply() {
      ItemArray<ISymbolicExpressionTree> expressions = SymbolicExpressionTreeParameter.ActualValue;
      ResultCollection results = ResultsParameter.ActualValue;
      DataTable symbolFrequencies = SymbolFrequenciesParameter.ActualValue;
      if (symbolFrequencies == null) {
        symbolFrequencies = new DataTable("Symbol frequencies", "Relative frequency of symbols aggregated over the whole population.");
        symbolFrequencies.VisualProperties.YAxisTitle = "Relative Symbol Frequency";

        SymbolFrequenciesParameter.ActualValue = symbolFrequencies;
        results.Add(new Result("Symbol frequencies", symbolFrequencies));
      }

      // all rows must have the same number of values so we can just take the first
      int numberOfValues = symbolFrequencies.Rows.Select(r => r.Values.Count).DefaultIfEmpty().First();

      foreach (var pair in SymbolicExpressionSymbolFrequencyAnalyzer.CalculateSymbolFrequencies(expressions, AggregrateSymbolsWithDifferentSubtreeCount.Value)) {
        if (!symbolFrequencies.Rows.ContainsKey(pair.Key)) {
          // initialize a new row for the symbol and pad with zeros
          DataRow row = new DataRow(pair.Key, "", Enumerable.Repeat(0.0, numberOfValues));
          row.VisualProperties.StartIndexZero = true;
          symbolFrequencies.Rows.Add(row);
        }
        symbolFrequencies.Rows[pair.Key].Values.Add(Math.Round(pair.Value, 3));
      }

      // add a zero for each data row that was not modified in the previous loop 
      foreach (var row in symbolFrequencies.Rows.Where(r => r.Values.Count != numberOfValues + 1))
        row.Values.Add(0.0);

      return base.Apply();
    }
    public override IOperation Apply() {
      //code executed in the first call of analyzer
      if (qualitiesBeforeCoOp == null) {
        double[] trainingQuality;
        // sort is ascending and we take the first n% => order so that best solutions are smallest
        // sort order is determined by maximization parameter
        if (Maximization.Value) {
          // largest values must be sorted first
          trainingQuality = Quality.Select(x => -x.Value).ToArray();
        } else {
          // smallest values must be sorted first
          trainingQuality = Quality.Select(x => x.Value).ToArray();
        }
        // sort trees by training qualities
        int topN = (int)Math.Max(trainingQuality.Length * PercentageOfBestSolutions, 1);
        scopeIndexes = Enumerable.Range(0, trainingQuality.Length).ToArray();
        Array.Sort(trainingQuality, scopeIndexes);
        scopeIndexes = scopeIndexes.Take(topN).ToArray();
        qualitiesBeforeCoOp = scopeIndexes.Select(x => Quality[x].Value).ToArray();

        OperationCollection operationCollection = new OperationCollection();
        operationCollection.Parallel = true;
        foreach (var scopeIndex in scopeIndexes) {
          var childOperation = ExecutionContext.CreateChildOperation(ConstantOptimizationEvaluator, ExecutionContext.Scope.SubScopes[scopeIndex]);
          operationCollection.Add(childOperation);
        }

        return new OperationCollection { operationCollection, ExecutionContext.CreateOperation(this) };
      }

      //code executed to analyze results of constant optimization
      double[] qualitiesAfterCoOp = scopeIndexes.Select(x => Quality[x].Value).ToArray();
      var qualityImprovement = qualitiesBeforeCoOp.Zip(qualitiesAfterCoOp, (b, a) => a - b).ToArray();

      if (!ResultCollection.ContainsKey(DataTableNameConstantOptimizationImprovement)) {
        var dataTable = new DataTable(DataTableNameConstantOptimizationImprovement);
        ResultCollection.Add(new Result(DataTableNameConstantOptimizationImprovement, dataTable));
        dataTable.VisualProperties.YAxisTitle = "R²";

        dataTable.Rows.Add(new DataRow(DataRowNameMinimumImprovement));
        MinimumImprovement.VisualProperties.StartIndexZero = true;

        dataTable.Rows.Add(new DataRow(DataRowNameMedianImprovement));
        MedianImprovement.VisualProperties.StartIndexZero = true;

        dataTable.Rows.Add(new DataRow(DataRowNameAverageImprovement));
        AverageImprovement.VisualProperties.StartIndexZero = true;

        dataTable.Rows.Add(new DataRow(DataRowNameMaximumImprovement));
        MaximumImprovement.VisualProperties.StartIndexZero = true;
      }

      MinimumImprovement.Values.Add(qualityImprovement.Min());
      MedianImprovement.Values.Add(qualityImprovement.Median());
      AverageImprovement.Values.Add(qualityImprovement.Average());
      MaximumImprovement.Values.Add(qualityImprovement.Max());

      qualitiesBeforeCoOp = null;
      scopeIndexes = null;
      return base.Apply();
    }
    private void AddSemanticallyDifferentFromRootedParentTableEntry(BoolValue[] semanticallyDifferentFromRootedParent) {
      if (SemanticallyDifferentFromRootedParentDataTable == null) {
        var table = new DataTable(SemanticallyDifferentFromRootedParentParameterName, "");
        table.VisualProperties.YAxisTitle = "Percentage";
        table.VisualProperties.YAxisMaximumFixedValue = 100.0;
        table.VisualProperties.YAxisMaximumAuto = false;

        DataRow differentRow = new DataRow("Different From Parent");
        differentRow.VisualProperties.StartIndexZero = true;
        table.Rows.Add(differentRow);

        DataRow sameRow = new DataRow("Same As Parent");
        sameRow.VisualProperties.StartIndexZero = true;
        table.Rows.Add(sameRow);

        SemanticallyDifferentFromRootedParentDataTable = table;
      }
      double different = semanticallyDifferentFromRootedParent.Count(x => x.Value);

      SemanticallyDifferentFromRootedParentDataTable.Rows["Different From Parent"].Values.Add(different / semanticallyDifferentFromRootedParent.Length * 100.0);
      SemanticallyDifferentFromRootedParentDataTable.Rows["Same As Parent"].Values.Add((semanticallyDifferentFromRootedParent.Length - different) / semanticallyDifferentFromRootedParent.Length * 100.0);
    }
    public override IOperation Apply() {
      ResultCollection results = ResultsParameter.ActualValue;

      List<IScope> scopes = new List<IScope>() { ExecutionContext.Scope };
      for (int i = 0; i < DepthParameter.Value.Value; i++)
        scopes = scopes.Select(x => (IEnumerable<IScope>)x.SubScopes).Aggregate((a, b) => a.Concat(b)).ToList();

      ItemCollection<StringValue> collectedValues = CollectedValuesParameter.Value;
      foreach (StringValue collected in collectedValues) {
        //collect the values of the successful offspring
        Dictionary<String, int> counts = new Dictionary<String, int>();
        for (int i = 0; i < scopes.Count; i++) {
          IScope child = scopes[i];
          string successfulOffspringFlag = SuccessfulOffspringFlagParameter.Value.Value;
          if (child.Variables.ContainsKey(collected.Value) &&
              child.Variables.ContainsKey(successfulOffspringFlag) &&
              (child.Variables[successfulOffspringFlag].Value is BoolValue) &&
              (child.Variables[successfulOffspringFlag].Value as BoolValue).Value) {
            String key = child.Variables[collected.Value].Value.ToString();

            if (!counts.ContainsKey(key))
              counts.Add(key, 1);
            else
              counts[key]++;
          }
        }

        if (counts.Count > 0) {
          //create a data table containing the collected values
          ResultCollection successfulOffspringAnalysis;

          if (SuccessfulOffspringAnalysisParameter.ActualValue == null) {
            successfulOffspringAnalysis = new ResultCollection();
            SuccessfulOffspringAnalysisParameter.ActualValue = successfulOffspringAnalysis;
          } else {
            successfulOffspringAnalysis = SuccessfulOffspringAnalysisParameter.ActualValue;
          }

          string resultKey = "SuccessfulOffspringAnalyzer Results";
          if (!results.ContainsKey(resultKey)) {
            results.Add(new Result(resultKey, successfulOffspringAnalysis));
          } else {
            results[resultKey].Value = successfulOffspringAnalysis;
          }

          DataTable successProgressAnalysis;
          if (!successfulOffspringAnalysis.ContainsKey(collected.Value)) {
            successProgressAnalysis = new DataTable();
            successProgressAnalysis.Name = collected.Value;
            successfulOffspringAnalysis.Add(new Result(collected.Value, successProgressAnalysis));
          } else {
            successProgressAnalysis = successfulOffspringAnalysis[collected.Value].Value as DataTable;
          }

          int successfulCount = 0;
          foreach (string key in counts.Keys) {
            successfulCount += counts[key];
          }

          foreach (String value in counts.Keys) {
            DataRow row;
            if (!successProgressAnalysis.Rows.ContainsKey(value)) {
              row = new DataRow(value);
              int iterations = GenerationsParameter.ActualValue.Value;

              //fill up all values seen the first time
              for (int i = 1; i < iterations; i++)
                row.Values.Add(0);

              successProgressAnalysis.Rows.Add(row);
            } else {
              row = successProgressAnalysis.Rows[value];
            }

            row.Values.Add(counts[value] / (double)successfulCount);
          }

          //fill up all values that are not present in the current generation
          foreach (DataRow row in successProgressAnalysis.Rows) {
            if (!counts.ContainsKey(row.Name))
              row.Values.Add(0);
          }
        }
      }

      return base.Apply();
    }
 private void AddValue(DataTable table, double data, string name, string description) {
   DataRow row;
   table.Rows.TryGetValue(name, out row);
   if (row == null) {
     row = new DataRow(name, description);
     row.VisualProperties.StartIndexZero = StartIndexZero;
     row.Values.Add(data);
     table.Rows.Add(row);
   } else {
     row.Values.Add(data);
   }
 }
    private void AddSemanticLocalityTableEntry(double average) {
      if (SemanticLocalityDataTable == null) {
        var table = new DataTable(SemanticLocalityParameterName, "");
        table.VisualProperties.YAxisTitle = "Average Fitness Change";

        DataRow row = new DataRow("Sematic Locality");
        row.VisualProperties.StartIndexZero = true;
        table.Rows.Add(row);

        SemanticLocalityDataTable = table;
      }
      SemanticLocalityDataTable.Rows["Sematic Locality"].Values.Add(average);
    }
    public override IOperation Apply() {
      DataTable ageDistribution = null;
      ResultCollection results = ResultsParameter.ActualValue;
      string description = "Shows the age distributions in the current population.";
      if (results.ContainsKey(HistogramName)) {
        ageDistribution = results[HistogramName].Value as DataTable;
      } else {
        ageDistribution = new DataTable("Population Age Distribution", description);
        ageDistribution.VisualProperties.XAxisTitle = AgeParameter.ActualName;
        ageDistribution.VisualProperties.YAxisTitle = "Frequency";
        results.Add(new Result(HistogramName, description, ageDistribution));
      }
      DataRow row;
      if (!ageDistribution.Rows.TryGetValue("AgeDistribution", out row)) {
        row = new DataRow("AgeDistribution");
        row.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Histogram;
        ageDistribution.Rows.Add(row);
      }
      var ages = AgeParameter.ActualValue;
      row.Values.Replace(ages.Select(x => x.Value));

      if (StoreHistory) {
        string historyResultName = HistogramName + " History";
        DataTableHistory adHistory = null;
        if (results.ContainsKey(historyResultName)) {
          adHistory = results[historyResultName].Value as DataTableHistory;
        } else {
          adHistory = new DataTableHistory();
          results.Add(new Result(historyResultName, adHistory));
        }
        DataTable table = (DataTable)ageDistribution.Clone();
        IntValue iteration = IterationsParameter.ActualValue;
        if (iteration != null) {
          string iterationName = IterationsParameter.ActualName;
          if (iterationName.EndsWith("s")) iterationName = iterationName.Remove(iterationName.Length - 1);
          string appendix = " at " + iterationName + " " + iteration.Value.ToString();
          table.Name += appendix;
          table.Rows["AgeDistribution"].VisualProperties.DisplayName += appendix;
        }
        adHistory.Add(table);
      }
      return base.Apply();
    }
    public override IOperation Apply() {
      var results = ResultCollectionParameter.ActualValue;

      if (!results.ContainsKey(RegressionSolutionQualitiesResultName)) {
        var newDataTable = new DataTable(RegressionSolutionQualitiesResultName);
        results.Add(new Result(RegressionSolutionQualitiesResultName, "Chart displaying the training and test qualities of the regression solutions.", newDataTable));
      }

      var dataTable = (DataTable)results[RegressionSolutionQualitiesResultName].Value;

      // only if the parameters are available (not available in old persisted code)
      ILookupParameter<DoubleValue> trainingQualityParam = null;
      ILookupParameter<DoubleValue> testQualityParam = null;
      // store actual names of parameter because it is changed below
      trainingQualityParam = TrainingQualityParameter;
      string prevTrainingQualityParamName = trainingQualityParam.ActualName;
      testQualityParam = TestQualityParameter;
      string prevTestQualityParamName = testQualityParam.ActualName;
      foreach (var result in results.Where(r => r.Value is IRegressionSolution)) {
        var solution = (IRegressionSolution)result.Value;

        var trainingR2Name = result.Name + " Training R²";
        if (!dataTable.Rows.ContainsKey(trainingR2Name))
          dataTable.Rows.Add(new DataRow(trainingR2Name));

        var testR2Name = result.Name + " Test R²";
        if (!dataTable.Rows.ContainsKey(testR2Name))
          dataTable.Rows.Add(new DataRow(testR2Name));

        dataTable.Rows[trainingR2Name].Values.Add(solution.TrainingRSquared);
        dataTable.Rows[testR2Name].Values.Add(solution.TestRSquared);

        // also add training and test R² to the scope using the parameters
        // HACK: we change the ActualName of the parameter to write two variables for each solution in the results collection
        trainingQualityParam.ActualName = trainingR2Name;
        trainingQualityParam.ActualValue = new DoubleValue(solution.TrainingRSquared);
        testQualityParam.ActualName = testR2Name;
        testQualityParam.ActualValue = new DoubleValue(solution.TestRSquared);
      }

      trainingQualityParam.ActualName = prevTrainingQualityParamName;
      testQualityParam.ActualName = prevTestQualityParamName;

      return base.Apply();
    }
    private static DataTable CalcAverage(RunCollection runs, string tableName) {
      DataTable temptable = new DataTable();

      var visibleRuns = runs.Where(r => r.Visible);

      var resultName = (string)tableName;

      var dataTables = visibleRuns.Where(r => r.Results.ContainsKey(resultName)).Select(r => (DataTable)r.Results[resultName]);
      if (dataTables.Count() != visibleRuns.Count()) {
        throw new ArgumentException("Should not happen");
      }

      var dataRows = dataTables.SelectMany(dt => dt.Rows).GroupBy(r => r.Name, r => r);

      foreach (var row in dataRows) {
        var averageValues = DataRowsAggregate(Enumerable.Average, row.Select(r => r.Values));
        DataRow averageRow = new DataRow(row.Key, "Average of Values", averageValues);
        temptable.Rows.Add(averageRow);
      }
      return temptable;
    }
    private void AddConstructiveEffectTableEntry(IntValue[] constructiveEffect) {
      if (ConstructiveEffectDataTable == null) {
        var table = new DataTable(ConstructiveEffectParameterName, "");
        table.VisualProperties.YAxisTitle = "Percentage";
        table.VisualProperties.YAxisMaximumFixedValue = 100.0;
        table.VisualProperties.YAxisMaximumAuto = false;

        DataRow worseThanRootedRow = new DataRow("Worse than rooted");
        worseThanRootedRow.VisualProperties.StartIndexZero = true;
        table.Rows.Add(worseThanRootedRow);

        DataRow betterThanRootedRow = new DataRow("Better than rooted");
        betterThanRootedRow.VisualProperties.StartIndexZero = true;
        table.Rows.Add(betterThanRootedRow);

        DataRow betterThanBothRow = new DataRow("Better than both");
        betterThanBothRow.VisualProperties.StartIndexZero = true;
        table.Rows.Add(betterThanBothRow);

        ConstructiveEffectDataTable = table;
      }
      List<double> constructiveEffectCount = new List<double>() { 0.0, 0.0, 0.0 };
      for (int i = 0; i < constructiveEffect.Length; i++) {
        constructiveEffectCount[constructiveEffect[i].Value]++;
      }

      ConstructiveEffectDataTable.Rows["Worse than rooted"].Values.Add(constructiveEffectCount[0] / constructiveEffect.Length * 100.0);
      ConstructiveEffectDataTable.Rows["Better than rooted"].Values.Add((constructiveEffectCount[1] + constructiveEffectCount[2]) / constructiveEffect.Length * 100.0);
      ConstructiveEffectDataTable.Rows["Better than both"].Values.Add(constructiveEffectCount[2] / constructiveEffect.Length * 100.0);
    }
    public override IOperation Apply() {
      ItemArray<BoolArray> cases = CasesParameter.ActualValue;
      ItemArray<DoubleArray> caseQualities = CaseQualitiesParameter.ActualValue;
      int length = cases.First().Length;
      if (cases.Any(x => x.Length != length) || caseQualities.Any(x => x.Length != length)) {
        throw new ArgumentException("Every individual has to have the same number of cases.");
      }

      double count = cases.Count();
      int rows = cases.First().Length;
      ResultCollection results = ResultsParameter.ActualValue;
      DataTable casesSolvedFrequencies = CasesSolvedFrequenciesParameter.ActualValue;
      DataTable summedCaseQualities = SummedCaseQualitiesParameter.ActualValue;
      if (casesSolvedFrequencies == null || summedCaseQualities == null) {
        casesSolvedFrequencies = new DataTable("Cases solved", "Absolute frequency of cases solved aggregated over the whole population.");
        casesSolvedFrequencies.VisualProperties.YAxisTitle = "Absolute Cases Solved Frequency";
        summedCaseQualities = new DataTable("Summed case qualities", "Absolute frequency of cases solved aggregated over the whole population.");
        summedCaseQualities.VisualProperties.YAxisTitle = "Summed Cases Qualities";


        CasesSolvedFrequenciesParameter.ActualValue = casesSolvedFrequencies;
        SummedCaseQualitiesParameter.ActualValue = summedCaseQualities;
        results.Add(new Result("Cases solved", casesSolvedFrequencies));
        results.Add(new Result("Summed cases qualities", summedCaseQualities));
      }

      // all rows must have the same number of values so we can just take the first
      int numberOfValues = casesSolvedFrequencies.Rows.Select(r => r.Values.Count).DefaultIfEmpty().First();

      foreach (var triple in Enumerable.Range(0, cases[0].Length).Select(i => new Tuple<string, int, double>("Case " + i, cases.Count(caseArray => caseArray[i]), caseQualities.Sum(casesQualityArray => casesQualityArray[i])))) {
        if (!casesSolvedFrequencies.Rows.ContainsKey(triple.Item1)) {
          // initialize a new row for the symbol and pad with zeros
          DataRow row = new DataRow(triple.Item1, "", Enumerable.Repeat(0.0, numberOfValues));
          row.VisualProperties.StartIndexZero = true;
          casesSolvedFrequencies.Rows.Add(row);

          row = new DataRow(triple.Item1, "", Enumerable.Repeat(0.0, numberOfValues));
          row.VisualProperties.StartIndexZero = true;
          summedCaseQualities.Rows.Add(row);
        }
        casesSolvedFrequencies.Rows[triple.Item1].Values.Add(triple.Item2);
        summedCaseQualities.Rows[triple.Item1].Values.Add(triple.Item3);
      }
      return base.Apply();
    }
 public RunCollectionChartAverageView() {
   InitializeComponent();
   combinedDataTable = new DataTable("Combined DataTable", "A data table containing data rows from multiple runs.");
   viewHost.Content = combinedDataTable;
   suppressUpdates = false;
 }
Exemple #25
0
    public override IOperation Apply() {
      var sp = StrategyParametersParameter.ActualValue;
      var vector = MeanParameter.ActualValue;
      var results = ResultsParameter.ActualValue;
      var qualities = QualityParameter.ActualValue;
      double min = qualities[0].Value, max = qualities[0].Value, avg = qualities[0].Value;
      for (int i = 1; i < qualities.Length; i++) {
        if (qualities[i].Value < min) min = qualities[i].Value;
        if (qualities[i].Value > max) max = qualities[i].Value;
        avg += qualities[i].Value;
      }
      avg /= qualities.Length;

      DataTable progress;
      if (results.ContainsKey("Progress")) {
        progress = (DataTable)results["Progress"].Value;
      } else {
        progress = new DataTable("Progress");
        progress.Rows.Add(new DataRow("AxisRatio"));
        progress.Rows.Add(new DataRow("Sigma"));
        progress.Rows.Add(new DataRow("Min Quality"));
        progress.Rows.Add(new DataRow("Max Quality"));
        progress.Rows.Add(new DataRow("Avg Quality"));
        progress.VisualProperties.YAxisLogScale = true;
        results.Add(new Result("Progress", progress));
      }
      progress.Rows["AxisRatio"].Values.Add(sp.AxisRatio);
      progress.Rows["Sigma"].Values.Add(sp.Sigma);
      progress.Rows["Min Quality"].Values.Add(min);
      progress.Rows["Max Quality"].Values.Add(max);
      progress.Rows["Avg Quality"].Values.Add(avg);

      DataTable scaling;
      if (results.ContainsKey("Scaling")) {
        scaling = (DataTable)results["Scaling"].Value;
      } else {
        scaling = new DataTable("Scaling");
        scaling.VisualProperties.YAxisLogScale = true;
        for (int i = 0; i < sp.C.GetLength(0); i++)
          scaling.Rows.Add(new DataRow("Axis" + i.ToString()));
        results.Add(new Result("Scaling", scaling));
      }
      for (int i = 0; i < sp.C.GetLength(0); i++)
        scaling.Rows["Axis" + i.ToString()].Values.Add(sp.D[i]);

      DataTable realVector;
      if (results.ContainsKey("Object Variables")) {
        realVector = (DataTable)results["Object Variables"].Value;
      } else {
        realVector = new DataTable("Object Variables");
        for (int i = 0; i < vector.Length; i++)
          realVector.Rows.Add(new DataRow("Axis" + i.ToString()));
        results.Add(new Result("Object Variables", realVector));
      }
      for (int i = 0; i < vector.Length; i++)
        realVector.Rows["Axis" + i.ToString()].Values.Add(vector[i]);

      DataTable stdDevs;
      if (results.ContainsKey("Standard Deviations")) {
        stdDevs = (DataTable)results["Standard Deviations"].Value;
      } else {
        stdDevs = new DataTable("Standard Deviations");
        stdDevs.VisualProperties.YAxisLogScale = true;
        stdDevs.Rows.Add(new DataRow("MinStdDev"));
        stdDevs.Rows.Add(new DataRow("MaxStdDev"));
        for (int i = 0; i < vector.Length; i++)
          stdDevs.Rows.Add(new DataRow("Axis" + i.ToString()));
        results.Add(new Result("Standard Deviations", stdDevs));
      }
      for (int i = 0; i < vector.Length; i++)
        stdDevs.Rows["Axis" + i.ToString()].Values.Add(Math.Sqrt(sp.C[i, i]));
      stdDevs.Rows["MinStdDev"].Values.Add(sp.D.Min() * sp.Sigma);
      stdDevs.Rows["MaxStdDev"].Values.Add(sp.D.Max() * sp.Sigma);

      return base.Apply();
    }
    private void AddSemanticallyEquivalentCrossoverTableEntry(IntValue[] semanticallyEquivalentCrossover) {
      if (SemanticallyEquivalentCrossoverDataTable == null) {
        var table = new DataTable(SemanticallyEquivalentCrossoverParameterName, "");
        table.VisualProperties.YAxisTitle = "Percentage";
        table.VisualProperties.YAxisMaximumFixedValue = 100.0;
        table.VisualProperties.YAxisMaximumAuto = false;

        DataRow noCrossoverRow = new DataRow("No Crossover");
        noCrossoverRow.VisualProperties.StartIndexZero = true;
        table.Rows.Add(noCrossoverRow);

        DataRow equivalentRow = new DataRow("Equivalent");
        equivalentRow.VisualProperties.StartIndexZero = true;
        table.Rows.Add(equivalentRow);

        DataRow equivalentOrNoCrossoverRow = new DataRow("Equivalent + No Crossover");
        equivalentOrNoCrossoverRow.VisualProperties.StartIndexZero = true;
        table.Rows.Add(equivalentOrNoCrossoverRow);

        DataRow differentRow = new DataRow("Different");
        differentRow.VisualProperties.StartIndexZero = true;
        table.Rows.Add(differentRow);

        SemanticallyEquivalentCrossoverDataTable = table;
      }
      List<int> semanticallyEquivalentCrossoverCount = new List<int>() { 0, 0, 0 };
      for (int i = 0; i < semanticallyEquivalentCrossover.Length; i++) {
        semanticallyEquivalentCrossoverCount[semanticallyEquivalentCrossover[i].Value]++;
      }
      double total = semanticallyEquivalentCrossover.Length;
      SemanticallyEquivalentCrossoverDataTable.Rows["No Crossover"].Values.Add(semanticallyEquivalentCrossoverCount[0] / total * 100.0);
      SemanticallyEquivalentCrossoverDataTable.Rows["Equivalent"].Values.Add(semanticallyEquivalentCrossoverCount[1] / total * 100.0);
      SemanticallyEquivalentCrossoverDataTable.Rows["Equivalent + No Crossover"].Values.Add((semanticallyEquivalentCrossoverCount[0] + semanticallyEquivalentCrossoverCount[1]) / total * 100.0);
      SemanticallyEquivalentCrossoverDataTable.Rows["Different"].Values.Add(semanticallyEquivalentCrossoverCount[2] / total * 100.0);
    }
    public override IOperation Apply() {
      UpdateCounter.Value++;
      // the analyzer runs periodically, every 'updateInterval' times
      if (UpdateCounter.Value == UpdateInterval.Value) {
        UpdateCounter.Value = 0; // reset counter

        // compute all tree lengths and store them in the lengthsTable
        var solutions = SymbolicExpressionTreeParameter.ActualValue;

        var treeLengthsTable = SymbolicExpressionTreeLengthsParameter.ActualValue;
        // if the table was not created yet, we create it here
        if (treeLengthsTable == null) {
          treeLengthsTable = new DataTable("Tree Length Histogram");
          SymbolicExpressionTreeLengthsParameter.ActualValue = treeLengthsTable;
        }

        // data table which stores tree length values
        DataRow treeLengthsTableRow;

        const string treeLengthsTableRowName = "Symbolic expression tree lengths";
        const string treeLengthsTableRowDesc = "The distribution of symbolic expression tree lengths";
        const string xAxisTitle = "Symbolic expression tree lengths";
        const string yAxisTitle = "Frequency / Number of tree individuals";

        var treeLengths = solutions.Select(s => (int)s.Length).ToList();

        int maxLength = treeLengths.Max(t => t);
        int minLength = treeLengths.Min(t => t);

        if (!treeLengthsTable.Rows.ContainsKey(treeLengthsTableRowName)) {
          treeLengthsTableRow = new DataRow(treeLengthsTableRowName, treeLengthsTableRowDesc, treeLengths.Select(x => (double)x));
          treeLengthsTable.Rows.Add(treeLengthsTableRow);
        } else {
          treeLengthsTableRow = treeLengthsTable.Rows[treeLengthsTableRowName];
          treeLengthsTableRow.Values.Replace(treeLengths.Select(x => (double)x));
        }

        double maximumAllowedTreeLength = MaximumSymbolicExpressionTreeLengthParameter.ActualValue.Value;

        treeLengthsTableRow.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Histogram;
        treeLengthsTableRow.VisualProperties.ExactBins = false;

        int range = maxLength - minLength;
        if (range == 0) range = 1;
        // the following trick should result in an integer intervalWidth of 1,2,4,...
        treeLengthsTableRow.VisualProperties.Bins = range;

        if (maxLength <= 25) // [0,25]
          treeLengthsTableRow.VisualProperties.ScaleFactor = 1.0;
        else if (maxLength <= 100) // [26,100]
          treeLengthsTableRow.VisualProperties.ScaleFactor = 1.0 / 2.0;
        else if (maxLength <= 250) // [101,250]
          treeLengthsTableRow.VisualProperties.ScaleFactor = 1.0 / 5.0;
        else if (maxLength <= 500) // [251,500]
          treeLengthsTableRow.VisualProperties.ScaleFactor = 1.0 / 10.0;
        else
          treeLengthsTableRow.VisualProperties.ScaleFactor = 1.0 / 20.0; // [501,inf]

        treeLengthsTableRow.VisualProperties.IsVisibleInLegend = false;

        // visual properties for the X-axis
        treeLengthsTable.VisualProperties.XAxisMinimumAuto = false;
        treeLengthsTable.VisualProperties.XAxisMaximumAuto = false;
        treeLengthsTable.VisualProperties.XAxisMinimumFixedValue = 0.0;
        if (maxLength > maximumAllowedTreeLength + 1)
          treeLengthsTable.VisualProperties.XAxisMaximumFixedValue = maxLength + 1; // +1 so the histogram column for the maximum length won't get trimmed
        else
          treeLengthsTable.VisualProperties.XAxisMaximumFixedValue = maximumAllowedTreeLength + 1;
        treeLengthsTable.VisualProperties.XAxisTitle = xAxisTitle;
        //visual properties for the Y-axis
        treeLengthsTable.VisualProperties.YAxisMinimumAuto = false;
        treeLengthsTable.VisualProperties.YAxisMaximumAuto = false;
        treeLengthsTable.VisualProperties.YAxisMinimumFixedValue = 0.0;
        int maxFreq = (int)Math.Round(solutions.GroupBy(s => s.Length).Max(g => g.Count()) / treeLengthsTableRow.VisualProperties.ScaleFactor);
        if (maxFreq % 5 != 0)
          maxFreq += (5 - maxFreq % 5);
        double yAxisMaximumFixedValue = maxFreq;

        treeLengthsTable.VisualProperties.YAxisMaximumFixedValue = yAxisMaximumFixedValue;
        treeLengthsTable.VisualProperties.YAxisTitle = yAxisTitle;

        var results = ResultsParameter.ActualValue;

        if (!results.ContainsKey(treeLengthsTableRowName)) {
          results.Add(new Result(treeLengthsTableRowName, treeLengthsTable));
        } else {
          results[treeLengthsTableRowName].Value = treeLengthsTable;
        }

        bool storeHistory = StoreHistoryParameter.Value.Value;
        const string treeLengthHistoryTableName = "Tree lengths history";

        if (storeHistory) {
          var treeLengthsHistory = SymbolicExpressionTreeLengthsHistoryParameter.ActualValue;
          if (treeLengthsHistory == null) {
            treeLengthsHistory = new DataTableHistory();
            SymbolicExpressionTreeLengthsHistoryParameter.ActualValue = treeLengthsHistory;
          }
          treeLengthsHistory.Add((DataTable)treeLengthsTable.Clone());

          if (!results.ContainsKey(treeLengthHistoryTableName)) {
            results.Add(new Result(treeLengthHistoryTableName, treeLengthsHistory));
          } else {
            results[treeLengthHistoryTableName].Value = treeLengthsHistory;
          }
        }
      }
      return base.Apply();
    }
    public override IOperation Apply() {
      if (SimilarityParameter.ActualValue == null || SimilarityParameter.ActualValue.Value.IsAlmost(-1.0)) {
        UpdateCounter.Value++;
        if (UpdateCounter.Value != UpdateInterval.Value) return base.Apply();
        UpdateCounter.Value = 0;
        var trees = SymbolicExpressionTreeParameter.ActualValue.ToList();

        SimilarityParameter.ActualValue = new DoubleValue();

        var operations = new OperationCollection { Parallel = true };
        foreach (var tree in trees) {
          var op = new SymbolicDataAnalysisExpressionTreeSimilarityCalculator(DistanceCalculatorParameter.Value) {
            CurrentSymbolicExpressionTree = tree,
            MaximumTreeDepth = MaximumSymbolicExpressionTreeDepth.Value
          };
          var operation = ExecutionContext.CreateChildOperation(op, ExecutionContext.Scope);
          operations.Add(operation);
        }
        return new OperationCollection { operations, ExecutionContext.CreateOperation(this) };
      }

      var results = ResultsParameter.ActualValue;
      // population diversity
      DataTable populationDiversityTable;
      if (!results.ContainsKey("PopulationDiversity")) {
        populationDiversityTable = new DataTable("PopulationDiversity") { VisualProperties = { YAxisTitle = "Diversity" } };
        results.Add(new Result("PopulationDiversity", populationDiversityTable));
      }
      populationDiversityTable = (DataTable)results["PopulationDiversity"].Value;
      if (!populationDiversityTable.Rows.ContainsKey("Diversity"))
        populationDiversityTable.Rows.Add(new DataRow("Diversity") { VisualProperties = { StartIndexZero = true } });

      int length = SymbolicExpressionTreeParameter.ActualValue.Length;
      var similarity = SimilarityParameter.ActualValue.Value / (length * (length - 1) / 2.0);
      var diversity = 1 - similarity;
      SimilarityParameter.ActualValue.Value = -1.0;

      populationDiversityTable.Rows["Diversity"].Values.Add(diversity);

      return base.Apply();
    }
 private void AddValues(double[] x, DataTable dataTable) {
   if (!dataTable.Rows.Any()) {
     for (int i = 0; i < x.Length; i++) {
       var newRow = new DataRow("x" + i);
       newRow.Values.Add(x[i]);
       dataTable.Rows.Add(newRow);
     }
   } else {
     for (int i = 0; i < x.Length; i++) {
       dataTable.Rows.ElementAt(i).Values.Add(x[i]);
     }
   }
 }
    private void AddTypeSelectedForSimilarityTableEntry(StringValue[] typeSelectedForSimilarity) {
      if (!ResultCollection.ContainsKey(TypeSelectedForSimilarityParameterName)) {
        var newTable = new DataTable(TypeSelectedForSimilarityParameterName, "");
        newTable.VisualProperties.YAxisTitle = "Percentage";
        newTable.VisualProperties.YAxisMaximumAuto = false;

        ResultCollection.Add(new Result(TypeSelectedForSimilarityParameterName, newTable));
      }
      var table = ((DataTable)ResultCollection[TypeSelectedForSimilarityParameterName].Value);

      // all rows must have the same number of values so we can just take the first
      int numberOfValues = table.Rows.Select(r => r.Values.Count).DefaultIfEmpty().First();

      double count = typeSelectedForSimilarity.Count();
      var groupedValues = typeSelectedForSimilarity.Select(x => x.Value).GroupBy(x => x);
      foreach (var type in groupedValues) {
        if (!table.Rows.ContainsKey(type.Key)) {
          // initialize a new row for the symbol and pad with zeros
          DataRow row = new DataRow(type.Key, "", Enumerable.Repeat(0.0, numberOfValues));
          row.VisualProperties.StartIndexZero = true;
          table.Rows.Add(row);
        }
        table.Rows[type.Key].Values.Add(type.Count() / count * 100);
      }

      // add a zero for each data row that was not modified in the previous loop 
      foreach (var row in table.Rows.Where(r => r.Values.Count != numberOfValues + 1))
        row.Values.Add(0.0);
    }