Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NonlinearRegression/NonlinearRegression.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NonlinearRegression/NonlinearRegression.cs	(revision 14563)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NonlinearRegression/NonlinearRegression.cs	(revision 14564)
@@ -21,16 +21,16 @@
 
 using System;
-using System.Collections.Generic;
 using System.Linq;
+using HeuristicLab.Analysis;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Data;
+using HeuristicLab.Optimization;
 using HeuristicLab.Parameters;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-using HeuristicLab.Optimization;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 using HeuristicLab.Problems.DataAnalysis;
 using HeuristicLab.Problems.DataAnalysis.Symbolic;
 using HeuristicLab.Problems.DataAnalysis.Symbolic.Regression;
+using HeuristicLab.Random;
 
 namespace HeuristicLab.Algorithms.DataAnalysis {
@@ -45,4 +45,8 @@
     private const string ModelStructureParameterName = "Model structure";
     private const string IterationsParameterName = "Iterations";
+    private const string RestartsParameterName = "Restarts";
+    private const string SetSeedRandomlyParameterName = "SetSeedRandomly";
+    private const string SeedParameterName = "Seed";
+    private const string InitParamsRandomlyParameterName = "InitializeParametersRandomly";
 
     public IFixedValueParameter<StringValue> ModelStructureParameter {
@@ -51,4 +55,20 @@
     public IFixedValueParameter<IntValue> IterationsParameter {
       get { return (IFixedValueParameter<IntValue>)Parameters[IterationsParameterName]; }
+    }
+
+    public IFixedValueParameter<BoolValue> SetSeedRandomlyParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[SetSeedRandomlyParameterName]; }
+    }
+
+    public IFixedValueParameter<IntValue> SeedParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[SeedParameterName]; }
+    }
+
+    public IFixedValueParameter<IntValue> RestartsParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[RestartsParameterName]; }
+    }
+
+    public IFixedValueParameter<BoolValue> InitParametersRandomlyParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[InitParamsRandomlyParameterName]; }
     }
 
@@ -63,4 +83,23 @@
     }
 
+    public int Restarts {
+      get { return RestartsParameter.Value.Value; }
+      set { RestartsParameter.Value.Value = value; }
+    }
+
+    public int Seed {
+      get { return SeedParameter.Value.Value; }
+      set { SeedParameter.Value.Value = value; }
+    }
+
+    public bool SetSeedRandomly {
+      get { return SetSeedRandomlyParameter.Value.Value; }
+      set { SetSeedRandomlyParameter.Value.Value = value; }
+    }
+
+    public bool InitializeParametersRandomly {
+      get { return InitParametersRandomlyParameter.Value.Value; }
+      set { InitParametersRandomlyParameter.Value.Value = value; }
+    }
 
     [StorableConstructor]
@@ -74,7 +113,42 @@
       Parameters.Add(new FixedValueParameter<StringValue>(ModelStructureParameterName, "The function for which the parameters must be fit (only numeric constants are tuned).", new StringValue("1.0 * x*x + 0.0")));
       Parameters.Add(new FixedValueParameter<IntValue>(IterationsParameterName, "The maximum number of iterations for constants optimization.", new IntValue(200)));
-    }
+      Parameters.Add(new FixedValueParameter<IntValue>(RestartsParameterName, "The number of independent random restarts (>0)", new IntValue(10)));
+      Parameters.Add(new FixedValueParameter<IntValue>(SeedParameterName, "The PRNG seed value.", new IntValue()));
+      Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyParameterName, "Switch to determine if the random number seed should be initialized randomly.", new BoolValue(true)));
+      Parameters.Add(new FixedValueParameter<BoolValue>(InitParamsRandomlyParameterName, "Switch to determine if the real-valued model parameters should be initialized randomly in each restart.", new BoolValue(false)));
+
+      SetParameterHiddenState();
+
+      InitParametersRandomlyParameter.Value.ValueChanged += (sender, args) => {
+        SetParameterHiddenState();
+      };
+    }
+
+    private void SetParameterHiddenState() {
+      var hide = !InitializeParametersRandomly;
+      RestartsParameter.Hidden = hide;
+      SeedParameter.Hidden = hide;
+      SetSeedRandomlyParameter.Hidden = hide;
+    }
+
     [StorableHook(HookType.AfterDeserialization)]
-    private void AfterDeserialization() { }
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey(RestartsParameterName))
+        Parameters.Add(new FixedValueParameter<IntValue>(RestartsParameterName, "The number of independent random restarts", new IntValue(1)));
+      if (!Parameters.ContainsKey(SeedParameterName))
+        Parameters.Add(new FixedValueParameter<IntValue>(SeedParameterName, "The PRNG seed value.", new IntValue()));
+      if (!Parameters.ContainsKey(SetSeedRandomlyParameterName))
+        Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyParameterName, "Switch to determine if the random number seed should be initialized randomly.", new BoolValue(true)));
+      if (!Parameters.ContainsKey(InitParamsRandomlyParameterName))
+        Parameters.Add(new FixedValueParameter<BoolValue>(InitParamsRandomlyParameterName, "Switch to determine if the numeric parameters of the model should be initialized randomly.", new BoolValue(false)));
+
+      SetParameterHiddenState();
+      InitParametersRandomlyParameter.Value.ValueChanged += (sender, args) => {
+        SetParameterHiddenState();
+      };
+      #endregion
+    }
 
     public override IDeepCloneable Clone(Cloner cloner) {
@@ -84,22 +158,69 @@
     #region nonlinear regression
     protected override void Run() {
-      var solution = CreateRegressionSolution(Problem.ProblemData, ModelStructure, Iterations);
-      Results.Add(new Result(RegressionSolutionResultName, "The nonlinear regression solution.", solution));
-      Results.Add(new Result("Root mean square error (train)", "The root of the mean of squared errors of the regression solution on the training set.", new DoubleValue(solution.TrainingRootMeanSquaredError)));
-      Results.Add(new Result("Root mean square error (test)", "The root of the mean of squared errors of the regression solution on the test set.", new DoubleValue(solution.TestRootMeanSquaredError)));
-    }
-
-    public static ISymbolicRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData, string modelStructure, int maxIterations) {
+      IRegressionSolution bestSolution = null;
+      if (InitializeParametersRandomly) {
+        var qualityTable = new DataTable("RMSE table");
+        qualityTable.VisualProperties.YAxisLogScale = true;
+        var trainRMSERow = new DataRow("RMSE (train)");
+        trainRMSERow.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+        var testRMSERow = new DataRow("RMSE test");
+        testRMSERow.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+
+        qualityTable.Rows.Add(trainRMSERow);
+        qualityTable.Rows.Add(testRMSERow);
+        Results.Add(new Result(qualityTable.Name, qualityTable.Name + " for all restarts", qualityTable));
+        if (SetSeedRandomly) Seed = (new System.Random()).Next();
+        var rand = new MersenneTwister((uint)Seed);
+        bestSolution = CreateRegressionSolution(Problem.ProblemData, ModelStructure, Iterations, rand);
+        trainRMSERow.Values.Add(bestSolution.TrainingRootMeanSquaredError);
+        testRMSERow.Values.Add(bestSolution.TestRootMeanSquaredError);
+        for (int r = 0; r < Restarts; r++) {
+          var solution = CreateRegressionSolution(Problem.ProblemData, ModelStructure, Iterations, rand);
+          trainRMSERow.Values.Add(solution.TrainingRootMeanSquaredError);
+          testRMSERow.Values.Add(solution.TestRootMeanSquaredError);
+          if (solution.TrainingRootMeanSquaredError < bestSolution.TrainingRootMeanSquaredError) {
+            bestSolution = solution;
+          }
+        }
+      } else {
+        bestSolution = CreateRegressionSolution(Problem.ProblemData, ModelStructure, Iterations);
+      }
+
+      Results.Add(new Result(RegressionSolutionResultName, "The nonlinear regression solution.", bestSolution));
+      Results.Add(new Result("Root mean square error (train)", "The root of the mean of squared errors of the regression solution on the training set.", new DoubleValue(bestSolution.TrainingRootMeanSquaredError)));
+      Results.Add(new Result("Root mean square error (test)", "The root of the mean of squared errors of the regression solution on the test set.", new DoubleValue(bestSolution.TestRootMeanSquaredError)));
+
+    }
+
+    /// <summary>
+    /// Fits a model to the data by optimizing the numeric constants.
+    /// Model is specified as infix expression containing variable names and numbers. 
+    /// The starting point for the numeric constants is initialized randomly if a random number generator is specified (~N(0,1)). Otherwise the user specified constants are
+    /// used as a starting point. 
+    /// </summary>-
+    /// <param name="problemData">Training and test data</param>
+    /// <param name="modelStructure">The function as infix expression</param>
+    /// <param name="maxIterations">Number of constant optimization iterations (using Levenberg-Marquardt algorithm)</param>
+    /// <param name="random">Optional random number generator for random initialization of numeric constants.</param>
+    /// <returns></returns>
+    public static ISymbolicRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData, string modelStructure, int maxIterations, IRandom rand = null) {
       var parser = new InfixExpressionParser();
       var tree = parser.Parse(modelStructure);
-      var simplifier = new SymbolicDataAnalysisExpressionTreeSimplifier();
-      
+
       if (!SymbolicRegressionConstantOptimizationEvaluator.CanOptimizeConstants(tree)) throw new ArgumentException("The optimizer does not support the specified model structure.");
 
+      // initialize constants randomly
+      if (rand != null) {
+        foreach (var node in tree.IterateNodesPrefix().OfType<ConstantTreeNode>()) {
+          double f = Math.Exp(NormalDistributedRandom.NextDouble(rand, 0, 1));
+          double s = rand.NextDouble() < 0.5 ? -1 : 1;
+          node.Value = s * node.Value * f;
+        }
+      }
       var interpreter = new SymbolicDataAnalysisExpressionTreeLinearInterpreter();
-      SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, tree, problemData, problemData.TrainingIndices, 
+
+      SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, tree, problemData, problemData.TrainingIndices,
         applyLinearScaling: false, maxIterations: maxIterations,
         updateVariableWeights: false, updateConstantsInTree: true);
-
 
       var scaledModel = new SymbolicRegressionModel(problemData.TargetVariable, tree, (ISymbolicDataAnalysisExpressionTreeInterpreter)interpreter.Clone());
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs	(revision 14563)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs	(revision 14564)
@@ -81,4 +81,13 @@
           }
           strBuilder.Append(")");
+        } else {
+          // function with multiple arguments
+          strBuilder.Append(token).Append("(");
+          FormatRecursively(node.Subtrees.First(), strBuilder);
+          foreach (var subtree in node.Subtrees.Skip(1)) {
+            strBuilder.Append(", ");
+            FormatRecursively(subtree, strBuilder);
+          }
+          strBuilder.Append(")");
         }
       } else if (node.SubtreeCount == 1) {
@@ -94,5 +103,5 @@
           FormatRecursively(node.GetSubtree(0), strBuilder);
         } else {
-          // function
+          // function with only one argument
           strBuilder.Append(token).Append("(");
           FormatRecursively(node.GetSubtree(0), strBuilder);
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs	(revision 14563)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs	(revision 14564)
@@ -37,5 +37,5 @@
   /// </summary>
   public sealed class InfixExpressionParser {
-    private enum TokenType { Operator, Identifier, Number, LeftPar, RightPar, End, NA };
+    private enum TokenType { Operator, Identifier, Number, LeftPar, RightPar, Comma, End, NA };
     private class Token {
       internal double doubleVal;
@@ -102,6 +102,6 @@
         { "MEAN", new Average()},
         { "IF", new IfThenElse()},
-        { ">", new GreaterThan()},
-        { "<", new LessThan()},
+        { "GT", new GreaterThan()},
+        { "LT", new LessThan()},
         { "AND", new And()},
         { "OR", new Or()},
@@ -138,14 +138,15 @@
         }
         if (char.IsDigit(str[pos])) {
-          // read number (=> read until white space or operator)
+          // read number (=> read until white space or operator or comma)
           var sb = new StringBuilder();
           sb.Append(str[pos]);
           pos++;
           while (pos < str.Length && !char.IsWhiteSpace(str[pos])
-            && (str[pos] != '+' || str[pos-1] == 'e' || str[pos-1] == 'E')     // continue reading exponents
+            && (str[pos] != '+' || str[pos - 1] == 'e' || str[pos - 1] == 'E')     // continue reading exponents
             && (str[pos] != '-' || str[pos - 1] == 'e' || str[pos - 1] == 'E')
-            && str[pos] != '*'           
+            && str[pos] != '*'
             && str[pos] != '/'
-            && str[pos] != ')') {
+            && str[pos] != ')'
+            && str[pos] != ',') {
             sb.Append(str[pos]);
             pos++;
@@ -211,12 +212,18 @@
           pos++;
           yield return new Token { TokenType = TokenType.RightPar, strVal = ")" };
-        }
-      }
-    }
-
-    // S = Expr EOF
-    // Expr = ['-' | '+'] Term { '+' Term | '-' Term }
-    // Term = Fact { '*' Fact | '/' Fact }
-    // Fact = '(' Expr ')' | funcId '(' Expr ')' | varId | number
+        } else if (str[pos] == ',') {
+          pos++;
+          yield return new Token { TokenType = TokenType.Comma, strVal = "," };
+        } else {
+          throw new ArgumentException("Invalid character: " + str[pos]);
+        }
+      }
+    }
+
+    // S       = Expr EOF
+    // Expr    = ['-' | '+'] Term { '+' Term | '-' Term }
+    // Term    = Fact { '*' Fact | '/' Fact }
+    // Fact    = '(' Expr ')' | funcId '(' ArgList ')' | varId | number
+    // ArgList = Expr { ',' Expr }
     private ISymbolicExpressionTreeNode ParseS(Queue<Token> tokens) {
       var expr = ParseExpr(tokens);
@@ -326,5 +333,5 @@
     }
 
-    // Fact = '(' Expr ')' | funcId '(' Expr ')' | varId | number
+    // Fact = '(' Expr ')' | funcId '(' ArgList ')' | varId | number
     private ISymbolicExpressionTreeNode ParseFact(Queue<Token> tokens) {
       var next = tokens.Peek();
@@ -346,10 +353,16 @@
           if (lPar.TokenType != TokenType.LeftPar)
             throw new ArgumentException("expected (");
-          var expr = ParseExpr(tokens);
+          var args = ParseArgList(tokens);
+
+          // check semantic constraints
+          if (funcNode.Symbol.MinimumArity > args.Length || funcNode.Symbol.MaximumArity < args.Length)
+            throw new ArgumentException(string.Format("Symbol {0} requires between {1} and  {2} arguments.", funcId,
+              funcNode.Symbol.MinimumArity, funcNode.Symbol.MaximumArity));
+          foreach (var arg in args) funcNode.AddSubtree(arg);
+
           var rPar = tokens.Dequeue();
           if (rPar.TokenType != TokenType.RightPar)
             throw new ArgumentException("expected )");
 
-          funcNode.AddSubtree(expr);
           return funcNode;
         } else {
@@ -369,4 +382,16 @@
       }
     }
+
+    // ArgList = Expr { ',' Expr }
+    private ISymbolicExpressionTreeNode[] ParseArgList(Queue<Token> tokens) {
+      var exprList = new List<ISymbolicExpressionTreeNode>();
+      exprList.Add(ParseExpr(tokens));
+      while (tokens.Peek().TokenType != TokenType.RightPar) {
+        var comma = tokens.Dequeue();
+        if (comma.TokenType != TokenType.Comma) throw new ArgumentException("expected ',' ");
+        exprList.Add(ParseExpr(tokens));
+      }
+      return exprList.ToArray();
+    }
   }
 }
Index: /stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/InfixExpressionParserTest.cs
===================================================================
--- /stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/InfixExpressionParserTest.cs	(revision 14563)
+++ /stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/InfixExpressionParserTest.cs	(revision 14564)
@@ -86,4 +86,19 @@
       Console.WriteLine(formatter.Format(parser.Parse("x1*x2+x3*x4")));
 
+
+      Console.WriteLine(formatter.Format(parser.Parse("POW(3, 2)")));
+      Console.WriteLine(formatter.Format(parser.Parse("POW(3.1, 2.1)")));
+      Console.WriteLine(formatter.Format(parser.Parse("POW(3.1 , 2.1)")));
+      Console.WriteLine(formatter.Format(parser.Parse("POW(3.1 ,2.1)")));
+      Console.WriteLine(formatter.Format(parser.Parse("POW(-3.1 , - 2.1)")));
+      Console.WriteLine(formatter.Format(parser.Parse("ROOT(3, 2)")));
+      Console.WriteLine(formatter.Format(parser.Parse("ROOT(3.1, 2.1)")));
+      Console.WriteLine(formatter.Format(parser.Parse("ROOT(3.1 , 2.1)")));
+      Console.WriteLine(formatter.Format(parser.Parse("ROOT(3.1 ,2.1)")));
+      Console.WriteLine(formatter.Format(parser.Parse("ROOT(-3.1 , - 2.1)")));
+
+      Console.WriteLine(formatter.Format(parser.Parse("IF(GT( 0, 1), 1, 0)")));
+      Console.WriteLine(formatter.Format(parser.Parse("IF(LT(0,1), 1 , 0)")));
+
     }
   }
