Index: stable/HeuristicLab.Algorithms.DataAnalysis.Views/3.4/CrossValidationView.Designer.cs
===================================================================
--- stable/HeuristicLab.Algorithms.DataAnalysis.Views/3.4/CrossValidationView.Designer.cs	(revision 15149)
+++ stable/HeuristicLab.Algorithms.DataAnalysis.Views/3.4/CrossValidationView.Designer.cs	(revision 15150)
@@ -79,4 +79,5 @@
       this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
       this.splitContainer = new System.Windows.Forms.SplitContainer();
+      this.shuffleSamplesCheckBox = new System.Windows.Forms.CheckBox();
       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
       ((System.ComponentModel.ISupportInitialize)(this.foldsNumericUpDown)).BeginInit();
@@ -172,5 +173,5 @@
       // 
       this.foldsNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
-                  | System.Windows.Forms.AnchorStyles.Right)));
+            | System.Windows.Forms.AnchorStyles.Right)));
       this.foldsNumericUpDown.Location = new System.Drawing.Point(55, 26);
       this.foldsNumericUpDown.Maximum = new decimal(new int[] {
@@ -185,5 +186,5 @@
             0});
       this.foldsNumericUpDown.Name = "foldsNumericUpDown";
-      this.foldsNumericUpDown.Size = new System.Drawing.Size(248, 20);
+      this.foldsNumericUpDown.Size = new System.Drawing.Size(154, 20);
       this.foldsNumericUpDown.TabIndex = 3;
       this.foldsNumericUpDown.ThousandsSeparator = true;
@@ -208,5 +209,5 @@
       // 
       this.workersNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
-                  | System.Windows.Forms.AnchorStyles.Right)));
+            | System.Windows.Forms.AnchorStyles.Right)));
       this.workersNumericUpDown.Location = new System.Drawing.Point(55, 0);
       this.workersNumericUpDown.Maximum = new decimal(new int[] {
@@ -262,5 +263,5 @@
       // 
       this.samplesEndStringConvertibleValueView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
-                  | System.Windows.Forms.AnchorStyles.Right)));
+            | System.Windows.Forms.AnchorStyles.Right)));
       this.samplesEndStringConvertibleValueView.Caption = "StringConvertibleValue View";
       this.samplesEndStringConvertibleValueView.Content = null;
@@ -275,5 +276,5 @@
       // 
       this.samplesStartStringConvertibleValueView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
-                  | System.Windows.Forms.AnchorStyles.Right)));
+            | System.Windows.Forms.AnchorStyles.Right)));
       this.samplesStartStringConvertibleValueView.Caption = "StringConvertibleValue View";
       this.samplesStartStringConvertibleValueView.Content = null;
@@ -289,13 +290,13 @@
       this.tabControl.AllowDrop = true;
       this.tabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-                  | System.Windows.Forms.AnchorStyles.Left)
-                  | System.Windows.Forms.AnchorStyles.Right)));
+            | System.Windows.Forms.AnchorStyles.Left)
+            | System.Windows.Forms.AnchorStyles.Right)));
       this.tabControl.Controls.Add(this.algorithmTabPage);
       this.tabControl.Controls.Add(this.resultsTabPage);
       this.tabControl.Controls.Add(this.runsTabPage);
-      this.tabControl.Location = new System.Drawing.Point(0, 87);
+      this.tabControl.Location = new System.Drawing.Point(0, 115);
       this.tabControl.Name = "tabControl";
       this.tabControl.SelectedIndex = 0;
-      this.tabControl.Size = new System.Drawing.Size(616, 421);
+      this.tabControl.Size = new System.Drawing.Size(616, 393);
       this.tabControl.TabIndex = 4;
       // 
@@ -310,5 +311,5 @@
       this.algorithmTabPage.Name = "algorithmTabPage";
       this.algorithmTabPage.Padding = new System.Windows.Forms.Padding(3);
-      this.algorithmTabPage.Size = new System.Drawing.Size(608, 395);
+      this.algorithmTabPage.Size = new System.Drawing.Size(608, 367);
       this.algorithmTabPage.TabIndex = 0;
       this.algorithmTabPage.Text = "Algorithm";
@@ -321,5 +322,5 @@
       // 
       this.algorithmNamedItemView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
-                  | System.Windows.Forms.AnchorStyles.Right)));
+            | System.Windows.Forms.AnchorStyles.Right)));
       this.algorithmNamedItemView.Caption = "NamedItem View";
       this.algorithmNamedItemView.Content = null;
@@ -334,6 +335,6 @@
       this.algorithmTabControl.AllowDrop = true;
       this.algorithmTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-                  | System.Windows.Forms.AnchorStyles.Left)
-                  | System.Windows.Forms.AnchorStyles.Right)));
+            | System.Windows.Forms.AnchorStyles.Left)
+            | System.Windows.Forms.AnchorStyles.Right)));
       this.algorithmTabControl.Controls.Add(this.algorithmProblemTabPage);
       this.algorithmTabControl.Controls.Add(this.algorithmParametersTabPage);
@@ -341,5 +342,5 @@
       this.algorithmTabControl.Name = "algorithmTabControl";
       this.algorithmTabControl.SelectedIndex = 0;
-      this.algorithmTabControl.Size = new System.Drawing.Size(594, 324);
+      this.algorithmTabControl.Size = new System.Drawing.Size(594, 296);
       this.algorithmTabControl.TabIndex = 3;
       // 
@@ -353,5 +354,5 @@
       this.algorithmProblemTabPage.Name = "algorithmProblemTabPage";
       this.algorithmProblemTabPage.Padding = new System.Windows.Forms.Padding(3);
-      this.algorithmProblemTabPage.Size = new System.Drawing.Size(586, 298);
+      this.algorithmProblemTabPage.Size = new System.Drawing.Size(586, 270);
       this.algorithmProblemTabPage.TabIndex = 0;
       this.algorithmProblemTabPage.Text = "Problem";
@@ -375,6 +376,6 @@
       // 
       this.algorithmProblemViewHost.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-                  | System.Windows.Forms.AnchorStyles.Left)
-                  | System.Windows.Forms.AnchorStyles.Right)));
+            | System.Windows.Forms.AnchorStyles.Left)
+            | System.Windows.Forms.AnchorStyles.Right)));
       this.algorithmProblemViewHost.Caption = "View";
       this.algorithmProblemViewHost.Content = null;
@@ -383,5 +384,5 @@
       this.algorithmProblemViewHost.Name = "algorithmProblemViewHost";
       this.algorithmProblemViewHost.ReadOnly = false;
-      this.algorithmProblemViewHost.Size = new System.Drawing.Size(574, 256);
+      this.algorithmProblemViewHost.Size = new System.Drawing.Size(574, 228);
       this.algorithmProblemViewHost.TabIndex = 2;
       this.algorithmProblemViewHost.ViewsLabelVisible = true;
@@ -405,5 +406,5 @@
       this.algorithmParametersTabPage.Name = "algorithmParametersTabPage";
       this.algorithmParametersTabPage.Padding = new System.Windows.Forms.Padding(3);
-      this.algorithmParametersTabPage.Size = new System.Drawing.Size(586, 298);
+      this.algorithmParametersTabPage.Size = new System.Drawing.Size(586, 270);
       this.algorithmParametersTabPage.TabIndex = 1;
       this.algorithmParametersTabPage.Text = "Parameters";
@@ -412,4 +413,5 @@
       // algorithmParameterCollectionView
       // 
+      this.algorithmParameterCollectionView.AllowEditingOfHiddenParameters = true;
       this.algorithmParameterCollectionView.Caption = "ParameterCollection View";
       this.algorithmParameterCollectionView.Content = null;
@@ -418,5 +420,6 @@
       this.algorithmParameterCollectionView.Name = "algorithmParameterCollectionView";
       this.algorithmParameterCollectionView.ReadOnly = false;
-      this.algorithmParameterCollectionView.Size = new System.Drawing.Size(580, 292);
+      this.algorithmParameterCollectionView.ShowDetails = true;
+      this.algorithmParameterCollectionView.Size = new System.Drawing.Size(580, 264);
       this.algorithmParameterCollectionView.TabIndex = 0;
       // 
@@ -449,5 +452,5 @@
       this.resultsTabPage.Name = "resultsTabPage";
       this.resultsTabPage.Padding = new System.Windows.Forms.Padding(3);
-      this.resultsTabPage.Size = new System.Drawing.Size(608, 395);
+      this.resultsTabPage.Size = new System.Drawing.Size(608, 367);
       this.resultsTabPage.TabIndex = 1;
       this.resultsTabPage.Text = "Results";
@@ -462,5 +465,6 @@
       this.resultCollectionView.Name = "resultCollectionView";
       this.resultCollectionView.ReadOnly = true;
-      this.resultCollectionView.Size = new System.Drawing.Size(602, 389);
+      this.resultCollectionView.ShowDetails = true;
+      this.resultCollectionView.Size = new System.Drawing.Size(602, 361);
       this.resultCollectionView.TabIndex = 0;
       // 
@@ -472,5 +476,5 @@
       this.runsTabPage.Name = "runsTabPage";
       this.runsTabPage.Padding = new System.Windows.Forms.Padding(3);
-      this.runsTabPage.Size = new System.Drawing.Size(608, 395);
+      this.runsTabPage.Size = new System.Drawing.Size(608, 367);
       this.runsTabPage.TabIndex = 2;
       this.runsTabPage.Text = "Runs";
@@ -501,5 +505,5 @@
       this.runCollectionView.Name = "runCollectionView";
       this.runCollectionView.ReadOnly = false;
-      this.runCollectionView.Size = new System.Drawing.Size(602, 389);
+      this.runCollectionView.Size = new System.Drawing.Size(602, 361);
       this.runCollectionView.TabIndex = 0;
       // 
@@ -514,5 +518,5 @@
       // 
       this.splitContainer.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
-                  | System.Windows.Forms.AnchorStyles.Right)));
+            | System.Windows.Forms.AnchorStyles.Right)));
       this.splitContainer.Location = new System.Drawing.Point(0, 26);
       this.splitContainer.Name = "splitContainer";
@@ -520,4 +524,5 @@
       // splitContainer.Panel1
       // 
+      this.splitContainer.Panel1.Controls.Add(this.shuffleSamplesCheckBox);
       this.splitContainer.Panel1.Controls.Add(this.samplesEndStringConvertibleValueView);
       this.splitContainer.Panel1.Controls.Add(this.samplesStartStringConvertibleValueView);
@@ -531,11 +536,21 @@
       this.splitContainer.Panel2.Controls.Add(this.workersLabel);
       this.splitContainer.Panel2.Controls.Add(this.workersNumericUpDown);
-      this.splitContainer.Size = new System.Drawing.Size(616, 55);
+      this.splitContainer.Size = new System.Drawing.Size(616, 73);
       this.splitContainer.SplitterDistance = 306;
       this.splitContainer.TabIndex = 3;
       // 
+      // shuffleSamplesCheckBox
+      // 
+      this.shuffleSamplesCheckBox.AutoSize = true;
+      this.shuffleSamplesCheckBox.Location = new System.Drawing.Point(6, 52);
+      this.shuffleSamplesCheckBox.Name = "shuffleSamplesCheckBox";
+      this.shuffleSamplesCheckBox.Size = new System.Drawing.Size(102, 17);
+      this.shuffleSamplesCheckBox.TabIndex = 5;
+      this.shuffleSamplesCheckBox.Text = "Shuffle Samples";
+      this.shuffleSamplesCheckBox.UseVisualStyleBackColor = true;
+      this.shuffleSamplesCheckBox.CheckedChanged += new System.EventHandler(this.shuffleSamplesCheckBox_CheckedChanged);
+      // 
       // CrossValidationView
       // 
-      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
       this.Controls.Add(this.tabControl);
@@ -617,4 +632,5 @@
     private System.Windows.Forms.SplitContainer splitContainer;
     private Optimization.Views.ResultCollectionView resultCollectionView;
+    private System.Windows.Forms.CheckBox shuffleSamplesCheckBox;
   }
 }
Index: stable/HeuristicLab.Algorithms.DataAnalysis.Views/3.4/CrossValidationView.cs
===================================================================
--- stable/HeuristicLab.Algorithms.DataAnalysis.Views/3.4/CrossValidationView.cs	(revision 15149)
+++ stable/HeuristicLab.Algorithms.DataAnalysis.Views/3.4/CrossValidationView.cs	(revision 15150)
@@ -61,4 +61,5 @@
         runCollectionView.Content = null;
         storeAlgorithmInEachRunCheckBox.Checked = true;
+        shuffleSamplesCheckBox.Checked = false;
       } else {
         Locked = ReadOnly = Content.ExecutionState == ExecutionState.Started;
@@ -74,4 +75,5 @@
         executionTimeTextBox.Text = Content.ExecutionTime.ToString();
         storeAlgorithmInEachRunCheckBox.Checked = Content.StoreAlgorithmInEachRun;
+        shuffleSamplesCheckBox.Checked = Content.ShuffleSamples.Value;
       }
     }
@@ -137,4 +139,6 @@
           stopButton.Enabled = (Content.ExecutionState == ExecutionState.Started) || (Content.ExecutionState == ExecutionState.Paused);
           resetButton.Enabled = Content.ExecutionState != ExecutionState.Started;
+          // prevent changing the shuffle if the algorithm is not finished
+          shuffleSamplesCheckBox.Enabled = Content.ExecutionState == ExecutionState.Prepared;
         }
       }
@@ -197,4 +201,7 @@
 
     #region GUI events
+    private void shuffleSamplesCheckBox_CheckedChanged(object sender, EventArgs e) {
+      Content.ShuffleSamples.Value = shuffleSamplesCheckBox.Checked;
+    }
     private void foldsNumericUpDown_Validated(object sender, EventArgs e) {
       if (foldsNumericUpDown.Text == string.Empty)
@@ -238,6 +245,5 @@
         try {
           Content.Algorithm = (IAlgorithm)algorithmTypeSelectorDialog.TypeSelector.CreateInstanceOfSelectedType();
-        }
-        catch (Exception ex) {
+        } catch (Exception ex) {
           ErrorHandling.ShowErrorDialog(this, ex);
         }
@@ -250,5 +256,5 @@
         algorithmTabControl.Enabled = false;
 
-        ContentManager.LoadAsync(openFileDialog.FileName, delegate(IStorableContent content, Exception error) {
+        ContentManager.LoadAsync(openFileDialog.FileName, delegate (IStorableContent content, Exception error) {
           try {
             if (error != null) throw error;
@@ -258,10 +264,8 @@
             else
               Content.Algorithm = algorithm;
-          }
-          catch (Exception ex) {
+          } catch (Exception ex) {
             ErrorHandling.ShowErrorDialog(this, ex);
-          }
-          finally {
-            Invoke(new Action(delegate() {
+          } finally {
+            Invoke(new Action(delegate () {
               algorithmTabControl.Enabled = true;
             }));
@@ -289,5 +293,5 @@
         algorithmProblemViewHost.Enabled = false;
 
-        ContentManager.LoadAsync(openFileDialog.FileName, delegate(IStorableContent content, Exception error) {
+        ContentManager.LoadAsync(openFileDialog.FileName, delegate (IStorableContent content, Exception error) {
           try {
             if (error != null) throw error;
@@ -298,10 +302,8 @@
             else
               Content.Problem = problem;
-          }
-          catch (Exception ex) {
+          } catch (Exception ex) {
             Invoke(new Action(() => ErrorHandling.ShowErrorDialog(this, ex)));
-          }
-          finally {
-            Invoke(new Action(delegate() {
+          } finally {
+            Invoke(new Action(delegate () {
               algorithmProblemViewHost.Enabled = true;
               newProblemButton.Enabled = openProblemButton.Enabled = true;
@@ -357,5 +359,4 @@
     }
     #endregion
-
   }
 }
Index: stable/HeuristicLab.Algorithms.DataAnalysis/3.4/CrossValidation.cs
===================================================================
--- stable/HeuristicLab.Algorithms.DataAnalysis/3.4/CrossValidation.cs	(revision 15149)
+++ stable/HeuristicLab.Algorithms.DataAnalysis/3.4/CrossValidation.cs	(revision 15150)
@@ -33,4 +33,5 @@
 using HeuristicLab.Problems.DataAnalysis;
 using HeuristicLab.Problems.DataAnalysis.Symbolic;
+using HeuristicLab.Random;
 
 namespace HeuristicLab.Algorithms.DataAnalysis {
@@ -39,4 +40,7 @@
   [StorableClass]
   public sealed class CrossValidation : ParameterizedNamedItem, IAlgorithm, IStorableContent {
+    [Storable]
+    private int seed;
+
     public CrossValidation()
       : base() {
@@ -56,4 +60,5 @@
       samplesStart = new IntValue(0);
       samplesEnd = new IntValue(0);
+      shuffleSamples = new BoolValue(false);
       storeAlgorithmInEachRun = false;
 
@@ -71,4 +76,9 @@
     [StorableHook(HookType.AfterDeserialization)]
     private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (shuffleSamples == null) shuffleSamples = new BoolValue(false);
+      #endregion
+
       RegisterEvents();
       if (Algorithm != null) RegisterAlgorithmEvents();
@@ -89,4 +99,7 @@
       samplesStart = cloner.Clone(original.samplesStart);
       samplesEnd = cloner.Clone(original.samplesEnd);
+      shuffleSamples = cloner.Clone(original.shuffleSamples);
+      seed = original.seed;
+
       RegisterEvents();
       if (Algorithm != null) RegisterAlgorithmEvents();
@@ -170,5 +183,9 @@
       get { return results; }
     }
-
+    [Storable]
+    private BoolValue shuffleSamples;
+    public BoolValue ShuffleSamples {
+      get { return shuffleSamples; }
+    }
     [Storable]
     private IntValue folds;
@@ -270,11 +287,21 @@
         throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
 
+      seed = new FastRandom().NextInt();
+
       if (Algorithm != null) {
         //create cloned algorithms
         if (clonedAlgorithms.Count == 0) {
           int testSamplesCount = (SamplesEnd.Value - SamplesStart.Value) / Folds.Value;
-
+          IDataset shuffledDataset = null;
           for (int i = 0; i < Folds.Value; i++) {
-            IAlgorithm clonedAlgorithm = (IAlgorithm)algorithm.Clone();
+            var cloner = new Cloner();
+            if (ShuffleSamples.Value) {
+              var random = new FastRandom(seed);
+              var dataAnalysisProblem = (IDataAnalysisProblem)algorithm.Problem;
+              var dataset = (Dataset)dataAnalysisProblem.ProblemData.Dataset;
+              shuffledDataset = shuffledDataset ?? dataset.Shuffle(random);
+              cloner.RegisterClonedObject(dataset, shuffledDataset);
+            }
+            IAlgorithm clonedAlgorithm = cloner.Clone(Algorithm);
             clonedAlgorithm.Name = algorithm.Name + " Fold " + i;
             IDataAnalysisProblem problem = clonedAlgorithm.Problem as IDataAnalysisProblem;
@@ -422,4 +449,10 @@
         // clone manually to correctly clone references between cloned root objects 
         Cloner cloner = new Cloner();
+        if (ShuffleSamples.Value) {
+          var dataset = (Dataset)Problem.ProblemData.Dataset;
+          var random = new FastRandom(seed);
+          var shuffledDataset = dataset.Shuffle(random);
+          cloner.RegisterClonedObject(dataset, shuffledDataset);
+        }
         var problemDataClone = (IRegressionProblemData)cloner.Clone(Problem.ProblemData);
         // set partitions of problem data clone correctly
@@ -453,6 +486,10 @@
         // at least one algorithm (GBT with logistic regression loss) produces a classification solution even though the original problem is a regression problem.
         var targetVariable = solutions.Value.First().ProblemData.TargetVariable;
-        var problemDataClone = new ClassificationProblemData(Problem.ProblemData.Dataset,
-          Problem.ProblemData.AllowedInputVariables, targetVariable);
+        var dataset = (Dataset)Problem.ProblemData.Dataset;
+        if (ShuffleSamples.Value) {
+          var random = new FastRandom(seed);
+          dataset = dataset.Shuffle(random);
+        }
+        var problemDataClone = new ClassificationProblemData(dataset, Problem.ProblemData.AllowedInputVariables, targetVariable);
         // set partitions of problem data clone correctly
         problemDataClone.TrainingPartition.Start = SamplesStart.Value; problemDataClone.TrainingPartition.End = SamplesEnd.Value;
@@ -537,10 +574,14 @@
       algorithm.ProblemChanged += new EventHandler(Algorithm_ProblemChanged);
       algorithm.ExecutionStateChanged += new EventHandler(Algorithm_ExecutionStateChanged);
-      if (Problem != null) Problem.Reset += new EventHandler(Problem_Reset);
+      if (Problem != null) {
+        Problem.Reset += new EventHandler(Problem_Reset);
+      }
     }
     private void DeregisterAlgorithmEvents() {
       algorithm.ProblemChanged -= new EventHandler(Algorithm_ProblemChanged);
       algorithm.ExecutionStateChanged -= new EventHandler(Algorithm_ExecutionStateChanged);
-      if (Problem != null) Problem.Reset -= new EventHandler(Problem_Reset);
+      if (Problem != null) {
+        Problem.Reset -= new EventHandler(Problem_Reset);
+      }
     }
     private void Algorithm_ProblemChanged(object sender, EventArgs e) {
@@ -560,9 +601,7 @@
       ConfigureProblem();
     }
-
     private void Problem_Reset(object sender, EventArgs e) {
       ConfigureProblem();
     }
-
     private void ConfigureProblem() {
       SamplesStart.Value = 0;
@@ -590,9 +629,11 @@
     private void Algorithm_ExecutionStateChanged(object sender, EventArgs e) {
       switch (Algorithm.ExecutionState) {
-        case ExecutionState.Prepared: OnPrepared();
+        case ExecutionState.Prepared:
+          OnPrepared();
           break;
         case ExecutionState.Started: throw new InvalidOperationException("Algorithm template can not be started.");
         case ExecutionState.Paused: throw new InvalidOperationException("Algorithm template can not be paused.");
-        case ExecutionState.Stopped: OnStopped();
+        case ExecutionState.Stopped:
+          OnStopped();
           break;
       }
@@ -724,4 +765,5 @@
       AggregateResultValues(collectedResults);
       results.AddRange(collectedResults.Select(x => new Result(x.Key, x.Value)).Cast<IResult>().ToArray());
+      clonedAlgorithms.Clear();
       runsCounter++;
       runs.Add(new Run(string.Format("{0} Run {1}", Name, runsCounter), this));
Index: stable/HeuristicLab.Problems.DataAnalysis/3.4/Dataset.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis/3.4/Dataset.cs	(revision 15149)
+++ stable/HeuristicLab.Problems.DataAnalysis/3.4/Dataset.cs	(revision 15150)
@@ -126,4 +126,13 @@
       return new ModifiableDataset(variableNames, values);
     }
+    /// <summary>
+    /// Shuffle a dataset's rows
+    /// </summary>
+    /// <param name="random">Random number generator used for shuffling.</param>
+    /// <returns>A shuffled copy of the current dataset.</returns>
+    public Dataset Shuffle(IRandom random) {
+      var values = variableNames.Select(x => variableValues[x]).ToList();
+      return new Dataset(variableNames, values.ShuffleLists(random));
+    }
 
     protected Dataset(Dataset dataset) : this(dataset.variableNames, dataset.variableValues.Values) { }
