Index: /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/Distributions.cs
===================================================================
--- /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/Distributions.cs	(revision 14880)
+++ /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/Distributions.cs	(revision 14880)
@@ -0,0 +1,78 @@
+﻿
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Core;
+using HeuristicLab.ExpressionGenerator.Interfaces;
+
+namespace HeuristicLab.ExpressionGenerator {
+  // wrapper which calls NextDouble() of a PRNG to sample from a distribution
+  public class DoublePrngDistribution : IDistribution<double> {
+    private readonly IRandom prng;
+
+    public DoublePrngDistribution(IRandom random) {
+      this.prng = random;
+    }
+
+    public double Sample() {
+      return prng.NextDouble();
+    }
+
+    public IEnumerable<double> SampleN(int n) {
+      return Enumerable.Range(0, n).Select(_ => prng.NextDouble());
+    }
+  }
+  // wrapper which calls Next() of a PRNG to sample from a distribution
+  public class IntPrngDistribution : IDistribution<int> {
+    private readonly IRandom prng;
+
+    public IntPrngDistribution(IRandom random) {
+      this.prng = random;
+    }
+
+    public int Sample() {
+      return prng.Next();
+    }
+
+    public IEnumerable<int> SampleN(int n) {
+      return Enumerable.Range(0, n).Select(_ => prng.Next());
+    }
+  }
+
+  // p(x): x == value ? 1 : 0
+  public class PointDistribution<T> : IDistribution<T> where T : struct {
+    public readonly T value;
+
+    public PointDistribution(T value) {
+      this.value = value;
+    }
+
+    public T Sample() {
+      return value;
+    }
+
+    public IEnumerable<T> SampleN(int n) {
+      return Enumerable.Repeat(value, n);
+    }
+  }
+
+  public class DiscreteUniformDistribution : IDistribution<int> {
+    public readonly int minValue; // inclusive
+    public readonly int maxValue; // exclusive
+    public readonly IRandom random;
+
+    public DiscreteUniformDistribution(IRandom random, int minValue, int maxValue) {
+      this.minValue = minValue;
+      this.maxValue = maxValue;
+      this.random = random;
+    }
+
+    public int Sample() {
+      return random.Next(minValue, maxValue);
+    }
+
+    public IEnumerable<int> SampleN(int n) {
+      return Enumerable.Range(0, n).Select(_ => Sample());
+    }
+  }
+}
Index: /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/Expression.cs
===================================================================
--- /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/Expression.cs	(revision 14879)
+++ /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/Expression.cs	(revision 14880)
@@ -37,5 +37,5 @@
     public ExpressionType Type { get; private set; }
 
-    private readonly List<Expression> arguments;
+    private readonly List<Expression> arguments; // only for functions
     public IEnumerable<Expression> Arguments {
       get { return arguments ?? Enumerable.Empty<Expression>(); }
@@ -85,5 +85,5 @@
       switch (Type) {
         case ExpressionType.Constant:
-          sb.Append(Value.ToString("0.000", CultureInfo.InvariantCulture));
+          sb.Append(Value.ToString("E4", CultureInfo.InvariantCulture));
           break;
         case ExpressionType.RandomVariable:
@@ -108,6 +108,6 @@
         case ExpressionType.Constant:
           sb.Append(Value < 0
-              ? string.Format("(- {0})", Math.Abs(Value).ToString("0.000", CultureInfo.InvariantCulture))
-              : Value.ToString("0.000", CultureInfo.InvariantCulture));
+              ? string.Format("(- {0})", Math.Abs(Value).ToString("E4", CultureInfo.InvariantCulture))
+              : Value.ToString("E4", CultureInfo.InvariantCulture));
           break;
         case ExpressionType.RandomVariable:
Index: /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/ExpressionGenerator.cs
===================================================================
--- /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/ExpressionGenerator.cs	(revision 14879)
+++ /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/ExpressionGenerator.cs	(revision 14880)
@@ -24,4 +24,5 @@
 using System.Linq;
 using HeuristicLab.Core;
+using HeuristicLab.ExpressionGenerator.Interfaces;
 using HeuristicLab.Random;
 
@@ -32,33 +33,149 @@
     }
 
-    public static Expression NonlinearExpression(IRandom uniformRandom, Expression[] variables, bool useLog, bool useExp) {
-      var scalingTemplate = ScaledExpression(uniformRandom, variables, varianceRandom: new UniformDistributedRandom(uniformRandom, 1, 10));
-      var scaledVars = Instantiate(scalingTemplate, uniformRandom, 100, "scaledVar");
-
-      var sumTemplate = new RandomArityTemplate(Sum, new UniformDistributedRandom(uniformRandom, 1, 3)) { Label = "+" };
+    public static Expression RationalExpression(IRandom uniformRandom, Expression[] variables, bool useLog, bool useExp) {
+      var numerators =
+        Enumerable.Range(0, 20)
+          .Select(
+            i =>
+              NonlinearExpressionTemplate(uniformRandom, variables, useLog, useExp, false)
+                .Instantiate("numerator" + i, uniformRandom, sampleWithRepetition: false))
+          .ToArray();
+      var denominators =
+        Enumerable.Range(0, 20)
+          .Select(
+            i =>
+              NonlinearExpressionTemplate(uniformRandom, variables, useLog, useExp, false)
+                .Instantiate("denominator" + i, uniformRandom, sampleWithRepetition: false))
+          .ToArray();
+
+
+      var scaledNumeratorTemplate = new ScalingTemplate(new PointDistribution<double>(1.0));
+      scaledNumeratorTemplate.AddArguments(numerators);
+
+      var scaledDenominatorTemplate = new RangeTemplate(
+        minValue: new DoublePrngDistribution(new UniformDistributedRandom(uniformRandom, 0.01, 1)),
+        valueRange: new DoublePrngDistribution(new UniformDistributedRandom(uniformRandom, 2, 10)));
+      scaledDenominatorTemplate.AddArguments(denominators);
+
+
+      var scaledNumerators =
+        Enumerable.Range(0, 20)
+          .Select(i => scaledNumeratorTemplate.Instantiate("scaledNumerator" + i, uniformRandom, false));
+
+      var scaledDenominators =
+        Enumerable.Range(0, 20)
+          .Select(i => scaledDenominatorTemplate.Instantiate("scaledDenom" + i, uniformRandom, false));
+
+      var template = new BinaryOperatorTemplate(Division) { Label = "/" };
+      template.AddLeftArguments(scaledNumerators);
+      template.AddRightArguments(scaledDenominators);
+
+      return template.Instantiate("rational", uniformRandom, false);
+    }
+
+    public static Expression SumOfCompactNonlinearTerms(IRandom uniformRandom, Expression[] variables, bool useLog,
+      bool useExp, bool useFrac) {
+      var numInstances = 2 * variables.Length;
+
+      var scalingVarsTemplate = new ScalingTemplate(new DoublePrngDistribution(new GammaDistributedRandom(uniformRandom, 2, 2))); // exp(x) = 1, var(x) = 8
+      scalingVarsTemplate.AddArguments(variables);
+      var scaledVars = Instantiate(scalingVarsTemplate, uniformRandom, numInstances, "scaledVar");
+
+      var sumOfScaledVarsTemplate = new RandomArityTemplate(Sum, new DiscreteUniformDistribution(uniformRandom, 1, 3)) { Label = "+" };
+      sumOfScaledVarsTemplate.AddArguments(scaledVars);
+      var sumOfScaledVars = Instantiate(sumOfScaledVarsTemplate, uniformRandom, numInstances, "sumOfScaledVars");
+
+      var prodTemplate = new RandomArityTemplate(Product, new DiscreteUniformDistribution(uniformRandom, 1, 3)) { Label = "*" };
+      prodTemplate.AddArguments(variables);
+
+      var logTermsTemplate = LogOfScaledExpression(uniformRandom, sumOfScaledVars,
+      minValue: new DoublePrngDistribution(new UniformDistributedRandom(uniformRandom, 0.1, 2)),
+      valueRange: new DoublePrngDistribution(new UniformDistributedRandom(uniformRandom, 1, 10)));
+      var logTerms = Instantiate(logTermsTemplate, uniformRandom, numInstances, "log");
+
+      var expTemplate = ExpOfScaledExpression(uniformRandom, Instantiate(prodTemplate, uniformRandom, numInstances, "prodOfVars"),
+                           minValue: new PointDistribution<double>(-2.0),
+                           valueRange: new DoublePrngDistribution(new UniformDistributedRandom(uniformRandom, 4, 6)));
+      var expTerms = Instantiate(expTemplate, uniformRandom, numInstances, "exp");
+
+      var fracTemplate = new BinaryOperatorTemplate(Division) { Label = "/" };
+      fracTemplate.AddLeftArgument(Expression.Constant("const", 1.0), variables.Length);
+      fracTemplate.AddLeftArguments(variables);
+      fracTemplate.AddRightArguments(sumOfScaledVars);
+      var fracTerms = Enumerable.Range(1, numInstances).Select(i => fracTemplate.Instantiate("frac" + i, uniformRandom, false));
+
+      var prodOfFactorsTemplate = new RandomArityTemplate(Product, new DiscreteUniformDistribution(uniformRandom, 1, 4)) { Label = "*" };
+      prodOfFactorsTemplate.AddArguments(variables, variables.Select(_ => 1.0));
+      if (useLog) prodOfFactorsTemplate.AddArguments(logTerms, logTerms.Select(_ => .3));
+      if (useExp) prodOfFactorsTemplate.AddArguments(expTerms, expTerms.Select(_ => .3));
+      if (useFrac) prodOfFactorsTemplate.AddArguments(fracTerms, fracTerms.Select(_ => .3));
+      var prodFactors = Instantiate(prodOfFactorsTemplate, uniformRandom, numInstances, "prod");
+
+      var scaledTermsTemplate =
+        new ScalingTemplate(new DoublePrngDistribution(new GammaDistributedRandom(uniformRandom, 2, 2))); // exp(x) = 1, var(x) = 8
+      scaledTermsTemplate.AddArguments(variables, variables.Select(_ => 1.0));
+      if (useLog) scaledTermsTemplate.AddArguments(logTerms, logTerms.Select(_ => 1.0));
+      if (useExp) scaledTermsTemplate.AddArguments(expTerms, expTerms.Select(_ => 1.0));
+      if (useFrac) scaledTermsTemplate.AddArguments(fracTerms, fracTerms.Select(_ => 1.0));
+      scaledTermsTemplate.AddArguments(prodFactors, prodFactors.Select(_ => 4.0));
+
+      var scaledTerms = Instantiate(scaledTermsTemplate, uniformRandom, 100, "scaledTerm");
+
+      var sumTemplate = new RandomArityTemplate(Sum, arityDistribution: new DiscreteUniformDistribution(uniformRandom, 5, 25)) { Label = "+" };
+      sumTemplate.AddArguments(scaledTerms);
+
+      return sumTemplate.Instantiate("sum", uniformRandom, false);
+    }
+
+    public static Expression NonlinearExpression(IRandom uniformRandom, Expression[] variables, bool useLog, bool useExp, bool useFrac) {
+      return NonlinearExpressionTemplate(uniformRandom, variables, useLog, useExp, useFrac)
+        .Instantiate("nonlinearexpr", uniformRandom, sampleWithRepetition: false);
+    }
+
+    public static ExpressionTemplate NonlinearExpressionTemplate(IRandom uniformRandom, Expression[] variables, bool useLog, bool useExp, bool useFrac) {
+      var scalingTemplate = ScaledExpression(uniformRandom, variables, varianceDistribution: new DoublePrngDistribution(new UniformDistributedRandom(uniformRandom, 1, 10)));
+      var scaledVars = Instantiate(scalingTemplate, uniformRandom, variables.Length, "scaledVar");
+
+      var sumTemplate = new RandomArityTemplate(Sum, new DiscreteUniformDistribution(uniformRandom, 1, 3)) { Label = "+" };
       sumTemplate.AddArguments(scaledVars);
-      var prodTemplate = new RandomArityTemplate(Product, new UniformDistributedRandom(uniformRandom, 1, 3)) { Label = "*" };
+      var prodTemplate = new RandomArityTemplate(Product, new DiscreteUniformDistribution(uniformRandom, 1, 3)) { Label = "*" };
       prodTemplate.AddArguments(variables);
 
-      var logTemplate = LogOfScaledExpression(uniformRandom, Instantiate(sumTemplate, uniformRandom, 100, "sumOfScaledVars"),
-        minValue: new UniformDistributedRandom(uniformRandom, 0.1, 2),
-        valueRange: new UniformDistributedRandom(uniformRandom, 1, 10));
-
-      var expTemplate = ExpOfScaledExpression(uniformRandom, Instantiate(prodTemplate, uniformRandom, 100, "prodOfVars"),
-        minValue: new PointDistribution(-3),
-        valueRange: new UniformDistributedRandom(uniformRandom, 4, 6)); 
-
-      var scaledExprTemplate = new ScalingTemplate(new UniformDistributedRandom(uniformRandom, 1, 10)) { Label = "*" };
-      if (useLog) scaledExprTemplate.AddArguments(Instantiate(logTemplate, uniformRandom, 100, "log"));
-      if (useExp) scaledExprTemplate.AddArguments(Instantiate(expTemplate, uniformRandom, 100, "exp"));
-
-      var mainTemplate = new RandomArityTemplate(Sum, new UniformDistributedRandom(uniformRandom, 3, 5));
+      var logTemplate = LogOfScaledExpression(uniformRandom, Instantiate(sumTemplate, uniformRandom, scaledVars.Count(), "sumOfScaledVars"),
+        minValue: new DoublePrngDistribution(new UniformDistributedRandom(uniformRandom, 0.1, 2)),
+        valueRange: new DoublePrngDistribution(new UniformDistributedRandom(uniformRandom, 1, 10)));
+
+      var expTemplate = ExpOfScaledExpression(uniformRandom, Instantiate(prodTemplate, uniformRandom, variables.Length, "prodOfVars"),
+        minValue: new PointDistribution<double>(-3.0),
+        valueRange: new DoublePrngDistribution(new UniformDistributedRandom(uniformRandom, 4, 6)));
+
+      var variableSumTemplate = new RandomArityTemplate(Sum, new DiscreteUniformDistribution(uniformRandom, 1, 4)) { Label = "+" };
+      variableSumTemplate.AddArguments(variables);
+      var variableSums = Instantiate(variableSumTemplate, uniformRandom, variables.Length * 2, "varsum");
+
+      var scaledVariableSumTemplate =
+        new RangeTemplate(minValue: new DoublePrngDistribution(new UniformDistributedRandom(uniformRandom, 0.1, 1)),
+          valueRange: new DoublePrngDistribution(new UniformDistributedRandom(uniformRandom, 1, 5))) { Label = "*" };
+      scaledVariableSumTemplate.AddArguments(variableSums);
+      var scaledVariableSums = Instantiate(scaledVariableSumTemplate, uniformRandom, variables.Length * 2,
+        "scaledvarsum");
+
+      var fracTemplate = new BinaryOperatorTemplate(Division) { Label = "/" };
+      fracTemplate.AddLeftArguments(variables);
+      fracTemplate.AddRightArguments(scaledVariableSums);
+
+      var scaledExprTemplate = new ScalingTemplate(new DoublePrngDistribution(new UniformDistributedRandom(uniformRandom, 1, 10))) { Label = "*" };
+      if (useLog) scaledExprTemplate.AddArguments(Instantiate(logTemplate, uniformRandom, scaledVars.Count(), "log"));
+      if (useExp) scaledExprTemplate.AddArguments(Instantiate(expTemplate, uniformRandom, variables.Length, "exp"));
+      if (useFrac) scaledExprTemplate.AddArguments(Enumerable.Range(0, 20).Select(i => fracTemplate.Instantiate("frac" + i, uniformRandom, false)));
+
+      var mainTemplate = new RandomArityTemplate(Sum, arityDistribution: new DiscreteUniformDistribution(uniformRandom, 3, 5));
       mainTemplate.AddArguments(scaledVars);
       if (useLog || useExp) {
-        mainTemplate.AddArguments(Instantiate(scaledExprTemplate, uniformRandom, 100, "scaledExpr"));
+        mainTemplate.AddArguments(Instantiate(scaledExprTemplate, uniformRandom, 20, "scaledExpr"));
       }
       mainTemplate.Label = "+";
 
-      return mainTemplate.Instantiate("main", uniformRandom, false);
+      return mainTemplate;
     }
 
@@ -67,11 +184,11 @@
       int i = 1;
       // the main template
-      var template = new RandomArityTemplate(Sum, new UniformDistributedRandom(uniformRandom, 2, count)) { Label = "+" };
+      var template = new RandomArityTemplate(Sum, arityDistribution: new DiscreteUniformDistribution(uniformRandom, 2, count)) { Label = "+" };
       template.AddArguments(variables);
 
-      var sumTemplate = new RandomArityTemplate(Sum, new UniformDistributedRandom(uniformRandom, 1, variables.Length)) { Label = "+" };
+      var sumTemplate = new RandomArityTemplate(Sum, arityDistribution: new DiscreteUniformDistribution(uniformRandom, 1, variables.Length)) { Label = "+" };
       sumTemplate.AddArguments(variables);
 
-      var productTemplate = new RandomArityTemplate(Product, new UniformDistributedRandom(uniformRandom, 1, variables.Length)) { Label = "*" };
+      var productTemplate = new RandomArityTemplate(Product, arityDistribution: new DiscreteUniformDistribution(uniformRandom, 1, variables.Length)) { Label = "*" };
       productTemplate.AddArguments(variables);
 
@@ -102,6 +219,6 @@
 
     // variance random must have support only positive numbers
-    private static ExpressionTemplate ScaledExpression(IRandom uniformRandom, IEnumerable<Expression> arguments, IRandom varianceRandom) {
-      var scalingTemplate = new ScalingTemplate(scaledVariance: varianceRandom);
+    private static ExpressionTemplate ScaledExpression(IRandom uniformRandom, IEnumerable<Expression> arguments, IDistribution<double> varianceDistribution) {
+      var scalingTemplate = new ScalingTemplate(scaledVariance: varianceDistribution);
       scalingTemplate.AddArguments(arguments);
       scalingTemplate.Label = "*";
@@ -111,10 +228,10 @@
     /// template scales and translates the argument expression first to guarantee positive values
     private static ExpressionTemplate LogOfScaledExpression(IRandom uniformRandom, IEnumerable<Expression> arguments,
-      IRandom minValue = null, IRandom valueRange = null) {
+      IDistribution<double> minValue = null, IDistribution<double> valueRange = null) {
       var limitToRangeTemplate = new RangeTemplate(minValue, valueRange);
       limitToRangeTemplate.AddArguments(arguments);
 
       var logTemplate = new FixedArityTemplate(Log, 1) { Label = "log" };
-      logTemplate.AddArguments(Enumerable.Range(1, 100).Select(i => limitToRangeTemplate.Instantiate(string.Format("log{0}", i), uniformRandom, false)));
+      logTemplate.AddArguments(Enumerable.Range(1, arguments.Count()).Select(i => limitToRangeTemplate.Instantiate(string.Format("log{0}", i), uniformRandom, false)));
       return logTemplate;
     }
@@ -122,11 +239,11 @@
     /// template scales the argument expression first to guarantee reasonable values
     private static ExpressionTemplate ExpOfScaledExpression(IRandom uniformRandom, IEnumerable<Expression> arguments,
-      IRandom minValue = null,
-      IRandom valueRange = null) {
+      IDistribution<double> minValue = null,
+      IDistribution<double> valueRange = null) {
       var limitToRangeTemplate = new RangeTemplate(minValue, valueRange);
       limitToRangeTemplate.AddArguments(arguments);
 
       var expTemplate = new FixedArityTemplate(Exp, 1) { Label = "exp" };
-      expTemplate.AddArguments(Enumerable.Range(1, 100).Select(i => limitToRangeTemplate.Instantiate(string.Format("exp{0}", i), uniformRandom, false)));
+      expTemplate.AddArguments(Enumerable.Range(1, arguments.Count()).Select(i => limitToRangeTemplate.Instantiate(string.Format("exp{0}", i), uniformRandom, false)));
       return expTemplate;
     }
Index: /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/ExpressionTemplate.cs
===================================================================
--- /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/ExpressionTemplate.cs	(revision 14879)
+++ /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/ExpressionTemplate.cs	(revision 14880)
@@ -25,8 +25,12 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.ExpressionGenerator.Interfaces;
 using HeuristicLab.Random;
 
 namespace HeuristicLab.ExpressionGenerator {
-  public abstract class ExpressionTemplate {
+  public interface IExpressionTemplate {
+    string Label { get; set; }
+  }
+  public abstract class ExpressionTemplate : IExpressionTemplate {
     protected List<Tuple<Expression, double>> arguments;
     protected readonly Func<IEnumerable<double>, double> transform;
@@ -42,6 +46,6 @@
       var weights = arguments.Select(x => x.Item2);
       var args = sampleWithRepetition
-       ? arguments.SampleProportional(random, n, weights).Select(x => x.Item1)
-       : arguments.SampleProportionalWithoutRepetition(random, n, weights).Select(x => x.Item1);
+       ? arguments.SampleProportional(random, n, weights, windowing: false).Select(x => x.Item1)
+       : arguments.SampleProportionalWithoutRepetition(random, n, weights, windowing: false).Select(x => x.Item1);
       return args;
     }
@@ -70,12 +74,12 @@
 
   public class RandomArityTemplate : ExpressionTemplate {
-    private readonly IRandom arityDistribution;
-
-    public RandomArityTemplate(Func<IEnumerable<double>, double> transform, IRandom arityDistribution) : base(transform) {
+    private readonly IDistribution<int> arityDistribution;
+
+    public RandomArityTemplate(Func<IEnumerable<double>, double> transform, IDistribution<int> arityDistribution) : base(transform) {
       this.arityDistribution = arityDistribution;
     }
 
     public override Expression Instantiate(string name, IRandom random, bool sampleWithRepetition = false) {
-      var arity = (int)Math.Round(arityDistribution.NextDouble());
+      var arity = arityDistribution.Sample();
       return Instantiate(name, random, arity, sampleWithRepetition);
     }
@@ -93,8 +97,72 @@
   }
 
+
+  public class BinaryOperatorTemplate : IExpressionTemplate {
+    public string Label { get; set; }
+    private readonly Func<IEnumerable<double>, double> transform;
+    private List<Tuple<Expression, double>> leftArguments;
+    private List<Tuple<Expression, double>> rightArguments;
+
+    public BinaryOperatorTemplate(Func<IEnumerable<double>, double> transform) {
+      this.transform = transform;
+    }
+
+    public void AddLeftArgument(Expression expression, double weight = 1d) {
+      leftArguments = leftArguments ?? new List<Tuple<Expression, double>>();
+      leftArguments.Add(Tuple.Create(expression, weight));
+    }
+
+    public void AddLeftArguments(IEnumerable<Expression> expressions) {
+      leftArguments = leftArguments ?? new List<Tuple<Expression, double>>();
+      leftArguments.AddRange(expressions.Select(x => Tuple.Create(x, 1d)));
+    }
+
+    public void AddLeftArguments(IEnumerable<Expression> expressions, IEnumerable<double> weights) {
+      leftArguments = leftArguments ?? new List<Tuple<Expression, double>>();
+      leftArguments.AddRange(expressions.Zip(weights, Tuple.Create));
+    }
+
+
+    public void AddRightArgument(Expression expression, double weight = 1d) {
+      rightArguments = rightArguments ?? new List<Tuple<Expression, double>>();
+      rightArguments.Add(Tuple.Create(expression, weight));
+    }
+
+    public void AddRightArguments(IEnumerable<Expression> expressions) {
+      rightArguments = rightArguments ?? new List<Tuple<Expression, double>>();
+      rightArguments.AddRange(expressions.Select(x => Tuple.Create(x, 1d)));
+    }
+
+    public void AddRightArguments(IEnumerable<Expression> expressions, IEnumerable<double> weights) {
+      rightArguments = rightArguments ?? new List<Tuple<Expression, double>>();
+      rightArguments.AddRange(expressions.Zip(weights, Tuple.Create));
+    }
+
+    public Expression Instantiate(string name, IRandom random, bool sampleWithRepetition = false) {
+      Expression leftArgument = null;
+      Expression rightArgument = null;
+      {
+        var weights = leftArguments.Select(x => x.Item2);
+        leftArgument = sampleWithRepetition
+          ? leftArguments.SampleProportional(random, 1, weights, windowing: false).Select(x => x.Item1).First() :
+          leftArguments.SampleProportionalWithoutRepetition(random, 1, weights, windowing: false).Select(x => x.Item1).First();
+      }
+      {
+        var weights = rightArguments.Select(x => x.Item2);
+        rightArgument = sampleWithRepetition
+          ? rightArguments.SampleProportional(random, 1, weights).Select(x => x.Item1).First() :
+          rightArguments.SampleProportionalWithoutRepetition(random, 1, weights).Select(x => x.Item1).First();
+      }
+
+      var func = Expression.Function(name, transform, new Expression[] { leftArgument, rightArgument });
+      func.Label = Label;
+      return func;
+    }
+  }
+
   public class ScalingTemplate : ExpressionTemplate {
-    private readonly IRandom scaledVariance;
+    private readonly IDistribution<double> scaledVariance;
     // w * expr
-    public ScalingTemplate(IRandom scaledVariance = null) : base(ExpressionGenerator.Product) {
+    public ScalingTemplate(IDistribution<double> scaledVariance = null) : base(ExpressionGenerator.Product) {
       this.scaledVariance = scaledVariance;
     }
@@ -109,5 +177,5 @@
         var data = evaluator.GenerateData(expr, 10000);
         var variance = data[expr].VariancePop();
-        @const = scaledVariance.NextDouble() / variance;
+        @const = scaledVariance.Sample() / variance;
       }
 
@@ -119,7 +187,7 @@
 
   public class OffsetTemplate : ExpressionTemplate {
-    private readonly IRandom offset;
+    private readonly IDistribution<double> offset;
     // expr + offset
-    public OffsetTemplate(IRandom offset = null) : base(ExpressionGenerator.Sum) {
+    public OffsetTemplate(IDistribution<double> offset = null) : base(ExpressionGenerator.Sum) {
       this.offset = offset;
     }
@@ -134,5 +202,5 @@
         var data = evaluator.GenerateData(expr, 10000);
         var average = data[expr].Average();
-        @const = offset.NextDouble() - average;
+        @const = offset.Sample() - average;
       }
 
@@ -144,8 +212,8 @@
 
   public class RangeTemplate : ExpressionTemplate {
-    private readonly IRandom minValue;
-    private readonly IRandom valueRange;
+    private readonly IDistribution<double> minValue;
+    private readonly IDistribution<double> valueRange;
     // expr + offset
-    public RangeTemplate(IRandom minValue = null, IRandom valueRange = null) : base(null) {
+    public RangeTemplate(IDistribution<double> minValue = null, IDistribution<double> valueRange = null) : base(null) {
       this.minValue = minValue;
       this.valueRange = valueRange;
@@ -163,5 +231,5 @@
         var data = evaluator.GenerateData(expr, 10000);
         if (valueRange != null) {
-          var targetRange = valueRange.NextDouble();
+          var targetRange = valueRange.Sample();
           var min = data[expr].Min();
           var max = data[expr].Max();
@@ -171,5 +239,5 @@
         }
         if (minValue != null) {
-          var targetMin = minValue.NextDouble();
+          var targetMin = minValue.Sample();
           var min = data[expr].Min();
           add += (targetMin - min) / mult;
Index: /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/HeuristicLab.ExpressionGenerator.csproj
===================================================================
--- /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/HeuristicLab.ExpressionGenerator.csproj	(revision 14879)
+++ /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/HeuristicLab.ExpressionGenerator.csproj	(revision 14880)
@@ -72,10 +72,11 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Distributions.cs" />
     <Compile Include="Expression.cs" />
     <Compile Include="ExpressionEvaluator.cs" />
     <Compile Include="ExpressionGenerator.cs" />
     <Compile Include="ExpressionTemplate.cs" />
+    <Compile Include="Interfaces\IDistribution.cs" />
     <Compile Include="Interfaces\IExpression.cs" />
-    <Compile Include="PointDistribution.cs" />
     <Compile Include="Plugin.cs" />
   </ItemGroup>
Index: /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/Interfaces/IDistribution.cs
===================================================================
--- /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/Interfaces/IDistribution.cs	(revision 14880)
+++ /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/Interfaces/IDistribution.cs	(revision 14880)
@@ -0,0 +1,8 @@
+﻿using System.Collections.Generic;
+
+namespace HeuristicLab.ExpressionGenerator.Interfaces {
+  public interface IDistribution<T> {
+    T Sample();
+    IEnumerable<T> SampleN(int n);
+  }
+}
Index: anches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/PointDistribution.cs
===================================================================
--- /branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/PointDistribution.cs	(revision 14879)
+++ 	(revision )
@@ -1,65 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-$year$ 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 HeuristicLab.Common;
-using HeuristicLab.Core;
-
-namespace HeuristicLab.ExpressionGenerator {
-
-  public class PointDistribution : Item, IRandom {
-    private double value;
-    public PointDistribution() : base() { }
-
-    public PointDistribution(PointDistribution original, Cloner cloner) : base(original, cloner) {
-      value = original.value;
-    }
-
-    public PointDistribution(double value) {
-      this.value = value;
-    }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new PointDistribution(this, cloner);
-    }
-
-    public void Reset() {
-    }
-
-    public void Reset(int seed) {
-    }
-
-    public int Next() {
-      throw new NotSupportedException();
-    }
-
-    public int Next(int maxVal) {
-      throw new NotSupportedException();
-    }
-
-    public int Next(int minVal, int maxVal) {
-      throw new NotSupportedException();
-    }
-
-    public double NextDouble() {
-      return value;
-    }
-  }
-}
