Changeset 15150


Ignore:
Timestamp:
07/06/17 11:39:20 (2 weeks ago)
Author:
gkronber
Message:

#2760: merged r14864, r14865, r14904, r15002, r15026, r15077, r15111 from trunk to stable

Location:
stable
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • stable/HeuristicLab.Algorithms.DataAnalysis.Views/3.4/CrossValidationView.Designer.cs

    r14186 r15150  
    7979      this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
    8080      this.splitContainer = new System.Windows.Forms.SplitContainer();
     81      this.shuffleSamplesCheckBox = new System.Windows.Forms.CheckBox();
    8182      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
    8283      ((System.ComponentModel.ISupportInitialize)(this.foldsNumericUpDown)).BeginInit();
     
    172173      //
    173174      this.foldsNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
    174                   | System.Windows.Forms.AnchorStyles.Right)));
     175            | System.Windows.Forms.AnchorStyles.Right)));
    175176      this.foldsNumericUpDown.Location = new System.Drawing.Point(55, 26);
    176177      this.foldsNumericUpDown.Maximum = new decimal(new int[] {
     
    185186            0});
    186187      this.foldsNumericUpDown.Name = "foldsNumericUpDown";
    187       this.foldsNumericUpDown.Size = new System.Drawing.Size(248, 20);
     188      this.foldsNumericUpDown.Size = new System.Drawing.Size(154, 20);
    188189      this.foldsNumericUpDown.TabIndex = 3;
    189190      this.foldsNumericUpDown.ThousandsSeparator = true;
     
    208209      //
    209210      this.workersNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
    210                   | System.Windows.Forms.AnchorStyles.Right)));
     211            | System.Windows.Forms.AnchorStyles.Right)));
    211212      this.workersNumericUpDown.Location = new System.Drawing.Point(55, 0);
    212213      this.workersNumericUpDown.Maximum = new decimal(new int[] {
     
    262263      //
    263264      this.samplesEndStringConvertibleValueView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
    264                   | System.Windows.Forms.AnchorStyles.Right)));
     265            | System.Windows.Forms.AnchorStyles.Right)));
    265266      this.samplesEndStringConvertibleValueView.Caption = "StringConvertibleValue View";
    266267      this.samplesEndStringConvertibleValueView.Content = null;
     
    275276      //
    276277      this.samplesStartStringConvertibleValueView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
    277                   | System.Windows.Forms.AnchorStyles.Right)));
     278            | System.Windows.Forms.AnchorStyles.Right)));
    278279      this.samplesStartStringConvertibleValueView.Caption = "StringConvertibleValue View";
    279280      this.samplesStartStringConvertibleValueView.Content = null;
     
    289290      this.tabControl.AllowDrop = true;
    290291      this.tabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
    291                   | System.Windows.Forms.AnchorStyles.Left)
    292                   | System.Windows.Forms.AnchorStyles.Right)));
     292            | System.Windows.Forms.AnchorStyles.Left)
     293            | System.Windows.Forms.AnchorStyles.Right)));
    293294      this.tabControl.Controls.Add(this.algorithmTabPage);
    294295      this.tabControl.Controls.Add(this.resultsTabPage);
    295296      this.tabControl.Controls.Add(this.runsTabPage);
    296       this.tabControl.Location = new System.Drawing.Point(0, 87);
     297      this.tabControl.Location = new System.Drawing.Point(0, 115);
    297298      this.tabControl.Name = "tabControl";
    298299      this.tabControl.SelectedIndex = 0;
    299       this.tabControl.Size = new System.Drawing.Size(616, 421);
     300      this.tabControl.Size = new System.Drawing.Size(616, 393);
    300301      this.tabControl.TabIndex = 4;
    301302      //
     
    310311      this.algorithmTabPage.Name = "algorithmTabPage";
    311312      this.algorithmTabPage.Padding = new System.Windows.Forms.Padding(3);
    312       this.algorithmTabPage.Size = new System.Drawing.Size(608, 395);
     313      this.algorithmTabPage.Size = new System.Drawing.Size(608, 367);
    313314      this.algorithmTabPage.TabIndex = 0;
    314315      this.algorithmTabPage.Text = "Algorithm";
     
    321322      //
    322323      this.algorithmNamedItemView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
    323                   | System.Windows.Forms.AnchorStyles.Right)));
     324            | System.Windows.Forms.AnchorStyles.Right)));
    324325      this.algorithmNamedItemView.Caption = "NamedItem View";
    325326      this.algorithmNamedItemView.Content = null;
     
    334335      this.algorithmTabControl.AllowDrop = true;
    335336      this.algorithmTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
    336                   | System.Windows.Forms.AnchorStyles.Left)
    337                   | System.Windows.Forms.AnchorStyles.Right)));
     337            | System.Windows.Forms.AnchorStyles.Left)
     338            | System.Windows.Forms.AnchorStyles.Right)));
    338339      this.algorithmTabControl.Controls.Add(this.algorithmProblemTabPage);
    339340      this.algorithmTabControl.Controls.Add(this.algorithmParametersTabPage);
     
    341342      this.algorithmTabControl.Name = "algorithmTabControl";
    342343      this.algorithmTabControl.SelectedIndex = 0;
    343       this.algorithmTabControl.Size = new System.Drawing.Size(594, 324);
     344      this.algorithmTabControl.Size = new System.Drawing.Size(594, 296);
    344345      this.algorithmTabControl.TabIndex = 3;
    345346      //
     
    353354      this.algorithmProblemTabPage.Name = "algorithmProblemTabPage";
    354355      this.algorithmProblemTabPage.Padding = new System.Windows.Forms.Padding(3);
    355       this.algorithmProblemTabPage.Size = new System.Drawing.Size(586, 298);
     356      this.algorithmProblemTabPage.Size = new System.Drawing.Size(586, 270);
    356357      this.algorithmProblemTabPage.TabIndex = 0;
    357358      this.algorithmProblemTabPage.Text = "Problem";
     
    375376      //
    376377      this.algorithmProblemViewHost.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
    377                   | System.Windows.Forms.AnchorStyles.Left)
    378                   | System.Windows.Forms.AnchorStyles.Right)));
     378            | System.Windows.Forms.AnchorStyles.Left)
     379            | System.Windows.Forms.AnchorStyles.Right)));
    379380      this.algorithmProblemViewHost.Caption = "View";
    380381      this.algorithmProblemViewHost.Content = null;
     
    383384      this.algorithmProblemViewHost.Name = "algorithmProblemViewHost";
    384385      this.algorithmProblemViewHost.ReadOnly = false;
    385       this.algorithmProblemViewHost.Size = new System.Drawing.Size(574, 256);
     386      this.algorithmProblemViewHost.Size = new System.Drawing.Size(574, 228);
    386387      this.algorithmProblemViewHost.TabIndex = 2;
    387388      this.algorithmProblemViewHost.ViewsLabelVisible = true;
     
    405406      this.algorithmParametersTabPage.Name = "algorithmParametersTabPage";
    406407      this.algorithmParametersTabPage.Padding = new System.Windows.Forms.Padding(3);
    407       this.algorithmParametersTabPage.Size = new System.Drawing.Size(586, 298);
     408      this.algorithmParametersTabPage.Size = new System.Drawing.Size(586, 270);
    408409      this.algorithmParametersTabPage.TabIndex = 1;
    409410      this.algorithmParametersTabPage.Text = "Parameters";
     
    412413      // algorithmParameterCollectionView
    413414      //
     415      this.algorithmParameterCollectionView.AllowEditingOfHiddenParameters = true;
    414416      this.algorithmParameterCollectionView.Caption = "ParameterCollection View";
    415417      this.algorithmParameterCollectionView.Content = null;
     
    418420      this.algorithmParameterCollectionView.Name = "algorithmParameterCollectionView";
    419421      this.algorithmParameterCollectionView.ReadOnly = false;
    420       this.algorithmParameterCollectionView.Size = new System.Drawing.Size(580, 292);
     422      this.algorithmParameterCollectionView.ShowDetails = true;
     423      this.algorithmParameterCollectionView.Size = new System.Drawing.Size(580, 264);
    421424      this.algorithmParameterCollectionView.TabIndex = 0;
    422425      //
     
    449452      this.resultsTabPage.Name = "resultsTabPage";
    450453      this.resultsTabPage.Padding = new System.Windows.Forms.Padding(3);
    451       this.resultsTabPage.Size = new System.Drawing.Size(608, 395);
     454      this.resultsTabPage.Size = new System.Drawing.Size(608, 367);
    452455      this.resultsTabPage.TabIndex = 1;
    453456      this.resultsTabPage.Text = "Results";
     
    462465      this.resultCollectionView.Name = "resultCollectionView";
    463466      this.resultCollectionView.ReadOnly = true;
    464       this.resultCollectionView.Size = new System.Drawing.Size(602, 389);
     467      this.resultCollectionView.ShowDetails = true;
     468      this.resultCollectionView.Size = new System.Drawing.Size(602, 361);
    465469      this.resultCollectionView.TabIndex = 0;
    466470      //
     
    472476      this.runsTabPage.Name = "runsTabPage";
    473477      this.runsTabPage.Padding = new System.Windows.Forms.Padding(3);
    474       this.runsTabPage.Size = new System.Drawing.Size(608, 395);
     478      this.runsTabPage.Size = new System.Drawing.Size(608, 367);
    475479      this.runsTabPage.TabIndex = 2;
    476480      this.runsTabPage.Text = "Runs";
     
    501505      this.runCollectionView.Name = "runCollectionView";
    502506      this.runCollectionView.ReadOnly = false;
    503       this.runCollectionView.Size = new System.Drawing.Size(602, 389);
     507      this.runCollectionView.Size = new System.Drawing.Size(602, 361);
    504508      this.runCollectionView.TabIndex = 0;
    505509      //
     
    514518      //
    515519      this.splitContainer.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
    516                   | System.Windows.Forms.AnchorStyles.Right)));
     520            | System.Windows.Forms.AnchorStyles.Right)));
    517521      this.splitContainer.Location = new System.Drawing.Point(0, 26);
    518522      this.splitContainer.Name = "splitContainer";
     
    520524      // splitContainer.Panel1
    521525      //
     526      this.splitContainer.Panel1.Controls.Add(this.shuffleSamplesCheckBox);
    522527      this.splitContainer.Panel1.Controls.Add(this.samplesEndStringConvertibleValueView);
    523528      this.splitContainer.Panel1.Controls.Add(this.samplesStartStringConvertibleValueView);
     
    531536      this.splitContainer.Panel2.Controls.Add(this.workersLabel);
    532537      this.splitContainer.Panel2.Controls.Add(this.workersNumericUpDown);
    533       this.splitContainer.Size = new System.Drawing.Size(616, 55);
     538      this.splitContainer.Size = new System.Drawing.Size(616, 73);
    534539      this.splitContainer.SplitterDistance = 306;
    535540      this.splitContainer.TabIndex = 3;
    536541      //
     542      // shuffleSamplesCheckBox
     543      //
     544      this.shuffleSamplesCheckBox.AutoSize = true;
     545      this.shuffleSamplesCheckBox.Location = new System.Drawing.Point(6, 52);
     546      this.shuffleSamplesCheckBox.Name = "shuffleSamplesCheckBox";
     547      this.shuffleSamplesCheckBox.Size = new System.Drawing.Size(102, 17);
     548      this.shuffleSamplesCheckBox.TabIndex = 5;
     549      this.shuffleSamplesCheckBox.Text = "Shuffle Samples";
     550      this.shuffleSamplesCheckBox.UseVisualStyleBackColor = true;
     551      this.shuffleSamplesCheckBox.CheckedChanged += new System.EventHandler(this.shuffleSamplesCheckBox_CheckedChanged);
     552      //
    537553      // CrossValidationView
    538554      //
    539       this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
    540555      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
    541556      this.Controls.Add(this.tabControl);
     
    617632    private System.Windows.Forms.SplitContainer splitContainer;
    618633    private Optimization.Views.ResultCollectionView resultCollectionView;
     634    private System.Windows.Forms.CheckBox shuffleSamplesCheckBox;
    619635  }
    620636}
  • stable/HeuristicLab.Algorithms.DataAnalysis.Views/3.4/CrossValidationView.cs

    r14186 r15150  
    6161        runCollectionView.Content = null;
    6262        storeAlgorithmInEachRunCheckBox.Checked = true;
     63        shuffleSamplesCheckBox.Checked = false;
    6364      } else {
    6465        Locked = ReadOnly = Content.ExecutionState == ExecutionState.Started;
     
    7475        executionTimeTextBox.Text = Content.ExecutionTime.ToString();
    7576        storeAlgorithmInEachRunCheckBox.Checked = Content.StoreAlgorithmInEachRun;
     77        shuffleSamplesCheckBox.Checked = Content.ShuffleSamples.Value;
    7678      }
    7779    }
     
    137139          stopButton.Enabled = (Content.ExecutionState == ExecutionState.Started) || (Content.ExecutionState == ExecutionState.Paused);
    138140          resetButton.Enabled = Content.ExecutionState != ExecutionState.Started;
     141          // prevent changing the shuffle if the algorithm is not finished
     142          shuffleSamplesCheckBox.Enabled = Content.ExecutionState == ExecutionState.Prepared;
    139143        }
    140144      }
     
    197201
    198202    #region GUI events
     203    private void shuffleSamplesCheckBox_CheckedChanged(object sender, EventArgs e) {
     204      Content.ShuffleSamples.Value = shuffleSamplesCheckBox.Checked;
     205    }
    199206    private void foldsNumericUpDown_Validated(object sender, EventArgs e) {
    200207      if (foldsNumericUpDown.Text == string.Empty)
     
    238245        try {
    239246          Content.Algorithm = (IAlgorithm)algorithmTypeSelectorDialog.TypeSelector.CreateInstanceOfSelectedType();
    240         }
    241         catch (Exception ex) {
     247        } catch (Exception ex) {
    242248          ErrorHandling.ShowErrorDialog(this, ex);
    243249        }
     
    250256        algorithmTabControl.Enabled = false;
    251257
    252         ContentManager.LoadAsync(openFileDialog.FileName, delegate(IStorableContent content, Exception error) {
     258        ContentManager.LoadAsync(openFileDialog.FileName, delegate (IStorableContent content, Exception error) {
    253259          try {
    254260            if (error != null) throw error;
     
    258264            else
    259265              Content.Algorithm = algorithm;
    260           }
    261           catch (Exception ex) {
     266          } catch (Exception ex) {
    262267            ErrorHandling.ShowErrorDialog(this, ex);
    263           }
    264           finally {
    265             Invoke(new Action(delegate() {
     268          } finally {
     269            Invoke(new Action(delegate () {
    266270              algorithmTabControl.Enabled = true;
    267271            }));
     
    289293        algorithmProblemViewHost.Enabled = false;
    290294
    291         ContentManager.LoadAsync(openFileDialog.FileName, delegate(IStorableContent content, Exception error) {
     295        ContentManager.LoadAsync(openFileDialog.FileName, delegate (IStorableContent content, Exception error) {
    292296          try {
    293297            if (error != null) throw error;
     
    298302            else
    299303              Content.Problem = problem;
    300           }
    301           catch (Exception ex) {
     304          } catch (Exception ex) {
    302305            Invoke(new Action(() => ErrorHandling.ShowErrorDialog(this, ex)));
    303           }
    304           finally {
    305             Invoke(new Action(delegate() {
     306          } finally {
     307            Invoke(new Action(delegate () {
    306308              algorithmProblemViewHost.Enabled = true;
    307309              newProblemButton.Enabled = openProblemButton.Enabled = true;
     
    357359    }
    358360    #endregion
    359 
    360361  }
    361362}
  • stable/HeuristicLab.Algorithms.DataAnalysis/3.4/CrossValidation.cs

    r15149 r15150  
    3333using HeuristicLab.Problems.DataAnalysis;
    3434using HeuristicLab.Problems.DataAnalysis.Symbolic;
     35using HeuristicLab.Random;
    3536
    3637namespace HeuristicLab.Algorithms.DataAnalysis {
     
    3940  [StorableClass]
    4041  public sealed class CrossValidation : ParameterizedNamedItem, IAlgorithm, IStorableContent {
     42    [Storable]
     43    private int seed;
     44
    4145    public CrossValidation()
    4246      : base() {
     
    5660      samplesStart = new IntValue(0);
    5761      samplesEnd = new IntValue(0);
     62      shuffleSamples = new BoolValue(false);
    5863      storeAlgorithmInEachRun = false;
    5964
     
    7176    [StorableHook(HookType.AfterDeserialization)]
    7277    private void AfterDeserialization() {
     78      // BackwardsCompatibility3.3
     79      #region Backwards compatible code, remove with 3.4
     80      if (shuffleSamples == null) shuffleSamples = new BoolValue(false);
     81      #endregion
     82
    7383      RegisterEvents();
    7484      if (Algorithm != null) RegisterAlgorithmEvents();
     
    8999      samplesStart = cloner.Clone(original.samplesStart);
    90100      samplesEnd = cloner.Clone(original.samplesEnd);
     101      shuffleSamples = cloner.Clone(original.shuffleSamples);
     102      seed = original.seed;
     103
    91104      RegisterEvents();
    92105      if (Algorithm != null) RegisterAlgorithmEvents();
     
    170183      get { return results; }
    171184    }
    172 
     185    [Storable]
     186    private BoolValue shuffleSamples;
     187    public BoolValue ShuffleSamples {
     188      get { return shuffleSamples; }
     189    }
    173190    [Storable]
    174191    private IntValue folds;
     
    270287        throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
    271288
     289      seed = new FastRandom().NextInt();
     290
    272291      if (Algorithm != null) {
    273292        //create cloned algorithms
    274293        if (clonedAlgorithms.Count == 0) {
    275294          int testSamplesCount = (SamplesEnd.Value - SamplesStart.Value) / Folds.Value;
    276 
     295          IDataset shuffledDataset = null;
    277296          for (int i = 0; i < Folds.Value; i++) {
    278             IAlgorithm clonedAlgorithm = (IAlgorithm)algorithm.Clone();
     297            var cloner = new Cloner();
     298            if (ShuffleSamples.Value) {
     299              var random = new FastRandom(seed);
     300              var dataAnalysisProblem = (IDataAnalysisProblem)algorithm.Problem;
     301              var dataset = (Dataset)dataAnalysisProblem.ProblemData.Dataset;
     302              shuffledDataset = shuffledDataset ?? dataset.Shuffle(random);
     303              cloner.RegisterClonedObject(dataset, shuffledDataset);
     304            }
     305            IAlgorithm clonedAlgorithm = cloner.Clone(Algorithm);
    279306            clonedAlgorithm.Name = algorithm.Name + " Fold " + i;
    280307            IDataAnalysisProblem problem = clonedAlgorithm.Problem as IDataAnalysisProblem;
     
    422449        // clone manually to correctly clone references between cloned root objects
    423450        Cloner cloner = new Cloner();
     451        if (ShuffleSamples.Value) {
     452          var dataset = (Dataset)Problem.ProblemData.Dataset;
     453          var random = new FastRandom(seed);
     454          var shuffledDataset = dataset.Shuffle(random);
     455          cloner.RegisterClonedObject(dataset, shuffledDataset);
     456        }
    424457        var problemDataClone = (IRegressionProblemData)cloner.Clone(Problem.ProblemData);
    425458        // set partitions of problem data clone correctly
     
    453486        // at least one algorithm (GBT with logistic regression loss) produces a classification solution even though the original problem is a regression problem.
    454487        var targetVariable = solutions.Value.First().ProblemData.TargetVariable;
    455         var problemDataClone = new ClassificationProblemData(Problem.ProblemData.Dataset,
    456           Problem.ProblemData.AllowedInputVariables, targetVariable);
     488        var dataset = (Dataset)Problem.ProblemData.Dataset;
     489        if (ShuffleSamples.Value) {
     490          var random = new FastRandom(seed);
     491          dataset = dataset.Shuffle(random);
     492        }
     493        var problemDataClone = new ClassificationProblemData(dataset, Problem.ProblemData.AllowedInputVariables, targetVariable);
    457494        // set partitions of problem data clone correctly
    458495        problemDataClone.TrainingPartition.Start = SamplesStart.Value; problemDataClone.TrainingPartition.End = SamplesEnd.Value;
     
    537574      algorithm.ProblemChanged += new EventHandler(Algorithm_ProblemChanged);
    538575      algorithm.ExecutionStateChanged += new EventHandler(Algorithm_ExecutionStateChanged);
    539       if (Problem != null) Problem.Reset += new EventHandler(Problem_Reset);
     576      if (Problem != null) {
     577        Problem.Reset += new EventHandler(Problem_Reset);
     578      }
    540579    }
    541580    private void DeregisterAlgorithmEvents() {
    542581      algorithm.ProblemChanged -= new EventHandler(Algorithm_ProblemChanged);
    543582      algorithm.ExecutionStateChanged -= new EventHandler(Algorithm_ExecutionStateChanged);
    544       if (Problem != null) Problem.Reset -= new EventHandler(Problem_Reset);
     583      if (Problem != null) {
     584        Problem.Reset -= new EventHandler(Problem_Reset);
     585      }
    545586    }
    546587    private void Algorithm_ProblemChanged(object sender, EventArgs e) {
     
    560601      ConfigureProblem();
    561602    }
    562 
    563603    private void Problem_Reset(object sender, EventArgs e) {
    564604      ConfigureProblem();
    565605    }
    566 
    567606    private void ConfigureProblem() {
    568607      SamplesStart.Value = 0;
     
    590629    private void Algorithm_ExecutionStateChanged(object sender, EventArgs e) {
    591630      switch (Algorithm.ExecutionState) {
    592         case ExecutionState.Prepared: OnPrepared();
     631        case ExecutionState.Prepared:
     632          OnPrepared();
    593633          break;
    594634        case ExecutionState.Started: throw new InvalidOperationException("Algorithm template can not be started.");
    595635        case ExecutionState.Paused: throw new InvalidOperationException("Algorithm template can not be paused.");
    596         case ExecutionState.Stopped: OnStopped();
     636        case ExecutionState.Stopped:
     637          OnStopped();
    597638          break;
    598639      }
     
    724765      AggregateResultValues(collectedResults);
    725766      results.AddRange(collectedResults.Select(x => new Result(x.Key, x.Value)).Cast<IResult>().ToArray());
     767      clonedAlgorithms.Clear();
    726768      runsCounter++;
    727769      runs.Add(new Run(string.Format("{0} Run {1}", Name, runsCounter), this));
  • stable/HeuristicLab.Problems.DataAnalysis/3.4/Dataset.cs

    r15131 r15150  
    126126      return new ModifiableDataset(variableNames, values);
    127127    }
     128    /// <summary>
     129    /// Shuffle a dataset's rows
     130    /// </summary>
     131    /// <param name="random">Random number generator used for shuffling.</param>
     132    /// <returns>A shuffled copy of the current dataset.</returns>
     133    public Dataset Shuffle(IRandom random) {
     134      var values = variableNames.Select(x => variableValues[x]).ToList();
     135      return new Dataset(variableNames, values.ShuffleLists(random));
     136    }
    128137
    129138    protected Dataset(Dataset dataset) : this(dataset.variableNames, dataset.variableValues.Values) { }
Note: See TracChangeset for help on using the changeset viewer.