Index: /branches/2968_infix_string_formatter/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionStringFormatter.cs
===================================================================
--- /branches/2968_infix_string_formatter/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionStringFormatter.cs	(revision 16339)
+++ /branches/2968_infix_string_formatter/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionStringFormatter.cs	(revision 16339)
@@ -0,0 +1,178 @@
+﻿using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using System.Collections.Generic;
+using HeuristicLab.Common;
+using System.Text;
+using System.Globalization;
+using System.Linq;
+using System;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Formatters {
+  [Item("Infix String Formater", "Formatter for symbolic expressions, which produces an infix expression " +
+    "as well as a list of all coefficient values")]
+  [StorableClass]
+  public sealed class InfixExpressionStringFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter {
+    private readonly List<KeyValuePair<string, double>> constants;
+    private static int constantCounter = 0;
+
+    [StorableConstructor]
+    private InfixExpressionStringFormatter(bool deserializing): base(deserializing) {}
+    private InfixExpressionStringFormatter(InfixExpressionStringFormatter original, Cloner cloner) 
+      : base(original, cloner) {
+      constants = new List<KeyValuePair<string, double>>(original.constants);
+    }
+    public InfixExpressionStringFormatter() : base() {
+      Name = ItemName;
+      Description = ItemDescription;
+      constants = new List<KeyValuePair<string, double>>();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new InfixExpressionStringFormatter(this, cloner);
+    }
+
+    public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
+      StringBuilder strBuilder = new StringBuilder();
+      FormatRecursively(symbolicExpressionTree.Root.GetSubtree(0).GetSubtree(0), strBuilder);
+      strBuilder.Append($"{Environment.NewLine}{Environment.NewLine}");
+      foreach (var constant in constants) {
+        strBuilder.Append($"{constant.Key} = {constant.Value}{Environment.NewLine}");
+      }
+      return strBuilder.ToString();
+    }
+
+    private void FormatRecursively(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      if (node.SubtreeCount > 1) {
+        var token = GetToken(node.Symbol);
+        if (token == "+" || token == "-" || token == "OR" || token == "XOR") {
+          strBuilder.Append("(");
+          FormatRecursively(node.Subtrees.First(), strBuilder);
+
+          foreach (var subtree in node.Subtrees.Skip(1)) {
+            strBuilder.Append(" ").Append(token).Append(" ");
+            FormatRecursively(subtree, strBuilder);
+          }
+          strBuilder.Append(")");
+
+        } else if (token == "*" || token == "/" || token == "AND") {
+          strBuilder.Append("(");
+          FormatRecursively(node.Subtrees.First(), strBuilder);
+
+          foreach (var subtree in node.Subtrees.Skip(1)) {
+            strBuilder.Append(" ").Append(token).Append(" ");
+            FormatRecursively(subtree, strBuilder);
+          }
+          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) {
+        var token = GetToken(node.Symbol);
+        if (token == "-" || token == "NOT") {
+          strBuilder.Append("(").Append(token).Append("(");
+          FormatRecursively(node.GetSubtree(0), strBuilder);
+          strBuilder.Append("))");
+        } else if (token == "/") {
+          strBuilder.Append("1/");
+          FormatRecursively(node.GetSubtree(0), strBuilder);
+        } else if (token == "+" || token == "*") {
+          FormatRecursively(node.GetSubtree(0), strBuilder);
+        } else {
+          // function with only one argument
+          strBuilder.Append(token).Append("(");
+          FormatRecursively(node.GetSubtree(0), strBuilder);
+          strBuilder.Append(")");
+        }
+      } else {
+        if (node.Symbol is LaggedVariable) {
+          var varNode = node as LaggedVariableTreeNode;
+          if (!varNode.Weight.IsAlmost(1.0)) {
+            strBuilder.Append("(");
+            strBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}", varNode.Weight);
+            strBuilder.Append("*");
+          }
+          strBuilder.Append("LAG(");
+          if (varNode.VariableName.Contains("'")) {
+            strBuilder.AppendFormat("\"{0}\"", varNode.VariableName);
+          } else {
+            strBuilder.AppendFormat("'{0}'", varNode.VariableName);
+          }
+          strBuilder.Append(", ")
+            .AppendFormat(CultureInfo.InvariantCulture, "{0}", varNode.Lag)
+            .Append(")");
+        } else if (node.Symbol is Variable) {
+          var varNode = node as VariableTreeNode;
+          if (!varNode.Weight.IsAlmost(1.0)) {
+            string constantKey = $"c_{constantCounter}";
+            strBuilder.Append("(");
+            strBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}", constantKey);
+            strBuilder.Append("*");
+            constants.Add(new KeyValuePair<string, double>(constantKey, varNode.Weight));
+            constantCounter++;
+          }
+          if (varNode.VariableName.Contains("'")) {
+            strBuilder.AppendFormat("\"{0}\"", varNode.VariableName);
+          } else {
+            strBuilder.AppendFormat("'{0}'", varNode.VariableName);
+          }
+          if (!varNode.Weight.IsAlmost(1.0)) {
+            strBuilder.Append(")");
+          }
+        } else if (node.Symbol is FactorVariable) {
+          var factorNode = node as FactorVariableTreeNode;
+          if (factorNode.VariableName.Contains("'")) {
+            strBuilder.AppendFormat("\"{0}\"", factorNode.VariableName);
+          } else {
+            strBuilder.AppendFormat("'{0}'", factorNode.VariableName);
+          }
+          strBuilder.AppendFormat("[{0}]",
+            string.Join(", ", factorNode.Weights.Select(w => w.ToString(CultureInfo.InvariantCulture))));
+        } else if (node.Symbol is BinaryFactorVariable) {
+          var factorNode = node as BinaryFactorVariableTreeNode;
+          if (!factorNode.Weight.IsAlmost(1.0)) {
+            strBuilder.Append("(");
+            strBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}", factorNode.Weight);
+            strBuilder.Append("*");
+          }
+          if (factorNode.VariableName.Contains("'")) {
+            strBuilder.AppendFormat("\"{0}\"", factorNode.VariableName);
+          } else {
+            strBuilder.AppendFormat("'{0}'", factorNode.VariableName);
+          }
+          strBuilder.Append(" = ");
+          if (factorNode.VariableValue.Contains("'")) {
+            strBuilder.AppendFormat("\"{0}\"", factorNode.VariableValue);
+          } else {
+            strBuilder.AppendFormat("'{0}'", factorNode.VariableValue);
+          }
+
+          if (!factorNode.Weight.IsAlmost(1.0)) {
+            strBuilder.Append(")");
+          }
+
+        } else if (node.Symbol is Constant) {
+          var constNode = node as ConstantTreeNode;
+          string constantKey = $"c_{constantCounter}";
+
+          strBuilder.AppendFormat(CultureInfo.InvariantCulture, constantKey);
+          constants.Add(new KeyValuePair<string, double>(constantKey, constNode.Value));
+          constantCounter++;
+        }
+      }
+    }
+
+    private string GetToken(ISymbol symbol) {
+      var tok = InfixExpressionParser.knownSymbols.GetBySecond(symbol).SingleOrDefault();
+      if (tok == null)
+        throw new ArgumentException(string.Format("Unknown symbol {0} found.", symbol.Name));
+      return tok;
+    }
+  }
+}
Index: /branches/2968_infix_string_formatter/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- /branches/2968_infix_string_formatter/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 16338)
+++ /branches/2968_infix_string_formatter/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 16339)
@@ -41,5 +41,5 @@
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
-    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
@@ -51,5 +51,5 @@
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
-    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <OutputPath>..\..\..\..\bin\</OutputPath>
     <DefineConstants>TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
@@ -60,5 +60,5 @@
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
     <DebugSymbols>true</DebugSymbols>
-    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <OutputPath>..\..\..\..\bin\</OutputPath>
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <DebugType>full</DebugType>
@@ -69,5 +69,5 @@
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
-    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <OutputPath>..\..\..\..\bin\</OutputPath>
     <DefineConstants>TRACE</DefineConstants>
     <Optimize>true</Optimize>
@@ -80,5 +80,5 @@
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
     <DebugSymbols>true</DebugSymbols>
-    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <OutputPath>..\..\..\..\bin\</OutputPath>
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <DebugType>full</DebugType>
@@ -89,5 +89,5 @@
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
-    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <OutputPath>..\..\..\..\bin\</OutputPath>
     <DefineConstants>TRACE</DefineConstants>
     <Optimize>true</Optimize>
@@ -207,4 +207,5 @@
     <Compile Include="Interpreter\BatchInstruction.cs" />
     <Compile Include="Interpreter\BatchOperations.cs" />
+    <Compile Include="Formatters\InfixExpressionStringFormatter.cs" />
     <Compile Include="Interpreter\SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs" />
     <Compile Include="Interpreter\SymbolicDataAnalysisExpressionTreeBatchInterpreter.cs" />
