Index: branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks.Views/3.3/DirectedGraphChart.cs
===================================================================
--- branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks.Views/3.3/DirectedGraphChart.cs	(revision 13789)
+++ branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks.Views/3.3/DirectedGraphChart.cs	(revision 13806)
@@ -90,5 +90,5 @@
       get { return graph; }
       set {
-        if (value == null || graph == value) return;
+        if (value == null || graph == value || !value.Vertices.Any()) return;
         graph = value;
         Draw();
Index: branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks.Views/3.3/RunCollectionVariableInteractionNetworkView.cs
===================================================================
--- branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks.Views/3.3/RunCollectionVariableInteractionNetworkView.cs	(revision 13789)
+++ branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks.Views/3.3/RunCollectionVariableInteractionNetworkView.cs	(revision 13806)
@@ -269,4 +269,20 @@
     }
 
+    private static VariableInteractionNetwork ApplyThreshold(VariableInteractionNetwork originalNetwork, double threshold) {
+      var arcs = originalNetwork.Arcs.Where(x => x.Weight >= threshold).ToList();
+      if (!arcs.Any()) return originalNetwork;
+      var filteredNetwork = new VariableInteractionNetwork();
+      var cloner = new Cloner();
+      var vertices = arcs.SelectMany(x => new[] { x.Source, x.Target }).Select(cloner.Clone).Distinct(); // arcs are not cloned
+      filteredNetwork.AddVertices(vertices);
+      filteredNetwork.AddArcs(arcs.Select(x => (IArc)x.Clone(cloner)));
+
+      var unusedJunctions = filteredNetwork.Vertices.Where(x => x.InDegree == 0 && x is JunctionNetworkNode).ToList();
+      filteredNetwork.RemoveVertices(unusedJunctions);
+      var orphanedNodes = filteredNetwork.Vertices.Where(x => x.Degree == 0).ToList();
+      filteredNetwork.RemoveVertices(orphanedNodes);
+      return filteredNetwork.Vertices.Any() ? filteredNetwork : originalNetwork;
+    }
+
     private static double CalculateAverageQuality(RunCollection runs) {
       var pd = (IRegressionProblemData)runs.First().Parameters["ProblemData"];
@@ -374,22 +390,9 @@
       var tb = (TextBox)sender;
       errorProvider.SetError(tb, string.Empty);
-      var network = ApplyThreshold(variableInteractionNetwork, double.Parse(tb.Text));
+      double impact;
+      if (!double.TryParse(tb.Text, out impact))
+        impact = 0.1;
+      var network = ApplyThreshold(variableInteractionNetwork, impact);
       graphChart.Graph = network;
-    }
-
-    private static VariableInteractionNetwork ApplyThreshold(VariableInteractionNetwork originalNetwork, double threshold) {
-      var arcs = originalNetwork.Arcs.Where(x => x.Weight >= threshold).ToList();
-      if (!arcs.Any()) return originalNetwork;
-      var filteredNetwork = new VariableInteractionNetwork();
-      var cloner = new Cloner();
-      var vertices = arcs.SelectMany(x => new[] { x.Source, x.Target }).Select(cloner.Clone).Distinct(); // arcs are not cloned
-      filteredNetwork.AddVertices(vertices);
-      filteredNetwork.AddArcs(arcs.Select(x => (IArc)x.Clone(cloner)));
-
-      var unusedJunctions = filteredNetwork.Vertices.Where(x => x.InDegree == 0 && x is JunctionNetworkNode).ToList();
-      filteredNetwork.RemoveVertices(unusedJunctions);
-      var orphanedNodes = filteredNetwork.Vertices.Where(x => x.Degree == 0).ToList();
-      filteredNetwork.RemoveVertices(orphanedNodes);
-      return filteredNetwork;
     }
 
Index: branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks/3.3/CreateTargetVariationExperiment.cs
===================================================================
--- branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks/3.3/CreateTargetVariationExperiment.cs	(revision 13789)
+++ branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks/3.3/CreateTargetVariationExperiment.cs	(revision 13806)
@@ -26,4 +26,5 @@
 using HeuristicLab.Optimization;
 using HeuristicLab.Optimizer;
+using HeuristicLab.Problems.DataAnalysis;
 
 namespace HeuristicLab.VariableInteractionNetworks {
@@ -47,5 +48,14 @@
     protected override void OnActiveViewChanged(object sender, EventArgs e) {
       IContentView activeView = MainFormManager.MainForm.ActiveView as IContentView;
-      ToolStripItem.Enabled = (activeView != null) && (activeView.Content != null) && (activeView.Content is IOptimizer) && !activeView.Locked;
+      bool enabled = false;
+      if (activeView != null && !activeView.Locked && activeView.Content != null) {
+        var algorithm = activeView.Content as IAlgorithm;
+        if (algorithm != null) {
+          var problem = algorithm.Problem;
+          // make sure the problem data specifies a target variable
+          enabled = problem is IRegressionProblem || problem is IClassificationProblem;
+        }
+      }
+      ToolStripItem.Enabled = enabled;
     }
 
Index: branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks/3.3/CreateTargetVariationExperimentDialog.Designer.cs
===================================================================
--- branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks/3.3/CreateTargetVariationExperimentDialog.Designer.cs	(revision 13789)
+++ branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks/3.3/CreateTargetVariationExperimentDialog.Designer.cs	(revision 13806)
@@ -33,9 +33,9 @@
       this.cancelButton = new System.Windows.Forms.Button();
       this.okButton = new System.Windows.Forms.Button();
-      this.binomialCoeffNumericUpDown = new System.Windows.Forms.NumericUpDown();
+      this.combinationGroupSizeNumericUpDown = new System.Windows.Forms.NumericUpDown();
       this.label1 = new System.Windows.Forms.Label();
-      this.label2 = new System.Windows.Forms.Label();
+      this.warningLabel = new System.Windows.Forms.Label();
       ((System.ComponentModel.ISupportInitialize)(this.repetitionsNumericUpDown)).BeginInit();
-      ((System.ComponentModel.ISupportInitialize)(this.binomialCoeffNumericUpDown)).BeginInit();
+      ((System.ComponentModel.ISupportInitialize)(this.combinationGroupSizeNumericUpDown)).BeginInit();
       this.SuspendLayout();
       // 
@@ -98,29 +98,31 @@
       this.okButton.Click += new System.EventHandler(this.okButton_Click);
       // 
-      // binomialCoeffNumericUpDown
+      // combinationGroupSizeNumericUpDown
       // 
-      this.binomialCoeffNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+      this.combinationGroupSizeNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
-      this.binomialCoeffNumericUpDown.Location = new System.Drawing.Point(128, 38);
-      this.binomialCoeffNumericUpDown.Maximum = new decimal(new int[] {
+      this.combinationGroupSizeNumericUpDown.Location = new System.Drawing.Point(128, 38);
+      this.combinationGroupSizeNumericUpDown.Maximum = new decimal(new int[] {
             1000000,
             0,
             0,
             0});
-      this.binomialCoeffNumericUpDown.Minimum = new decimal(new int[] {
+      this.combinationGroupSizeNumericUpDown.Minimum = new decimal(new int[] {
             1,
             0,
             0,
             0});
-      this.binomialCoeffNumericUpDown.Name = "binomialCoeffNumericUpDown";
-      this.binomialCoeffNumericUpDown.Size = new System.Drawing.Size(185, 20);
-      this.binomialCoeffNumericUpDown.TabIndex = 4;
-      this.binomialCoeffNumericUpDown.ThousandsSeparator = true;
-      this.binomialCoeffNumericUpDown.Value = new decimal(new int[] {
+      this.combinationGroupSizeNumericUpDown.Name = "combinationGroupSizeNumericUpDown";
+      this.combinationGroupSizeNumericUpDown.Size = new System.Drawing.Size(185, 20);
+      this.combinationGroupSizeNumericUpDown.TabIndex = 4;
+      this.combinationGroupSizeNumericUpDown.ThousandsSeparator = true;
+      this.combinationGroupSizeNumericUpDown.Value = new decimal(new int[] {
             10,
             0,
             0,
             0});
-      this.binomialCoeffNumericUpDown.Validated += new System.EventHandler(this.binomialCoefficientNumericUpDown_Validated);
+      this.combinationGroupSizeNumericUpDown.ValueChanged += new System.EventHandler(this.combinationGroupSizeNumericUpDown_Validated);
+      this.combinationGroupSizeNumericUpDown.Validating += new System.ComponentModel.CancelEventHandler(this.combinationGroupSizeNumericUpDown_Validating);
+      this.combinationGroupSizeNumericUpDown.Validated += new System.EventHandler(this.combinationGroupSizeNumericUpDown_Validated);
       // 
       // label1
@@ -129,17 +131,16 @@
       this.label1.Location = new System.Drawing.Point(26, 40);
       this.label1.Name = "label1";
-      this.label1.Size = new System.Drawing.Size(79, 13);
+      this.label1.Size = new System.Drawing.Size(60, 13);
       this.label1.TabIndex = 5;
-      this.label1.Text = "&Binomial coeff.:";
+      this.label1.Text = "&Group size:";
       // 
-      // label2
+      // warningLabel
       // 
-      this.label2.ForeColor = System.Drawing.Color.Red;
-      this.label2.Location = new System.Drawing.Point(26, 67);
-      this.label2.Name = "label2";
-      this.label2.Size = new System.Drawing.Size(287, 50);
-      this.label2.TabIndex = 5;
-      this.label2.Text = "Warning: depending on the binomial coefficient and the number of variables, this " +
-    "can create very large experiments. ";
+      this.warningLabel.ForeColor = System.Drawing.Color.Red;
+      this.warningLabel.Location = new System.Drawing.Point(26, 67);
+      this.warningLabel.Name = "warningLabel";
+      this.warningLabel.Size = new System.Drawing.Size(287, 50);
+      this.warningLabel.TabIndex = 5;
+      this.warningLabel.TextAlign = System.Drawing.ContentAlignment.TopCenter;
       // 
       // CreateTargetVariationExperimentDialog
@@ -152,13 +153,13 @@
       this.Controls.Add(this.okButton);
       this.Controls.Add(this.cancelButton);
-      this.Controls.Add(this.label2);
+      this.Controls.Add(this.warningLabel);
       this.Controls.Add(this.label1);
       this.Controls.Add(this.repetitionsLabel);
-      this.Controls.Add(this.binomialCoeffNumericUpDown);
+      this.Controls.Add(this.combinationGroupSizeNumericUpDown);
       this.Controls.Add(this.repetitionsNumericUpDown);
       this.Name = "CreateTargetVariationExperimentDialog";
       this.Text = "Create Target Variation Experiment";
       ((System.ComponentModel.ISupportInitialize)(this.repetitionsNumericUpDown)).EndInit();
-      ((System.ComponentModel.ISupportInitialize)(this.binomialCoeffNumericUpDown)).EndInit();
+      ((System.ComponentModel.ISupportInitialize)(this.combinationGroupSizeNumericUpDown)).EndInit();
       this.ResumeLayout(false);
       this.PerformLayout();
@@ -172,7 +173,7 @@
         private System.Windows.Forms.Button cancelButton;
         private System.Windows.Forms.Button okButton;
-    private System.Windows.Forms.NumericUpDown binomialCoeffNumericUpDown;
+    private System.Windows.Forms.NumericUpDown combinationGroupSizeNumericUpDown;
     private System.Windows.Forms.Label label1;
-    private System.Windows.Forms.Label label2;
+    private System.Windows.Forms.Label warningLabel;
   }
 }
Index: branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks/3.3/CreateTargetVariationExperimentDialog.cs
===================================================================
--- branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks/3.3/CreateTargetVariationExperimentDialog.cs	(revision 13789)
+++ branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks/3.3/CreateTargetVariationExperimentDialog.cs	(revision 13806)
@@ -24,4 +24,5 @@
 using System.Linq;
 using System.Windows.Forms;
+using HeuristicLab.Common;
 using HeuristicLab.MainForm;
 using HeuristicLab.Optimization;
@@ -32,5 +33,5 @@
     public Experiment Experiment { get; private set; }
     private int repetitions;
-    private int binomialCoefficient;
+    private int combinationGroupSize;
 
     public CreateTargetVariationExperimentDialog() : this(null) { }
@@ -38,19 +39,14 @@
       InitializeComponent();
       repetitions = (int)repetitionsNumericUpDown.Value;
+      combinationGroupSize = (int)combinationGroupSizeNumericUpDown.Value;
+
+      var problem = alg.Problem as IDataAnalysisProblem;
+      var inputCount = problem.ProblemData.AllowedInputVariables.Count();
+      if (combinationGroupSize > inputCount)
+        combinationGroupSize = inputCount;
+      warningLabel.Text = string.Format("Warning: this will create {0} combinations.", EnumerableExtensions.BinomialCoefficient(inputCount, combinationGroupSize));
 
       Experiment = null;
       okButton.Enabled = alg != null;
-    }
-
-    private void repetitionsNumericUpDown_Validated(object sender, EventArgs e) {
-      if (repetitionsNumericUpDown.Text == string.Empty)
-        repetitionsNumericUpDown.Text = repetitionsNumericUpDown.Value.ToString();
-      repetitions = (int)repetitionsNumericUpDown.Value;
-    }
-
-    private void binomialCoefficientNumericUpDown_Validated(object sender, EventArgs e) {
-      if (binomialCoeffNumericUpDown.Text == string.Empty)
-        binomialCoeffNumericUpDown.Text = binomialCoeffNumericUpDown.Value.ToString();
-      binomialCoefficient = (int)binomialCoeffNumericUpDown.Value;
     }
 
@@ -61,26 +57,27 @@
         throw new ArgumentNullException("The algorithm parameter must be a valid IAlgorithm instance.");
 
-      var regressionProblem = algorithm.Problem as IRegressionProblem;
-      if (regressionProblem == null)
-        throw new ArgumentNullException("The algorithm does not contain a valid problem instance.");
+      var problem = (IDataAnalysisProblem)algorithm.Problem;
+      var problemData = problem.ProblemData;
 
-      var problemData = regressionProblem.ProblemData;
-      var variables = problemData.Dataset.DoubleVariables.ToList();
+      var variables = problemData.AllowedInputVariables.ToList();
 
       for (int i = 0; i < variables.Count; i++) {
         var target = variables[i];
         var inputs = variables.Where(x => x != target).ToList();
-        var combinations = Util.Combinations(inputs, binomialCoefficient);
+        if (combinationGroupSize > inputs.Count)
+          combinationGroupSize = inputs.Count;
+
+        var combinations = inputs.Combinations(combinationGroupSize);
 
         foreach (var combination in combinations) {
           var h = new HashSet<string>(combination);
           var alg = (IAlgorithm)algorithm.Clone();
-          var pd = ((IRegressionProblem)alg.Problem).ProblemData;
-          pd.TargetVariable = target;
-          alg.Name += "{Target = " + target + ", Inputs = (" + combination.Aggregate((a, b) => a + "," + b) + ")}";
-
-          foreach (var item in pd.InputVariables) {
-            pd.InputVariables.SetItemCheckedState(item, h.Contains(item.Value));
+          alg.Name += " {Target = " + target + ", Inputs = (" + combination.Aggregate((a, b) => a + "," + b) + ")}";
+          problem = (IDataAnalysisProblem)alg.Problem;
+          problemData = problem.ProblemData;
+          foreach (var item in problemData.InputVariables) {
+            problemData.InputVariables.SetItemCheckedState(item, h.Contains(item.Value));
           }
+          SetTargetName(problemData, target);
 
           var batchrun = new BatchRun(string.Format("Batchrun {0}", i + 1)) {
@@ -95,7 +92,32 @@
     }
 
+    private static string GetTargetName(IDataAnalysisProblemData problemData) {
+      var regressionProblemData = problemData as IRegressionProblemData;
+      if (regressionProblemData != null)
+        return regressionProblemData.TargetVariable;
+      var classificationProblemData = problemData as IClassificationProblemData;
+      if (classificationProblemData != null)
+        return classificationProblemData.TargetVariable;
+      throw new ArgumentException("The provided argument must be either a regression or classification problem data.");
+    }
+
+    private static void SetTargetName(IDataAnalysisProblemData problemData, string targetName) {
+      var regressionProblemData = problemData as IRegressionProblemData;
+      if (regressionProblemData != null) {
+        regressionProblemData.TargetVariable = targetName;
+        return;
+      }
+      var classificationProblemData = problemData as IClassificationProblemData;
+      if (classificationProblemData != null) {
+        classificationProblemData.TargetVariable = targetName;
+        return;
+      }
+      throw new ArgumentException("The provided argument must be either a regression or classification problem data.");
+    }
+
+    #region events
     private void okButton_Click(object sender, EventArgs e) {
       IContentView activeView = MainFormManager.MainForm.ActiveView as IContentView;
-      if ((activeView != null) && (activeView.Content != null) && (activeView.Content is IOptimizer) && !activeView.Locked) {
+      if ((activeView != null) && (activeView.Content != null) && (activeView.Content is IAlgorithm) && !activeView.Locked) {
         Experiment = CreateVariableCombinations((IAlgorithm)activeView.Content);
         DialogResult = DialogResult.OK;
@@ -103,4 +125,34 @@
       }
     }
+
+    private void combinationGroupSizeNumericUpDown_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      IContentView activeView = MainFormManager.MainForm.ActiveView as IContentView;
+      if (activeView == null) return;
+      var algorithm = (IAlgorithm)activeView.Content;
+      var problem = algorithm.Problem as IDataAnalysisProblem;
+      if (problem == null) return;
+      var inputCount = problem.ProblemData.AllowedInputVariables.Count();
+      if (combinationGroupSizeNumericUpDown.Value > inputCount)
+        combinationGroupSizeNumericUpDown.Value = inputCount;
+    }
+
+    private void repetitionsNumericUpDown_Validated(object sender, EventArgs e) {
+      if (repetitionsNumericUpDown.Text == string.Empty)
+        repetitionsNumericUpDown.Text = repetitionsNumericUpDown.Value.ToString();
+      repetitions = (int)repetitionsNumericUpDown.Value;
+    }
+
+    private void combinationGroupSizeNumericUpDown_Validated(object sender, EventArgs e) {
+      if (combinationGroupSizeNumericUpDown.Text == string.Empty)
+        combinationGroupSizeNumericUpDown.Text = combinationGroupSizeNumericUpDown.Value.ToString();
+      combinationGroupSize = (int)combinationGroupSizeNumericUpDown.Value;
+      IContentView activeView = MainFormManager.MainForm.ActiveView as IContentView;
+      if (activeView == null) return;
+      var algorithm = (IAlgorithm)activeView.Content;
+      var problem = (IDataAnalysisProblem)algorithm.Problem;
+      var inputCount = problem.ProblemData.AllowedInputVariables.Count();
+      warningLabel.Text = string.Format("Warning: this will create {0} combinations.", EnumerableExtensions.BinomialCoefficient(inputCount, combinationGroupSize));
+    }
+    #endregion
   }
 }
Index: branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks/3.3/HeuristicLab.VariableInteractionNetworks-3.3.csproj
===================================================================
--- branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks/3.3/HeuristicLab.VariableInteractionNetworks-3.3.csproj	(revision 13789)
+++ branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks/3.3/HeuristicLab.VariableInteractionNetworks-3.3.csproj	(revision 13806)
@@ -166,5 +166,4 @@
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="SymbolicDataAnalysisVariableImpactsAnalyzer.cs" />
-    <Compile Include="TinySet.cs" />
     <Compile Include="VariableInteractionNetwork.cs" />
   </ItemGroup>
Index: branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks/3.3/TinySet.cs
===================================================================
--- branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks/3.3/TinySet.cs	(revision 13789)
+++ 	(revision )
@@ -1,107 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace HeuristicLab.VariableInteractionNetworks {
-  internal static class Util {
-    public static IEnumerable<IEnumerable<T>> Combinations<T>(IList<T> items, int k) {
-      if (k < 0)
-        throw new InvalidOperationException();
-      if (items == null)
-        throw new ArgumentNullException("items");
-      int n = items.Count;
-      if (n > TinySet.Maximum)
-        throw new InvalidOperationException();
-      return
-        from combination in Combinations(n, k)
-        select (from index in combination select items[index]);
-    }
-
-    // Takes integers n and k, both non-negative.
-    // Produces all sets of exactly k elements consisting only of 
-    // integers from 0 through n - 1.
-    private static IEnumerable<TinySet> Combinations(int n, int k) {
-      // Base case: if k is zero then there can be only one set
-      // regardless of the value of n: the empty set is the only set
-      // with zero elements.
-      if (k == 0) {
-        yield return TinySet.Empty;
-        yield break;
-      }
-
-      // Base case: if n < k then there can be no set of exactly
-      // k elements containing values from 0 to n - 1, because sets
-      // do not contain repeated elements.
-
-      if (n < k)
-        yield break;
-
-      // A set containing k elements where each is an integer from
-      // 0 to n - 2 is also a set of k elements where each is an
-      // integer from 0 to n - 1, so yield all of those.
-
-      foreach (var r in Combinations(n - 1, k))
-        yield return r;
-
-      // If we add n - 1 to all the sets of k - 1 elements where each
-      // is an integer from 0 to n - 2, then we get a set of k elements
-      // where each is an integer from 0 to n - 1.
-
-      foreach (var r in Combinations(n - 1, k - 1))
-        yield return r.Add(n - 1);
-    }
-  }
-
-  internal struct TinySet : IEnumerable<int> {
-    public static readonly TinySet Empty = new TinySet(0);
-    public const int Minimum = 0;
-    public const int Maximum = 31;
-    private readonly int bits;
-    private TinySet(int bits) { this.bits = bits; }
-    public bool Contains(int item) {
-      if (item < Minimum || item > Maximum)
-        return false;
-      return (bits & (1 << item)) != 0;
-    }
-    public TinySet Add(int item) {
-      if (item < Minimum || item > Maximum)
-        throw new InvalidOperationException();
-      return new TinySet(bits | (1 << item));
-    }
-    public TinySet Remove(int item) {
-      if (item < Minimum || item > Maximum)
-        return this;
-      return new TinySet(bits & ~(1 << item));
-    }
-    IEnumerator IEnumerable.GetEnumerator() {
-      return this.GetEnumerator();
-    }
-    public IEnumerator<int> GetEnumerator() {
-      for (int item = Minimum; item <= Maximum; ++item)
-        if (Contains(item))
-          yield return item;
-    }
-  }
-}
