Index: /branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/MultiTest.ps1
===================================================================
--- /branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/MultiTest.ps1	(revision 16614)
+++ /branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/MultiTest.ps1	(revision 16614)
@@ -0,0 +1,50 @@
+[cmdletbinding()]
+param(
+    [int] $WaitToStep = 200,
+    [int] $PeelCnt = 3,
+    [int] $EvalCnt = 3,
+    [ValidateSet("method1","method2", "method3")][string] $InitMethod = "method1",
+    [ValidateSet("method1","method2", "method3")][string] $GrowMethod = "method1",
+    [int] $MaxJobs = 30,
+    [switch] $Clear
+)
+
+$BenchmarksPath = Resolve-Path -Relative "go-code\go-pge\data\benchmark"
+
+$Clean = $false
+if($Clear) {
+    $Clean = $true
+}
+
+$BenchFiles = Get-ChildItem -Path $BenchmarksPath -File
+$ActiveJobs = @{}
+foreach($BenchName in $($BenchFiles | Select-Object -ExpandProperty BaseName -Unique)) {
+    $RunningCnt = ($ActiveJobs.Values | Where-Object { $_.State -eq "Running" }).Count
+    while ($RunningCnt -gt $MaxJobs) {
+        Start-Sleep -Seconds 1
+        $RunningCnt = ($ActiveJobs.Values | Where-Object { $_.State -eq "Running" }).Count
+    }
+    $ActiveJobs[$BenchName] = Start-Job -ScriptBlock {
+        param($PSPath, $WaitToStep, $BenchName, $PeelCnt, $EvalCnt, $InitMethod, $GrowMethod, $Clear)
+        Set-Location -Path $PSPath
+        ./TestResults -WaitToStep $WaitToStep -BenchName $BenchName -PeelCnt $PeelCnt -EvalCnt $EvalCnt -InitMethod $InitMethod -GrowMethod $GrowMethod *>&1
+    } -ArgumentList $(Resolve-Path $PSScriptRoot), $WaitToStep, $BenchName, $PeelCnt, $EvalCnt, $InitMethod, $GrowMethod, $Clean
+    Write-Host "Started job for $BenchName"
+}
+
+$ActiveJobs.Values | Wait-Job | Out-Null
+foreach($BenchName in $ActiveJobs.Keys) {
+    $Job = $ActiveJobs[$BenchName]
+    $Res = $Job | Receive-Job
+    $Succeeded = ($Res | Select-String -Pattern "^[0-9]+\sOK").Count
+    $Failed = ($Res | Select-String -Pattern "^[0-9]+\sfailed!").Count
+    if($($Succeeded + $Failed) -ne $WaitToStep ) {
+        Write-Error "Something went wrong!? Please check manuelly"
+    }
+    if($Succeeded -eq $WaitToStep) {
+        Write-Host "$($BenchName): $Succeeded / $WaitToStep tests succeeded"
+    } else {
+        Write-Warning "$($BenchName): $Failed / $WaitToStep tests failed!"
+    }
+}
+Get-Job | Remove-Job -Force | Out-Null
Index: /branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/PGE.cs
===================================================================
--- /branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/PGE.cs	(revision 16613)
+++ /branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/PGE.cs	(revision 16614)
@@ -34,5 +34,5 @@
 
     [DllImport("go-pge.dll", EntryPoint = "initTreeParams", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
-    public static extern void InitTreeParams(IntPtr roots, IntPtr nodes, IntPtr nonTrig, IntPtr leafs, IntPtr usableVars, int numUsableVars, int maxSize, int minSize, int maxDepth, int minDepth);
+    public static extern void InitTreeParams(IntPtr roots, IntPtr nodes, IntPtr nonTrig, IntPtr leafs, int numUsableVars, int maxSize, int minSize, int maxDepth, int minDepth);
 
     [DllImport("go-pge.dll", EntryPoint = "initProblem", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
@@ -43,5 +43,5 @@
 
     [DllImport("go-pge.dll", EntryPoint = "getStepResult", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
-    public static extern IntPtr GetStepResult(out int noBestPush, out int bestNewMinErr, out int bestlen1, out int bestlen2, out int testscore, out int nCoeff);
+    public static extern IntPtr GetStepResult(out int testscore, out int nCoeff);
 
     [DllImport("go-pge.dll", EntryPoint = "getCoeffResult", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
@@ -345,12 +345,10 @@
 
       int numberOfUseableVariables = problemData.AllowedInputVariables.Count();
-      IntPtr cUseableVars = GetUsableVars(numberOfUseableVariables);
 
       InitSearch(MaxGen, PgeRptEpoch, PgeRptCount, PgeArchiveCap, PeelCnt, EvalrCount, ZeroEpsilon, cInitMethod, cGrowMethod, sortType);
 
       // cUsableVars: list of indices into independent variables
-      InitTreeParams(cRoots, cNodes, cNonTrig, cLeafs, cUseableVars, numberOfUseableVariables, MaxSize, MinSize, MaxDepth, MinDepth);
-
-      
+      InitTreeParams(cRoots, cNodes, cNonTrig, cLeafs, numberOfUseableVariables, MaxSize, MinSize, MaxDepth, MinDepth);
+
       InitProblem(cName, MaxIterations, HitRatio, 
         searchVar: 0,  // SearchVar: index of dependent variables (this is always zero because we only have one target variable)
@@ -364,12 +362,8 @@
 
         for (int iResult = 0; iResult < nResults; iResult++) {
-          int nobestpush = 0;       //bool
-          int bestNewMinError = 0;  //bool
-          int bestlen1 = 0;
-          int bestlen2 = 0;
           int nCoeff = 0;
           int testScore = 0;
 
-          IntPtr eqn = GetStepResult(out nobestpush, out bestNewMinError, out bestlen1, out bestlen2, out testScore, out nCoeff);
+          IntPtr eqn = GetStepResult(out testScore, out nCoeff);
           string eqnStr = Marshal.PtrToStringAnsi(eqn);
 
@@ -378,7 +372,7 @@
             coeff[iCoeff] = GetCoeffResult();
           }
-          log.LogMessage("Push/Pop (" + iResult + ", " + bestlen1 + ", " + bestlen2 + ", " + testScore + ", noBestPush: " + (nobestpush > 0) + ", bestNewMin: " + (bestNewMinError > 0) + ") " + eqnStr + " coeff: " + string.Join(" ", coeff));
-
-          if (!string.IsNullOrEmpty(eqnStr) && (testScore < bestTestScore || bestNewMinError > 0)) {
+          log.LogMessage("Push/Pop (" + iResult + ", " + testScore + ") " + eqnStr + " coeff: " + string.Join(" ", coeff));
+
+          if (!string.IsNullOrEmpty(eqnStr) && (testScore < bestTestScore)) {
             // update best quality
             bestTestScore = testScore;
@@ -389,6 +383,4 @@
           bestTestScoreRow.Values.Add(bestTestScoreResult.Value); // always add the current best test score to data row
           curTestScoreRow.Values.Add(testScore);
-          len1Row.Values.Add(bestlen1);
-          len2Row.Values.Add(bestlen2);
         }
 
@@ -396,5 +388,4 @@
       }
 
-      Marshal.FreeHGlobal(cUseableVars);
       Marshal.FreeHGlobal(trainData);
       Marshal.FreeHGlobal(testData);
@@ -453,17 +444,4 @@
     }
 
-    private static IntPtr GetUsableVars(int n) {
-      long[] vars = new long[n];
-
-      for (int i = 0; i < n; i++) {
-        vars[i] = i;
-      }
-
-      IntPtr usableVars = Marshal.AllocHGlobal(sizeof(long) * n);
-      Marshal.Copy(vars, 0, usableVars, n);
-
-      return usableVars;
-    }
-
     private static IntPtr GetData(IDataset ds, IEnumerable<string> variableNames, IEnumerable<int> rows, out int n) {
 
Index: /branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/TestResults.ps1
===================================================================
--- /branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/TestResults.ps1	(revision 16613)
+++ /branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/TestResults.ps1	(revision 16614)
@@ -1,17 +1,39 @@
-﻿param(
-    [switch] $GenerateNew = $true,
-    [int] $WaitToStep = 200
+﻿[cmdletbinding()]
+param(
+    [int] $WaitToStep = 200,
+    [string] $BenchName = "Pagie_1",
+    [int] $PeelCnt = 3,
+    [int] $EvalCnt = 3,
+    [ValidateSet("method1","method2", "method3")][string] $InitMethod = "method1",
+    [ValidateSet("method1","method2", "method3")][string] $GrowMethod = "method1",
+    [bool] $Clear
 )
 
+$GenerateNew = $true
 
-$CLog = Join-Path -Path $(Resolve-Path $PSScriptRoot) -ChildPath 'CGen.log'
-$GoLog = Join-Path -Path $(Resolve-Path $PSScriptRoot) -ChildPath 'GoOut.log'
+$CLog = Join-Path -Path $(Resolve-Path $PSScriptRoot) -ChildPath "CGen_$($BenchName).log"
+$GoLog = Join-Path -Path $(Resolve-Path $PSScriptRoot) -ChildPath "GoOut_$($BenchName).log"
 
-$CExecutable = Join-Path -Path $(Resolve-Path $PSScriptRoot) -ChildPath 'a.exe'
+$CLogError = Join-Path -Path $(Resolve-Path $PSScriptRoot) -ChildPath "CGen_$($BenchName).err"
+$GoLogError = Join-Path -Path $(Resolve-Path $PSScriptRoot) -ChildPath "GoOut_$($BenchName).err"
+
+$CExecutable = Join-Path -Path $(Resolve-Path $PSScriptRoot) -ChildPath 'testmulti.exe'
 $GoExecutable = Join-Path -Path $(Resolve-Path $PSScriptRoot) -ChildPath 'go-code\go-pge\go-pge.exe'
 
-
 if($GenerateNew) {
-    $CGenProc = Start-Process -FilePath $CExecutable -RedirectStandardOutput $CLog -WorkingDirectory $PSScriptRoot -PassThru
+	if(Test-Path $GoLog -Type Leaf) {
+		Remove-Item -Path $GoLog
+	}
+	if(Test-Path $CLog -Type Leaf) {
+		Remove-Item -Path $CLog
+    }
+    if(Test-Path $GoLogError -Type Leaf) {
+        Remove-Item -Path $GoLogError
+    }
+    if(Test-Path $CLogError -Type Leaf) {
+        Remove-Item -Path $CLogError
+    }
+	
+    $CGenProc = Start-Process -FilePath $CExecutable -ArgumentList "$BenchName -evals=$($EvalCnt) -peel=$($PeelCnt) -iter=$($WaitToStep) -init=$($InitMethod) -grow=$($GrowMethod)" -RedirectStandardOutput $CLog -RedirectStandardError $CLogError -WorkingDirectory $PSScriptRoot -PassThru
     $StepReached = $false
     while(-not $StepReached) {
@@ -25,6 +47,8 @@
     $CGenProc  | Stop-Process -ErrorAction SilentlyContinue
 
-
-    $GoGenProc = Start-Process -FilePath $GoExecutable -ArgumentList "-pcfg=prob/bench/Pagie_1.cfg -evals=3 -peel=3 -iter=$WaitToStep -init=method1 -grow=method1"  -RedirectStandardOutput $GoLog -WorkingDirectory $(Join-Path -Path $PSScriptRoot -ChildPath 'go-code\go-pge') -PassThru
+	$env:GOGC="off"
+	$env:GODEBUG="cgocheck=0"
+	$env:CGO_ENABLED=1
+    $GoGenProc = Start-Process -FilePath $GoExecutable -ArgumentList "-pcfg=prob/bench/$($BenchName).cfg -evals=$($EvalCnt) -peel=$($PeelCnt) -iter=$($WaitToStep) -init=$($InitMethod) -grow=$($GrowMethod)"  -RedirectStandardOutput $GoLog -RedirectStandardError $GoLogError -WorkingDirectory $(Split-Path -Path $GoExecutable -Parent) -PassThru
     $StepReached = $false
     while(-not $StepReached) {
@@ -48,6 +72,6 @@
             [int]$CurrentStep = $Matches[1]
             $ValueList[$CurrentStep] = $(New-Object -TypeName System.Collections.ArrayList)
-        } elseif($Line -match "push\/pop \(\d+\,\d+\) \((.+)\)") {
-            $ValueList[$CurrentStep].Add($Matches[1].Trim().Replace(' ', '')) | Out-Null
+        } elseif($Line -match "push\/pop \(\d+\,\d+\) (.+)") {
+            $ValueList[$CurrentStep].Add($Matches[1].Trim().Replace('(', '').Replace(')', '').Replace(' ', '')) | Out-Null
         }
     }
@@ -64,5 +88,5 @@
             $ValueList[$CurrentStep] = $(New-Object -TypeName System.Collections.ArrayList)
         } elseif($Line -match "pop\/push\(\d+\,\d+\)\: (.+)") {
-            $ValueList[$CurrentStep].Add($Matches[1].Trim().Trim('(').Trim(')').Replace(' ', '')) | Out-Null
+            $ValueList[$CurrentStep].Add($Matches[1].Trim().Replace('(', '').Replace(')', '').Replace(' ', '')) | Out-Null
         }
     }
@@ -75,6 +99,6 @@
         [string]$Second
     )
-    $FirstChars = $First.Trim().ToUpper().ToCharArray() | Sort
-    $SecondChars = $Second.Trim().ToUpper().ToCharArray() | Sort
+    $FirstChars = $First.Trim().ToUpper().ToCharArray() | Sort-Object
+    $SecondChars = $Second.Trim().ToUpper().ToCharArray() | Sort-Object
 
     [System.Collections.ArrayList]$LeftChars = $SecondChars.Clone()
@@ -98,14 +122,14 @@
 $ParseGo = Get-GoSteps -Content $GoContent
 
-foreach($StepNr in $($ParseGo.Keys | Sort)) {
+foreach($StepNr in $($ParseGo.Keys | Sort-Object | Where-Object { $_ -ne 0 -and $_ -le $WaitToStep})) {
     $GoResult = $ParseGo[$StepNr]
-    [System.Collections.ArrayList]$CResult = $ParseC[$StepNr + 1]
+    [System.Collections.ArrayList]$CResult = $ParseC[$StepNr]
 
-    if($CResult -eq $null -or $CResult.Count -lt 1) {
-        Write-Information "Missing CStep nr. $StepNr"
+    if($null -eq $CResult -or $CResult.Count -lt 1) {
+        Write-Warning "Missing CStep nr. $StepNr"
         continue
     }
-    if($GoResult -eq $null -or $GoResult.Count -lt 1) {
-        Write-Information "Missing GoStep nr. $StepNr"
+    if($null -eq $GoResult -or $GoResult.Count -lt 1) {
+        Write-Warning "Missing GoStep nr. $StepNr"
         continue
     }
@@ -115,5 +139,5 @@
         $State = $false
         foreach($CRes in $CResult.Clone()) {  # Compare every Result with every Step Result
-            Write-Debug "$($GoRes) with $($CRes)"
+            Write-Output "$($GoRes) with $($CRes)"
             if(Compare-Results -First $GoRes -Second $CRes) {
                 $State = $true
@@ -128,7 +152,22 @@
 
     if($StepResult) {
-        Write-Host "$StepNr OK"
+        Write-Output "$StepNr OK"
     } else {
         Write-Warning "$StepNr failed!"
     }
 }
+
+if($Clear) {
+    if(Test-Path $GoLog -Type Leaf) {
+        Remove-Item -Path $GoLog
+    }
+    if(Test-Path $CLog -Type Leaf) {
+        Remove-Item -Path $CLog
+    }
+    if(Test-Path $GoLogError -Type Leaf) {
+        Remove-Item -Path $GoLogError
+    }
+    if(Test-Path $CLogError -Type Leaf) {
+        Remove-Item -Path $CLogError
+    }
+}
Index: /branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/go-code/go-pge/pge/all.go
===================================================================
--- /branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/go-code/go-pge/pge/all.go	(revision 16614)
+++ /branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/go-code/go-pge/pge/all.go	(revision 16614)
@@ -0,0 +1,1651 @@
+package main
+
+import (
+	"bufio"
+	"fmt"
+	"io/ioutil"
+	"log"
+	"math"
+	"os"
+	"strconv"
+	"strings"
+	"sort"
+	"C"
+	levmar "github.com_del/verdverm/go-levmar"
+	config "github.com_del/verdverm/go-pge/config"
+	probs "github.com_del/verdverm/go-pge/problems"
+	expr "github.com_del/verdverm/go-symexpr"
+)
+
+var c_input, c_ygiven []levmar.C_double
+
+func main() {
+	
+}
+
+//export GenInitExprMethod1
+func (PS *PgeSearch) GenInitExprMethod1() *probs.ReportQueue {
+	fmt.Printf("generating initial expressions\n")
+
+	GP := PS.cnfg.treecfg
+	fmt.Printf("%v\n", GP)
+
+	eList := make([]expr.Expr, 0)
+
+	for _, T := range GP.Roots {
+		switch T.ExprType() {
+		case expr.ADD:
+			eList = append(eList, PS.GenInitExprAddMethod1()[:]...)
+		case expr.MUL:
+			eList = append(eList, PS.GenInitExprMulMethod1()[:]...)
+		case expr.DIV:
+			eList = append(eList, PS.GenInitExprDivMethod1()[:]...)
+		default:
+			fmt.Printf("Error in GenInitExpr: unknown ROOT %d\n", T)
+		}
+	}
+
+	exprs := probs.NewReportQueue()
+	// exprs.SetSort(PS.cnfg.sortType)
+	exprs.SetSort(probs.PESORT_PARETO_TST_ERR)
+
+	for i, e := range eList {
+		fmt.Printf("%d:  %v\n", i, e)
+		serial := make([]int, 0, 64)
+		serial = e.Serial(serial)
+		PS.Trie.InsertSerial(serial)
+		// on train data
+		re := RegressExpr(e, PS.prob)
+		re.SetUnitID(i)
+		exprs.Push(re)
+	}
+	exprs.Sort()
+	return exprs
+}
+
+
+
+
+// This is the FFXish style init function
+//export GenInitExprMethod2
+func (PS *PgeSearch) GenInitExprMethod2() *probs.ReportQueue {
+	fmt.Printf("generating initial expressions\n")
+
+	GP := PS.cnfg.treecfg
+	fmt.Printf("%v\n", GP)
+
+	bases := make([]expr.Expr, 0)
+
+	// single constant
+	bases = append(bases, expr.NewConstant(-1))
+
+	// c*x_i
+	for _, v := range PS.prob.UsableVars {
+		mul := expr.NewMul()
+		mul.Insert(expr.NewConstant(-1))
+		mul.Insert(expr.NewVar(v))
+		bases = append(bases, mul)
+	}
+
+	// c*x_i^p & c*x_i^-p
+	for p := 2; p <= 4; p++ {
+		for _, v := range PS.prob.UsableVars {
+			// positive powers
+			mul := expr.NewMul()
+			mul.Insert(expr.NewConstant(-1))
+			mul.Insert(expr.NewPowI(expr.NewVar(v), p))
+			bases = append(bases, mul)
+
+			// negative powers
+			nul := expr.NewMul()
+			nul.Insert(expr.NewConstant(-1))
+			nul.Insert(expr.NewPowI(expr.NewVar(v), -p))
+			bases = append(bases, nul)
+		}
+	}
+
+	// c*N(d*x_i)
+	for _, N := range PS.GenNodes {
+		if N.ExprType() == expr.DIV || N.ExprType() == expr.ADD || N.ExprType() == expr.MUL {
+			continue
+		}
+		for _, v := range PS.prob.UsableVars {
+			// positive powers
+			mul := expr.NewMul()
+			mul.Insert(expr.NewConstant(-1))
+
+			nul := expr.NewMul()
+			nul.Insert(expr.NewConstant(-1))
+			nul.Insert(expr.NewVar(v))
+
+			n := N.Clone()
+			p := 1
+			n.SetExpr(&p, nul)
+			mul.Insert(n)
+			bases = append(bases, mul)
+		}
+	}
+
+	// copy bases for use later in expand
+	PS.ffxBases = make([]expr.Expr, len(bases))
+	for i, b := range bases {
+		PS.ffxBases[i] = b.Clone()
+	}
+
+	exprs := probs.NewReportQueue()
+	// exprs.SetSort(PS.cnfg.sortType)
+	exprs.SetSort(probs.PESORT_PARETO_TST_ERR)
+
+	for i, e := range bases {
+		fmt.Printf("%d:  %v\n", i, e)
+		serial := make([]int, 0, 64)
+		serial = e.Serial(serial)
+		PS.Trie.InsertSerial(serial)
+		// on train data
+		re := RegressExpr(e, PS.prob)
+		re.SetUnitID(i)
+		exprs.Push(re)
+	}
+	exprs.Sort()
+
+	return exprs
+}
+
+// This is the FFXish style init function
+//export GenInitExprMethod3
+func (PS *PgeSearch) GenInitExprMethod3() *probs.ReportQueue {
+	fmt.Printf("generating initial expressions\n")
+
+	GP := PS.cnfg.treecfg
+	fmt.Printf("%v\n", GP)
+
+	bases := make([]expr.Expr, 0)
+
+	// single constant
+	bases = append(bases, expr.NewConstant(-1))
+
+	// c*x_i
+	for _, v := range PS.prob.UsableVars {
+		mul := expr.NewMul()
+		mul.Insert(expr.NewConstant(-1))
+		mul.Insert(expr.NewVar(v))
+		bases = append(bases, mul)
+	}
+
+	// c*x_i^p & c*x_i^-p
+	for p := 2; p <= 4; p++ {
+		for _, v := range PS.prob.UsableVars {
+			// positive powers
+			mul := expr.NewMul()
+			mul.Insert(expr.NewConstant(-1))
+			mul.Insert(expr.NewPowI(expr.NewVar(v), p))
+			bases = append(bases, mul)
+
+			// negative powers
+			nul := expr.NewMul()
+			nul.Insert(expr.NewConstant(-1))
+			nul.Insert(expr.NewPowI(expr.NewVar(v), -p))
+			bases = append(bases, nul)
+		}
+	}
+
+	// c*N(d*x_i)
+	for _, N := range PS.GenNodes {
+		if N.ExprType() == expr.DIV || N.ExprType() == expr.ADD || N.ExprType() == expr.MUL {
+			continue
+		}
+		for _, v := range PS.prob.UsableVars {
+			// positive powers
+			mul := expr.NewMul()
+			mul.Insert(expr.NewConstant(-1))
+
+			nul := expr.NewMul()
+			nul.Insert(expr.NewConstant(-1))
+			nul.Insert(expr.NewVar(v))
+
+			n := N.Clone()
+			p := 1
+			n.SetExpr(&p, nul)
+			mul.Insert(n)
+			bases = append(bases, mul)
+		}
+	}
+
+	// copy bases for use later in expand
+	PS.ffxBases = make([]expr.Expr, len(bases))
+	for i, b := range bases {
+		PS.ffxBases[i] = b.Clone()
+	}
+
+	exprs := probs.NewReportQueue()
+	// exprs.SetSort(PS.cnfg.sortType)
+	exprs.SetSort(probs.PESORT_PARETO_TST_ERR)
+
+	for i, e := range bases {
+		fmt.Printf("%d:  %v\n", i, e)
+		serial := make([]int, 0, 64)
+		serial = e.Serial(serial)
+		PS.Trie.InsertSerial(serial)
+		// on train data
+		re := RegressExpr(e, PS.prob)
+		re.SetUnitID(i)
+		exprs.Push(re)
+	}
+	exprs.Sort()
+
+	return exprs
+}
+
+//export ExpandMethod2
+func (PS *PgeSearch) ExpandMethod2(O expr.Expr) (ret []expr.Expr) {
+	O.Sort()
+	ret = make([]expr.Expr, 0)
+	// fmt.Printf("Expanding expression:  %v\n", O)
+
+	add := O.(*expr.Add)
+
+	// adding term to addition
+	for _, B := range PS.ffxBases {
+		found := false
+		for _, C := range add.CS {
+			// fmt.Printf("checking %v in %v\n", B, add)
+			if C.AmISame(B) {
+				// fmt.Println("found\n\n")
+				found = true
+				break
+			}
+		}
+		if !found {
+			e := O.Clone()
+			a := e.(*expr.Add)
+			a.Insert(B.Clone())
+			sort.Sort(a)
+			a.CalcExprStats()
+			good := PS.cnfg.treecfg.CheckExpr(a)
+			if good {
+				ret = append(ret, a)
+			}
+			// fmt.Printf("grew  %v\n\n", a)
+			// ret = append(ret, a)
+		}
+	}
+
+	// extending terms in addition
+	for _, B := range PS.ffxBases {
+		for i, C := range add.CS {
+			if C.ExprType() == expr.MUL {
+				m := C.(*expr.Mul)
+				if len(m.CS) > 3 {
+					continue
+				}
+			}
+			e := O.Clone()
+			a := e.(*expr.Add)
+			mul := expr.NewMul()
+			mul.Insert(a.CS[i])
+			mul.Insert(B.Clone())
+			a.CS[i] = mul
+			sort.Sort(a)
+			a.CalcExprStats()
+			good := PS.cnfg.treecfg.CheckExpr(a)
+			if good {
+				ret = append(ret, a)
+			}
+			// fmt.Printf("grew  %v\n\n", a)
+			ret = append(ret, a)
+		}
+	}
+
+	// deepening terms 
+	// if len(add.CS) < 2 {
+	// 	return ret
+	// }
+	for i, C := range add.CS {
+		if C.ExprType() == expr.MUL {
+			m := C.(*expr.Mul)
+			if len(m.CS) != 2 {
+				continue
+			}
+			if m.CS[1].ExprType() == expr.ADD {
+				continue
+			}
+		} else {
+			continue
+		}
+
+		for _, B := range PS.ffxBases {
+			e := O.Clone()
+			a := e.(*expr.Add)
+			m := a.CS[i].(*expr.Mul)
+			n := m.CS[1]
+
+			switch n.ExprType() {
+			case expr.SQRT:
+				A := expr.NewAdd()
+				A.Insert(n.(*expr.Sqrt).C)
+				A.Insert(B.Clone())
+				n.(*expr.Sqrt).C = A
+			case expr.SIN:
+				A := expr.NewAdd()
+				A.Insert(n.(*expr.Sin).C)
+				A.Insert(B.Clone())
+				n.(*expr.Sin).C = A
+			case expr.COS:
+				A := expr.NewAdd()
+				A.Insert(n.(*expr.Cos).C)
+				A.Insert(B.Clone())
+				n.(*expr.Cos).C = A
+			case expr.TAN:
+				A := expr.NewAdd()
+				A.Insert(n.(*expr.Tan).C)
+				A.Insert(B.Clone())
+				n.(*expr.Tan).C = A
+			case expr.EXP:
+				A := expr.NewAdd()
+				A.Insert(n.(*expr.Exp).C)
+				A.Insert(B.Clone())
+				n.(*expr.Exp).C = A
+			case expr.LOG:
+				A := expr.NewAdd()
+				A.Insert(n.(*expr.Log).C)
+				A.Insert(B.Clone())
+				n.(*expr.Log).C = A
+
+			default:
+				A := expr.NewAdd()
+				A.Insert(m.CS[1])
+				A.Insert(B.Clone())
+				m.CS[1] = A
+			}
+			sort.Sort(a)
+			a.CalcExprStats()
+			good := PS.cnfg.treecfg.CheckExpr(a)
+			if good {
+				ret = append(ret, a)
+			}
+			// fmt.Printf("grew  %v\n", a)
+			ret = append(ret, a)
+		}
+	}
+	for i, C := range add.CS {
+		if C.ExprType() == expr.MUL {
+			m := C.(*expr.Mul)
+			if len(m.CS) != 2 {
+				continue
+			}
+			if m.CS[1].ExprType() == expr.ADD {
+				continue
+			}
+		} else {
+			continue
+		}
+
+		for _, B := range PS.ffxBases {
+			e := O.Clone()
+			a := e.(*expr.Add)
+			m := a.CS[i].(*expr.Mul)
+			n := m.CS[1]
+
+			switch n.ExprType() {
+			case expr.SQRT:
+				M := expr.NewMul()
+				M.Insert(n.(*expr.Sqrt).C)
+				M.Insert(B.Clone())
+				n.(*expr.Sqrt).C = M
+			case expr.SIN:
+				M := expr.NewMul()
+				M.Insert(n.(*expr.Sin).C)
+				M.Insert(B.Clone())
+				n.(*expr.Sin).C = M
+			case expr.COS:
+				M := expr.NewMul()
+				M.Insert(n.(*expr.Cos).C)
+				M.Insert(B.Clone())
+				n.(*expr.Cos).C = M
+			case expr.TAN:
+				M := expr.NewMul()
+				M.Insert(n.(*expr.Tan).C)
+				M.Insert(B.Clone())
+				n.(*expr.Tan).C = M
+			case expr.EXP:
+				M := expr.NewMul()
+				M.Insert(n.(*expr.Exp).C)
+				M.Insert(B.Clone())
+				n.(*expr.Exp).C = M
+			case expr.LOG:
+				M := expr.NewMul()
+				M.Insert(n.(*expr.Log).C)
+				M.Insert(B.Clone())
+				n.(*expr.Log).C = M
+			}
+			sort.Sort(a)
+			a.CalcExprStats()
+			good := PS.cnfg.treecfg.CheckExpr(a)
+			if good {
+				ret = append(ret, a)
+			}
+			// fmt.Printf("grew  %v\n", a)
+			ret = append(ret, a)
+		}
+	}
+	// fmt.Println("Len of ret = ", len(ret))
+	return ret
+}
+
+//export GenInitExprAddMethod1
+func (PS *PgeSearch) GenInitExprAddMethod1() []expr.Expr {
+
+	exprs := make([]expr.Expr, 0)
+
+	// WARNING adding a single coefficient results in the same traversal but with the added extra coefficient
+	cf := new(expr.Constant)
+	cf.P = 1
+	af := new(expr.Add)
+	af.Insert(cf)
+	exprs = append(exprs, af)
+
+	for _, i := range PS.cnfg.treecfg.UsableVars {
+		c := new(expr.Constant)
+		c.P = -1
+		v := new(expr.Var)
+		v.P = i
+
+		m := expr.NewMul()
+		m.Insert(c)
+		m.Insert(v)
+
+		a := expr.NewAdd()
+		a.Insert(m)
+		exprs = append(exprs, a)
+	}
+
+	fmt.Println("Initial Add:  ", exprs)
+	return exprs
+}
+
+//export GenInitExprMulMethod1
+func (PS *PgeSearch) GenInitExprMulMethod1() []expr.Expr {
+	exprs := make([]expr.Expr, 0)
+
+	for _, i := range PS.cnfg.treecfg.UsableVars {
+		c := new(expr.Constant)
+		c.P = -1
+		v := new(expr.Var)
+		v.P = i
+
+		m := expr.NewMul()
+		m.Insert(c)
+		m.Insert(v)
+
+		exprs = append(exprs, m)
+	}
+
+	fmt.Println("Initial Mul:  ", exprs)
+	return exprs
+}
+
+//export GenInitExprDivMethod1
+func (PS *PgeSearch) GenInitExprDivMethod1() []expr.Expr {
+	exprs := make([]expr.Expr, 0)
+
+	for _, i := range PS.cnfg.treecfg.UsableVars {
+		c := new(expr.Constant)
+		c.P = -1
+		v := new(expr.Var)
+		v.P = i
+
+		d := new(expr.Div)
+		d.Numer = c
+		d.Denom = v
+
+		exprs = append(exprs, d)
+	}
+
+	fmt.Println("Initial Div:  ", exprs)
+	return exprs
+}
+
+type pgeConfig struct {
+	// search params
+	maxGen        int
+	pgeRptEpoch   int
+	pgeRptCount   int
+	pgeArchiveCap int
+
+	simprules expr.SimpRules
+	treecfg   *probs.TreeParams
+
+	// PGE specific options
+	peelCnt     int
+	sortType    probs.SortType
+	zeroEpsilon float64
+
+	initMethod string
+	growMethod string
+
+	evalrCount int
+}
+
+//export pgeConfigParser
+func pgeConfigParser(field, value string, config interface{}) (err error) {
+
+	PC := config.(*pgeConfig)
+
+	switch strings.ToUpper(field) {
+	case "MAXGEN":
+		PC.maxGen, err = strconv.Atoi(value)
+	case "PGERPTEPOCH":
+		PC.pgeRptEpoch, err = strconv.Atoi(value)
+	case "PGERPTCOUNT":
+		PC.pgeRptCount, err = strconv.Atoi(value)
+	case "PGEARCHIVECAP":
+		PC.pgeArchiveCap, err = strconv.Atoi(value)
+
+	case "PEELCOUNT":
+		PC.peelCnt, err = strconv.Atoi(value)
+
+	case "EVALRCOUNT":
+		PC.evalrCount, err = strconv.Atoi(value)
+
+	case "SORTTYPE":
+		switch strings.ToLower(value) {
+		case "paretotrainerror":
+			PC.sortType = probs.PESORT_PARETO_TRN_ERR
+		case "paretotesterror":
+			PC.sortType = probs.PESORT_PARETO_TST_ERR
+
+		default:
+			log.Printf("PGE Config Not Implemented: %s, %s\n\n", field, value)
+		}
+
+	case "ZEROEPSILON":
+		PC.zeroEpsilon, err = strconv.ParseFloat(value, 64)
+
+	default:
+		// check augillary parsable structures [only TreeParams for now]
+		if PC.treecfg == nil {
+			PC.treecfg = new(probs.TreeParams)
+		}
+		found, ferr := probs.ParseTreeParams(field, value, PC.treecfg)
+		if ferr != nil {
+			log.Fatalf("error parsing PGE - treecfg Config\n")
+			return ferr
+		}
+		if !found {
+			log.Printf("PGE Config Not Implemented: %s, %s\n\n", field, value)
+		}
+
+	}
+	return
+}
+
+type PgeSearch struct {
+	id   int
+	cnfg pgeConfig
+	prob *probs.ExprProblem
+	iter int
+	stop bool
+
+	// comm up
+	commup *probs.ExprProblemComm
+
+	// comm down
+
+	// best exprs
+	Best *probs.ReportQueue
+
+	// training data in C format
+	c_input  []levmar.C_double
+	c_ygiven []levmar.C_double
+
+	// logs
+	logDir     string
+	mainLog    *log.Logger
+	mainLogBuf *bufio.Writer
+	eqnsLog    *log.Logger
+	eqnsLogBuf *bufio.Writer
+	errLog     *log.Logger
+	errLogBuf  *bufio.Writer
+
+	fitnessLog    *log.Logger
+	fitnessLogBuf *bufio.Writer
+	ipreLog       *log.Logger
+	ipreLogBuf    *bufio.Writer
+
+	// equations visited
+	Trie  *IpreNode
+	Queue *probs.ReportQueue
+
+	// eval channels
+	eval_in  chan expr.Expr
+	eval_out chan *probs.ExprReport
+
+	// genStuff
+	GenRoots   []expr.Expr
+	GenLeafs   []expr.Expr
+	GenNodes   []expr.Expr
+	GenNonTrig []expr.Expr
+
+	// FFXish stuff
+	ffxBases []expr.Expr
+
+	// statistics
+	neqns    int
+	ipreCnt  int
+	maxSize  int
+	maxScore int
+	minError float64
+}
+//export GetMaxIter
+func (PS *PgeSearch) GetMaxIter() int {
+	return PS.cnfg.maxGen
+} 
+//export SetMaxIter
+func (PS *PgeSearch) SetMaxIter(iter int) {
+	PS.cnfg.maxGen = iter
+}
+//export SetPeelCount
+func (PS *PgeSearch) SetPeelCount(cnt int) {
+	PS.cnfg.peelCnt = cnt
+}
+//export SetInitMethod
+func (PS *PgeSearch) SetInitMethod(init string) {
+	PS.cnfg.initMethod = init
+}
+//export SetGrowMethod
+func (PS *PgeSearch) SetGrowMethod(grow string) {
+	PS.cnfg.growMethod = grow
+}
+//export SetEvalrCount
+func (PS *PgeSearch) SetEvalrCount(cnt int) {
+	PS.cnfg.evalrCount = cnt
+}
+
+//export ParseConfig
+func (PS *PgeSearch) ParseConfig(filename string) {
+	fmt.Printf("Parsing PGE Config: %s\n", filename)
+	data, err := ioutil.ReadFile(filename)
+	if err != nil {
+		log.Fatal(err)
+	}
+	err = config.ParseConfig(data, pgeConfigParser, &PS.cnfg)
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+//export Init
+func (PS *PgeSearch) Init(done chan int, prob *probs.ExprProblem, logdir string, input interface{}) {
+	fmt.Printf("Init'n PGE\n")
+	// setup data
+
+	// open logs
+	PS.initLogs(logdir)
+
+	// copy in common config options
+	PS.prob = prob
+	if PS.cnfg.treecfg == nil {
+		PS.cnfg.treecfg = PS.prob.TreeCfg.Clone()
+	}
+	srules := expr.DefaultRules()
+	srules.ConvertConsts = true
+	PS.cnfg.simprules = srules
+
+	fmt.Println("Roots:   ", PS.cnfg.treecfg.RootsS)
+	fmt.Println("Nodes:   ", PS.cnfg.treecfg.NodesS)
+	fmt.Println("Leafs:   ", PS.cnfg.treecfg.LeafsS)
+	fmt.Println("NonTrig: ", PS.cnfg.treecfg.NonTrigS)
+
+	PS.GenRoots = make([]expr.Expr, len(PS.cnfg.treecfg.Roots))
+	for i := 0; i < len(PS.GenRoots); i++ {
+		PS.GenRoots[i] = PS.cnfg.treecfg.Roots[i].Clone()
+	}
+	PS.GenNodes = make([]expr.Expr, len(PS.cnfg.treecfg.Nodes))
+	for i := 0; i < len(PS.GenNodes); i++ {
+		PS.GenNodes[i] = PS.cnfg.treecfg.Nodes[i].Clone()
+	}
+	PS.GenNonTrig = make([]expr.Expr, len(PS.cnfg.treecfg.NonTrig))
+	for i := 0; i < len(PS.GenNonTrig); i++ {
+		PS.GenNonTrig[i] = PS.cnfg.treecfg.NonTrig[i].Clone()
+	}
+
+	PS.GenLeafs = make([]expr.Expr, 0)
+	for _, t := range PS.cnfg.treecfg.LeafsT {
+		switch t {
+		case expr.TIME:
+			PS.GenLeafs = append(PS.GenLeafs, expr.NewTime())
+
+		case expr.VAR:
+			fmt.Println("Use Vars: ", PS.cnfg.treecfg.UsableVars)
+			for _, i := range PS.cnfg.treecfg.UsableVars {
+				PS.GenLeafs = append(PS.GenLeafs, expr.NewVar(i))
+			}
+
+		case expr.SYSTEM:
+			for i := 0; i < PS.prob.Train[0].NumSys(); i++ {
+				PS.GenLeafs = append(PS.GenLeafs, expr.NewSystem(i))
+			}
+
+		}
+	}
+	/*** FIX ME
+	PS.GenLeafs = make([]expr.Expr, len(PS.cnfg.treecfg.Leafs))
+	for i := 0; i < len(PS.GenLeafs); i++ {
+		PS.GenLeafs[i] = PS.cnfg.treecfg.Leafs[i].Clone()
+	}
+	***/
+
+	fmt.Println("Roots:   ", PS.GenRoots)
+	fmt.Println("Nodes:   ", PS.GenNodes)
+	fmt.Println("Leafs:   ", PS.GenLeafs)
+	fmt.Println("NonTrig: ", PS.GenNonTrig)
+
+	// setup communication struct
+	PS.commup = input.(*probs.ExprProblemComm)
+
+	// initialize bbq
+	PS.Trie = new(IpreNode)
+	PS.Trie.val = -1
+	PS.Trie.next = make(map[int]*IpreNode)
+
+	PS.Best = probs.NewReportQueue()
+	PS.Best.SetSort(probs.GPSORT_PARETO_TST_ERR)
+	PS.Queue = PS.GenInitExpr()
+	PS.Queue.SetSort(probs.PESORT_PARETO_TST_ERR)
+
+	PS.neqns = PS.Queue.Len()
+
+	PS.minError = math.Inf(1)
+
+	PS.eval_in = make(chan expr.Expr, 4048)
+	PS.eval_out = make(chan *probs.ExprReport, 4048)
+
+	for i := 0; i < PS.cnfg.evalrCount; i++ {
+		go PS.Evaluate()
+	}
+}
+
+//export Evaluate
+func (PS *PgeSearch) Evaluate() {
+
+	for !PS.stop {
+		e := <-PS.eval_in
+		if e == nil {
+			continue
+		}
+		PS.eval_out <- RegressExpr(e, PS.prob)
+	}
+
+}
+
+//export Run
+func (PS *PgeSearch) Run() {
+	fmt.Printf("Running PGE\n")
+
+	PS.loop()
+
+	fmt.Println("PGE exitting")
+
+	PS.Clean()
+	PS.commup.Cmds <- -1
+}
+
+//export loop
+func (PS *PgeSearch) loop() {
+
+	PS.checkMessages()
+	for !PS.stop {
+
+		fmt.Println("in: PS.step() ", PS.iter)
+		PS.step()
+
+		// if PS.iter%PS.cnfg.pgeRptEpoch == 0 {
+		PS.reportExpr()
+		// }
+
+		// report current iteration
+		PS.commup.Gen <- [2]int{PS.id, PS.iter}
+		PS.iter++
+
+		PS.Clean()
+
+		PS.checkMessages()
+
+	}
+
+	// done expanding, pull the rest of the regressed solutions from the queue
+	p := 0
+	for PS.Queue.Len() > 0 {
+		e := PS.Queue.Pop().(*probs.ExprReport)
+
+		bPush := true
+		if len(e.Coeff()) == 1 && math.Abs(e.Coeff()[0]) < PS.cnfg.zeroEpsilon {
+			// fmt.Println("No Best Push")
+			bPush = false
+		}
+
+		if bPush {
+			// fmt.Printf("pop/push(%d,%d): %v\n", p, PS.Best.Len(), e.Expr())
+			PS.Best.Push(e)
+			p++
+		}
+
+		if e.TestScore() > PS.maxScore {
+			PS.maxScore = e.TestScore()
+		}
+		if e.TestError() < PS.minError {
+			PS.minError = e.TestError()
+			fmt.Printf("EXITING New Min Error:  %v\n", e)
+		}
+		if e.Size() > PS.maxSize {
+			PS.maxSize = e.Size()
+		}
+	}
+
+	fmt.Println("PGE sending last report")
+	PS.reportExpr()
+
+}
+ 
+//export step
+func (PS *PgeSearch) step() {
+
+	loop := 0
+	eval_cnt := 0 // for channeled eval
+
+	es := PS.peel()
+
+	ex := PS.expandPeeled(es)
+
+	for cnt := range ex {
+		E := ex[cnt]
+
+		if E == nil {
+			continue
+		}
+
+		for _, e := range E {
+			if e == nil {
+				continue
+			}
+			if !PS.cnfg.treecfg.CheckExpr(e) {
+				continue
+			}
+
+			// check ipre_trie
+			serial := make([]int, 0, 64)
+			serial = e.Serial(serial)
+			ins := PS.Trie.InsertSerial(serial)
+			if !ins {
+				continue
+			}
+
+			// for serial eval
+			// re := RegressExpr(e, PS.prob)
+
+			// start channeled eval
+			PS.eval_in <- e
+			eval_cnt++
+		}
+	}
+	for i := 0; i < eval_cnt; i++ {
+		re := <-PS.eval_out
+		// end channeled eval
+
+		// check for NaN/Inf in re.error  and  if so, skip
+		if math.IsNaN(re.TestError()) || math.IsInf(re.TestError(), 0) {
+			// fmt.Printf("Bad Error\n%v\n", re)
+			continue
+		}
+
+		if re.TestError() < PS.minError {
+			PS.minError = re.TestError()
+		}
+
+		// check for coeff == 0
+		doIns := true
+		for _, c := range re.Coeff() {
+			// i > 0 for free coeff
+			if math.Abs(c) < PS.cnfg.zeroEpsilon {
+				doIns = false
+				break
+			}
+		}
+
+		if doIns {
+			re.SetProcID(PS.id)
+			re.SetIterID(PS.iter)
+			re.SetUnitID(loop)
+			re.SetUniqID(PS.neqns)
+			loop++
+			PS.neqns++
+			// fmt.Printf("Queue.Push(): %v\n%v\n\n", re.Expr(), serial)
+			// fmt.Printf("Queue.Push(): %v\n", re)
+			// fmt.Printf("Queue.Push(): %v\n", re.Expr())
+
+			PS.Queue.Push(re)
+
+		}
+	}
+	// } // for sequential eval
+	PS.Queue.Sort()
+
+}
+
+//export peel
+func (PS *PgeSearch) peel() []*probs.ExprReport {
+	es := make([]*probs.ExprReport, PS.cnfg.peelCnt)
+	for p := 0; p < PS.cnfg.peelCnt && PS.Queue.Len() > 0; p++ {
+
+		e := PS.Queue.Pop().(*probs.ExprReport)
+
+		bPush := true
+		if len(e.Coeff()) == 1 && math.Abs(e.Coeff()[0]) < PS.cnfg.zeroEpsilon {
+			fmt.Println("No Best Push")
+			p--
+			continue
+		}
+
+		if bPush {
+			fmt.Printf("pop/push(%d,%d): %v\n", p, PS.Best.Len(), e.Expr())
+			PS.Best.Push(e)
+		}
+
+		es[p] = e
+
+		if e.TestScore() > PS.maxScore {
+			PS.maxScore = e.TestScore()
+		}
+		if e.TestError() < PS.minError {
+			PS.minError = e.TestError()
+			fmt.Printf("Best New Min Error:  %v\n", e)
+		}
+		if e.Size() > PS.maxSize {
+			PS.maxSize = e.Size()
+		}
+
+	}
+	return es
+}
+
+//export expandPeeled
+func (PS *PgeSearch) expandPeeled(es []*probs.ExprReport) [][]expr.Expr {
+	eqns := make([][]expr.Expr, PS.cnfg.peelCnt)
+	for p := 0; p < PS.cnfg.peelCnt; p++ {
+		if es[p] == nil {
+			continue
+		}
+		// fmt.Printf("expand(%d): %v\n", p, es[p].Expr())
+		if es[p].Expr().ExprType() != expr.ADD {
+			add := expr.NewAdd()
+			add.Insert(es[p].Expr())
+			add.CalcExprStats()
+			es[p].SetExpr(add)
+		}
+		eqns[p] = PS.Expand(es[p].Expr())
+		// fmt.Printf("Results:\n")
+		// for i, e := range eqns[p] {
+		// 	fmt.Printf("%d,%d:  %v\n", p, i, e)
+		// }
+		// fmt.Println()
+	}
+	fmt.Println("\n")
+	return eqns
+}
+
+//export reportExpr
+func (PS *PgeSearch) reportExpr() {
+
+	cnt := PS.cnfg.pgeRptCount
+	PS.Best.Sort()
+
+	// repot best equations
+	rpt := make(probs.ExprReportArray, cnt)
+	if PS.Best.Len() < cnt {
+		cnt = PS.Best.Len()
+	}
+	copy(rpt, PS.Best.GetQueue()[:cnt])
+
+	errSum, errCnt := 0.0, 0
+	PS.eqnsLog.Println("\n\nReport", PS.iter)
+	for i, r := range rpt {
+		PS.eqnsLog.Printf("\n%d:  %v\n", i, r)
+		if r != nil && r.Expr() != nil {
+			errSum += r.TestError()
+			errCnt++
+		}
+	}
+
+	PS.mainLog.Printf("Iter: %d  %f  %f\n", PS.iter, errSum/float64(errCnt), PS.minError)
+
+	PS.ipreLog.Println(PS.iter, PS.neqns, PS.Trie.cnt, PS.Trie.vst)
+	PS.fitnessLog.Println(PS.iter, PS.neqns, PS.Trie.cnt, PS.Trie.vst, errSum/float64(errCnt), PS.minError)
+
+	PS.commup.Rpts <- &rpt
+
+}
+
+//export Clean
+func (PS *PgeSearch) Clean() {
+	// fmt.Printf("Cleaning PGE\n")
+
+	PS.errLogBuf.Flush()
+	PS.mainLogBuf.Flush()
+	PS.eqnsLogBuf.Flush()
+	PS.fitnessLogBuf.Flush()
+	PS.ipreLogBuf.Flush()
+
+}
+
+//export initLogs
+func (PS *PgeSearch) initLogs(logdir string) {
+	// open logs
+	PS.logDir = logdir + "pge/"
+	os.Mkdir(PS.logDir, os.ModePerm)
+	tmpF0, err5 := os.Create(PS.logDir + "pge:err.log")
+	if err5 != nil {
+		log.Fatal("couldn't create errs log")
+	}
+	PS.errLogBuf = bufio.NewWriter(tmpF0)
+	PS.errLogBuf.Flush()
+	PS.errLog = log.New(PS.errLogBuf, "", log.LstdFlags)
+
+	tmpF1, err1 := os.Create(PS.logDir + "pge:main.log")
+	if err1 != nil {
+		log.Fatal("couldn't create main log")
+	}
+	PS.mainLogBuf = bufio.NewWriter(tmpF1)
+	PS.mainLogBuf.Flush()
+	PS.mainLog = log.New(PS.mainLogBuf, "", log.LstdFlags)
+
+	tmpF2, err2 := os.Create(PS.logDir + "pge:eqns.log")
+	if err2 != nil {
+		log.Fatal("couldn't create eqns log")
+	}
+	PS.eqnsLogBuf = bufio.NewWriter(tmpF2)
+	PS.eqnsLogBuf.Flush()
+	PS.eqnsLog = log.New(PS.eqnsLogBuf, "", 0)
+
+	tmpF3, err3 := os.Create(PS.logDir + "pge:fitness.log")
+	if err3 != nil {
+		log.Fatal("couldn't create eqns log")
+	}
+	PS.fitnessLogBuf = bufio.NewWriter(tmpF3)
+	PS.fitnessLogBuf.Flush()
+	PS.fitnessLog = log.New(PS.fitnessLogBuf, "", log.Ltime|log.Lmicroseconds)
+
+	tmpF4, err4 := os.Create(PS.logDir + "pge:ipre.log")
+	if err4 != nil {
+		log.Fatal("couldn't create eqns log")
+	}
+	PS.ipreLogBuf = bufio.NewWriter(tmpF4)
+	PS.ipreLogBuf.Flush()
+	PS.ipreLog = log.New(PS.ipreLogBuf, "", log.Ltime|log.Lmicroseconds)
+}
+
+//export checkMessages
+func (PS *PgeSearch) checkMessages() {
+
+	// check messages from superior
+	select {
+	case cmd, ok := <-PS.commup.Cmds:
+		if ok {
+			if cmd == -1 {
+				fmt.Println("PGE: stop sig recv'd")
+				PS.stop = true
+				return
+			}
+		}
+	default:
+		return
+	}
+}
+
+//export ExpandMethod3
+func (PS *PgeSearch) ExpandMethod3(O expr.Expr) (ret []expr.Expr) {
+	O.Sort()
+	ret = make([]expr.Expr, 0)
+	// fmt.Printf("Expanding expression:  %v\n", O)
+
+	add := O.(*expr.Add)
+
+	// adding term to addition
+	for _, B := range PS.ffxBases {
+		found := false
+		for _, C := range add.CS {
+			// fmt.Printf("checking %v in %v\n", B, add)
+			if C.AmISame(B) {
+				// fmt.Println("found\n\n")
+				found = true
+				break
+			}
+		}
+		if !found {
+			e := O.Clone()
+			a := e.(*expr.Add)
+			a.Insert(B.Clone())
+			sort.Sort(a)
+			a.CalcExprStats()
+			good := PS.cnfg.treecfg.CheckExpr(a)
+			if good {
+				ret = append(ret, a)
+			}
+			// fmt.Printf("grew  %v\n\n", a)
+			// ret = append(ret, a)
+		}
+	}
+
+	// extending terms in addition
+	for _, B := range PS.ffxBases {
+		for i, C := range add.CS {
+			if C.ExprType() == expr.MUL {
+				m := C.(*expr.Mul)
+				if len(m.CS) > 3 {
+					continue
+				}
+			}
+			e := O.Clone()
+			a := e.(*expr.Add)
+			mul := expr.NewMul()
+			mul.Insert(a.CS[i])
+			mul.Insert(B.Clone())
+			a.CS[i] = mul
+			sort.Sort(a)
+			a.CalcExprStats()
+			good := PS.cnfg.treecfg.CheckExpr(a)
+			if good {
+				ret = append(ret, a)
+			}
+			// fmt.Printf("grew  %v\n\n", a)
+			ret = append(ret, a)
+		}
+	}
+
+	// fmt.Println("Len of ret = ", len(ret))
+	return ret
+}
+
+//export RegressExpr
+func RegressExpr(E expr.Expr, P *probs.ExprProblem) (R *probs.ExprReport) {
+
+	guess := make([]float64, 0)
+	guess, eqn := E.ConvertToConstants(guess)
+
+	var coeff []float64
+	if len(guess) > 0 {
+
+		// fmt.Printf("x_dims:  %d  %d\n", x_dim, x_dim2)
+
+		// Callback version
+		coeff = levmar.LevmarExpr(eqn, P.SearchVar, P.SearchType, guess, P.Train, P.Test)
+
+		// Stack version
+		// x_dim := P.Train[0].NumDim()
+		// if c_input == nil {
+		// 	ps := P.Train[0].NumPoints()
+		// 	PS := len(P.Train) * ps
+		// 	x_tot := PS * x_dim
+
+		// 	c_input = make([]levmar.C_double, x_tot)
+		// 	c_ygiven = make([]levmar.C_double, PS)
+
+		// 	for i1, T := range P.Train {
+		// 		for i2, p := range T.Points() {
+		// 			i := i1*ps + i2
+		// 			c_ygiven[i] = levmar.MakeCDouble(p.Depnd(P.SearchVar))
+		// 			for i3, x_p := range p.Indeps() {
+		// 				j := i1*ps*x_dim + i2*x_dim + i3
+		// 				c_input[j] = levmar.MakeCDouble(x_p)
+		// 			}
+		// 		}
+		// 	}
+		// }
+		// coeff = levmar.StackLevmarExpr(eqn, x_dim, guess, c_ygiven, c_input)
+
+		// serial := make([]int, 0)
+		// serial = eqn.StackSerial(serial)
+		// fmt.Printf("StackSerial: %v\n", serial)
+		// fmt.Printf("%v\n%v\n%v\n\n", eqn, coeff, steff)
+	}
+
+	R = new(probs.ExprReport)
+	R.SetExpr(eqn) /*.ConvertToConstantFs(coeff)*/
+	R.SetCoeff(coeff)
+	R.Expr().CalcExprStats()
+
+	// hitsL1, hitsL2, evalCnt, nanCnt, infCnt, l1_err, l2_err := scoreExpr(E, P, coeff)
+	_, _, _, trnNanCnt, _, trn_l1_err, _ := scoreExpr(E, P, P.Train, coeff)
+	_, _, tstEvalCnt, tstNanCnt, _, tst_l1_err, tst_l2_err := scoreExpr(E, P, P.Test, coeff)
+
+	R.SetTrainScore(trnNanCnt)
+	R.SetTrainError(trn_l1_err)
+
+	R.SetPredScore(tstNanCnt)
+	R.SetTestScore(tstEvalCnt)
+	R.SetTestError(tst_l1_err)
+	R.SetPredError(tst_l2_err)
+
+	return R
+}
+
+//export scoreExpr
+func scoreExpr(e expr.Expr, P *probs.ExprProblem, dataSets []*probs.PointSet, coeff []float64) (hitsL1, hitsL2, evalCnt, nanCnt, infCnt int, l1_err, l2_err float64) {
+	var l1_sum, l2_sum float64
+	for _, PS := range dataSets {
+		for _, p := range PS.Points() {
+			y := p.Depnd(P.SearchVar)
+			var out float64
+			if P.SearchType == probs.ExprBenchmark {
+				out = e.Eval(0, p.Indeps(), coeff, PS.SysVals())
+			} else if P.SearchType == probs.ExprDiffeq {
+				out = e.Eval(p.Indep(0), p.Indeps()[1:], coeff, PS.SysVals())
+			}
+
+			if math.IsNaN(out) {
+				nanCnt++
+				continue
+			} else if math.IsInf(out, 0) {
+				infCnt++
+				continue
+			} else {
+				evalCnt++
+			}
+
+			diff := out - y
+			l1_val := math.Abs(diff)
+			l2_val := diff * diff
+			l1_sum += l1_val
+			l2_sum += l2_val
+
+			if l1_val < P.HitRatio {
+				hitsL1++
+			}
+			if l2_val < P.HitRatio {
+				hitsL2++
+			}
+		}
+	}
+
+	if evalCnt == 0 {
+		l1_err = math.NaN()
+		l2_err = math.NaN()
+	} else {
+		fEvalCnt := float64(evalCnt + 1)
+		l1_err = l1_sum / fEvalCnt
+		l2_err = math.Sqrt(l2_sum / fEvalCnt)
+	}
+
+	return
+}
+
+//export GenInitExpr
+func (PS *PgeSearch) GenInitExpr() *probs.ReportQueue {
+	switch PS.cnfg.initMethod {
+	case "method1":
+		return PS.GenInitExprMethod1()
+	case "method2":
+		return PS.GenInitExprMethod2()
+	case "method3":
+		return PS.GenInitExprMethod3()
+	default:
+		fmt.Println("Unknown init method")
+	}
+	return nil
+}
+
+//export Expand
+func (PS *PgeSearch) Expand(O expr.Expr) (ret []expr.Expr) {
+	var exprs []expr.Expr
+
+	switch PS.cnfg.growMethod {
+	case "method1":
+		exprs = PS.ExpandMethod1(O)
+	case "method2":
+		exprs = PS.ExpandMethod2(O)
+	case "method3":
+		exprs = PS.ExpandMethod3(O)
+	default:
+		fmt.Println("Unknown expand method")
+	}
+
+	// convert and simplify
+	for i, e := range exprs {
+		if e == nil {
+			continue
+		}
+		defer func() {
+			if r := recover(); r != nil {
+				fmt.Printf("Recovered in Expand %v   %d %v", r, i, e)
+				exprs[i] = nil
+			}
+		}()
+		c := make([]float64, 0)
+		// fmt.Printf("Preconv   %v\n", e)
+		c, eqn := e.ConvertToConstants(c)
+		e.CalcExprStats()
+		// fmt.Printf("Postconv  %v\n", eqn)
+
+		// fmt.Printf("Presimp  %v\n", eqn)
+		exprs[i] = eqn.Simplify(PS.cnfg.simprules)
+		// fmt.Printf("Postsimp  %v\n\n", exprs[i])
+		// serial := make([]int, 0, 64)
+		// serial = exprs[i].Serial(serial)
+		// fmt.Printf("Postsimp  %v   %v\n\n", exprs[i], serial)
+	}
+
+	// sort.Sort(expr.ExprArray(exprs))
+
+	// remove duplicates
+
+	// last := 0
+	// for last < len(exprs) && exprs[last] == nil {
+	// 	last++
+	// }
+	// for i := last + 1; i < len(exprs); i++ {
+	// 	if exprs[i] == nil {
+	// 		continue
+	// 	}
+	// 	if exprs[i].AmIAlmostSame(exprs[last]) {
+	// 		exprs[i] = nil
+	// 	} else {
+	// 		last = i
+	// 	}
+	// }
+
+	// copy to ret, ignoring nil & bad expressions ...
+	for _, e := range exprs {
+		if e == nil {
+			continue
+		}
+		// if !PS.cnfg.treecfg.CheckExpr(e) {
+		// 	continue
+		// }
+		ret = append(ret, e)
+	}
+	return ret
+}
+
+type IpreNode struct {
+	val int
+	cnt int
+	vst int
+
+	next map[int]*IpreNode
+}
+
+//export InsertSerial
+func (n *IpreNode) InsertSerial(s []int) (did_ins bool) {
+	in, _ := n.next[s[0]]
+
+	// does this branch exist?
+	if in == nil {
+		in = new(IpreNode)
+		in.val = s[0]
+		in.next = make(map[int]*IpreNode)
+		n.next[s[0]] = in
+		did_ins = true
+	}
+
+	// recursive call to insert
+	if len(s) > 1 {
+		did_ins = in.InsertSerial(s[1:]) || did_ins
+	}
+
+	// visitation accounting  
+	// (-1 is the root of the memoization tree)
+	in.vst++
+	if n.val == -1 {
+		n.vst++
+	}
+	if did_ins {
+		in.cnt++
+		if n.val == -1 {
+			n.cnt++
+		}
+	}
+
+	return did_ins
+}
+
+//export ExpandMethod1
+func (PS *PgeSearch) ExpandMethod1(O expr.Expr) (ret []expr.Expr) {
+	O.Sort()
+	ret = make([]expr.Expr, 0)
+	// fmt.Printf("Expanding expression:  %v\n", O)
+
+	for i := 0; i < O.Size(); i++ {
+		I := i
+		E := O.GetExpr(&I)
+		switch E.ExprType() {
+		case expr.ADD:
+			tmp := PS.AddTermToExprMethod1(O, E, i)
+			ret = append(ret, tmp[:]...)
+
+		case expr.MUL:
+			tmp := PS.WidenTermInExprMethod1(O, E, i)
+			ret = append(ret, tmp[:]...)
+
+		case expr.VAR:
+			tmp := PS.DeepenTermInExprMethod1(O, E, i)
+			ret = append(ret, tmp[:]...)
+
+		default: // expr.DIV,expr.COS,expr.SIN,expr.EXP,expr.LOG,expr.ABS,expr.POW
+			continue
+
+		}
+	}
+
+	return ret
+}
+
+// add another term to an add expr
+//export AddTermToExprMethod1
+func (PS *PgeSearch) AddTermToExprMethod1(O, E expr.Expr, pos int) (ret []expr.Expr) {
+	ret = make([]expr.Expr, 0)
+	A := E.(*expr.Add)
+
+	// f() + cL
+	for _, L := range PS.GenLeafs {
+		c := new(expr.Constant)
+		c.P = -1
+		l := L.Clone()
+
+		// mul it
+		M := expr.NewMul()
+		M.Insert(c)
+		M.Insert(l)
+
+		// skip if the same term already exists in the add
+		skip := false
+		for _, e := range A.CS {
+			if e == nil {
+				continue
+			}
+			// fmt.Printf("ACMP  %v  %v\n", M, e)
+			if e.AmIAlmostSame(M) || M.AmIAlmostSame(e) {
+				skip = true
+				break
+			}
+		}
+		if skip {
+			continue
+		}
+
+		C := O.Clone()
+		P := pos
+		AM := C.GetExpr(&P).(*expr.Add)
+		AM.Insert(M)
+		sort.Sort(AM)
+		C.CalcExprStats()
+		good := PS.cnfg.treecfg.CheckExpr(C)
+		if good {
+			ret = append(ret, C)
+		}
+	}
+
+	// f() + c*node(L)
+	for _, N := range PS.GenNodes {
+		for _, L := range PS.GenLeafs {
+
+			c := new(expr.Constant)
+			c.P = -1
+
+			l := L.Clone()
+			n := N.Clone()
+			p := 1
+			n.SetExpr(&p, l)
+
+			var E expr.Expr
+			if N.ExprType() == expr.DIV {
+				E = expr.NewDiv(c, l)
+			} else {
+				// mul it
+				M := expr.NewMul()
+				M.Insert(c)
+				M.Insert(n)
+				E = M
+			}
+
+			// skip if the same term already exists in the add
+			skip := false
+			for _, e := range A.CS {
+				if e == nil {
+					continue
+				}
+				// fmt.Printf("ACMP  %v  %v\n", M, e)
+				if e.AmIAlmostSame(E) || E.AmIAlmostSame(e) {
+					skip = true
+					break
+				}
+			}
+			if skip {
+				continue
+			}
+
+			// fmt.Println(E.String())
+
+			C := O.Clone()
+			P := pos
+			AM := C.GetExpr(&P).(*expr.Add)
+			AM.Insert(E)
+			sort.Sort(AM)
+			C.CalcExprStats()
+			good := PS.cnfg.treecfg.CheckExpr(C)
+			if good {
+				ret = append(ret, C)
+			}
+		}
+	}
+
+	return ret
+}
+
+// add complexity to a single multiplication term
+//export WidenTermInExprMethod1
+func (PS *PgeSearch) WidenTermInExprMethod1(O, E expr.Expr, pos int) (ret []expr.Expr) {
+	ret = make([]expr.Expr, 0)
+
+	// insert leafs  f()*L
+	for _, L := range PS.GenLeafs {
+		l := L.Clone()
+		C := O.Clone()
+		P := pos
+		e := C.GetExpr(&P)
+		// fmt.Printf("pos(%d): %v\n", pos, e)
+		M := e.(*expr.Mul)
+		M.Insert(l)
+		sort.Sort(M)
+		C.CalcExprStats()
+		good := PS.cnfg.treecfg.CheckExpr(C)
+		if good {
+			ret = append(ret, C)
+		}
+	}
+
+	// insert node(L)  :  f() * c*node(L)
+	for _, N := range PS.GenNodes {
+		for _, L := range PS.GenLeafs {
+			c := new(expr.Constant)
+			c.P = -1
+
+			l := L.Clone()
+			n := N.Clone()
+			p := 1
+			n.SetExpr(&p, l)
+
+			var E expr.Expr
+			if N.ExprType() == expr.DIV {
+				E = expr.NewDiv(c, l)
+			} else {
+				// mul it
+				M := expr.NewMul()
+				M.Insert(c)
+				M.Insert(n)
+				E = M
+			}
+
+			C := O.Clone()
+			P := pos
+			e := C.GetExpr(&P)
+			// fmt.Printf("pos(%d): %v\n", pos, e)
+			M := e.(*expr.Mul)
+
+			M.Insert(E)
+			sort.Sort(M)
+			C.CalcExprStats()
+			good := PS.cnfg.treecfg.CheckExpr(C)
+			if good {
+				ret = append(ret, C)
+			}
+		}
+	}
+	return ret
+}
+
+// change any term to something more complex...
+//export DeepenTermInExprMethod1
+func (PS *PgeSearch) DeepenTermInExprMethod1(O, E expr.Expr, pos int) []expr.Expr {
+	exprs := make([]expr.Expr, 0)
+
+	// make into add
+	A := expr.NewAdd()
+	A.Insert(E.Clone())
+	OA := A.Clone()
+	exprs = append(exprs, PS.AddTermToExprMethod1(OA, A, 0)[:]...)
+
+	// make into mul
+	M := expr.NewMul()
+	M.Insert(E.Clone())
+	OM := M.Clone()
+	exprs = append(exprs, PS.WidenTermInExprMethod1(OM, M, 0)[:]...)
+
+	// // make into div
+	// if E.ExprType() != expr.DIV {
+	// 	D := new(expr.Div)
+	// 	c := new(expr.Constant)
+	// 	c.P = -1
+	// 	D.Numer = c
+	// 	D.Denom = E.Clone()
+	// 	exprs = append(exprs, D)
+	// }
+
+	// make inside of nodes
+	for _, N := range PS.GenNodes {
+		if N.ExprType() == expr.DIV {
+			continue
+		}
+		T := N.Clone()
+		P := 1
+		T.SetExpr(&P, E.Clone())
+		exprs = append(exprs, T)
+	}
+
+	ret := make([]expr.Expr, 0)
+	for _, e := range exprs {
+		C := O.Clone()
+		P := pos
+		C.SetExpr(&P, e)
+		ret = append(ret, C)
+	}
+	return ret
+}
Index: /branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/go-code/go-pge/plug/pge.h
===================================================================
--- /branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/go-code/go-pge/plug/pge.h	(revision 16613)
+++ /branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/go-code/go-pge/plug/pge.h	(revision 16614)
@@ -94,7 +94,9 @@
 extern void LoopW();
 
-extern char* GetStepResult(GoInt* p0, GoInt* p1, GoInt* p2, GoInt* p3, GoInt* p4, void* p5, GoInt* p6);
+extern char* GetStepResult(GoInt* p0, GoInt* p1, GoInt* p2, GoInt* p3, GoInt* p4, GoInt* p5);
 
-extern void StepW();
+extern GoFloat64 GetCoeffResult();
+
+extern GoInt StepW();
 
 extern GoUint8 CheckStop();
Index: /branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/testmulti.c
===================================================================
--- /branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/testmulti.c	(revision 16614)
+++ /branches/2929_PrioritizedGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.PGE/3.3/testmulti.c	(revision 16614)
@@ -0,0 +1,447 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "list.c"
+#include "pge.h"
+
+#define MAX_CHAR 255
+//#define DEBUG
+
+char* trim(char *str)
+{
+  char *end;
+  while(isspace((unsigned char)*str)) {
+    str++;
+  }
+  if(*str == 0) {
+    return "\0";
+  }
+  end = str + strlen(str) - 1;
+  while(end > str && isspace((unsigned char)*end)) {
+    end--;
+  }
+  end[1] = '\0';
+  return str;
+}
+
+GoInt CountCols(char *str) {
+    GoInt res = 0;
+    trim(str);
+    char *partial = strtok(str, " ");
+    while(partial != NULL) {
+        res++;
+        partial = strtok(NULL, " ");
+    }
+    return res;
+}
+
+char* lowerCase(char *str) {
+    int i = 0;
+    while(str[i] && str[i] != '\0'){
+        char c = tolower(str[i]);
+        str[i] = c;
+        i++;
+    }
+    return str;
+}
+
+char *strndup(char *str, int chars)
+{
+    char *buffer;
+    int n;
+
+    buffer = (char *) malloc(chars +1);
+    if (buffer)
+    {
+        for (n = 0; ((n < chars) && (str[n] != 0)) ; n++) buffer[n] = str[n];
+        buffer[n] = 0;
+    }
+
+    return buffer;
+}
+
+//Read train / test data
+GoFloat64* ReadInputData(char *fileName, GoInt* nEntries, GoInt* nCol, char** depHead, char** indHead) {
+    FILE *fp;
+    fp = fopen(fileName, "r");
+    if (fp == NULL) {
+        char msg[MAX_CHAR];
+        strcpy(msg, "Error in ReadInputData, failed to open file: ");
+        perror(strcat(msg, fileName));
+        exit(EXIT_FAILURE);
+    }
+
+    int lineNr = 0;
+    int currentC = 0;
+    char line[MAX_CHAR];
+
+    fgets(line, MAX_CHAR, fp);
+    GoInt nIndCol = CountCols(strdup(line));
+    *indHead = strdup(trim(line)); //, nIndCol * 2 - 1);
+    #ifdef DEBUG
+        printf("Independent Variables %d\n", nIndCol);
+    #endif
+
+    fgets(line, MAX_CHAR, fp);
+    GoInt nDepCol = CountCols(strdup(line));
+    *depHead = strdup(trim(line)); //, nDepCol * 2 - 1);
+    #ifdef DEBUG
+        printf("Dependent Variables %d\n", nDepCol);
+    #endif
+
+    *nCol = nDepCol + nIndCol;
+    if(nDepCol < 0 || nIndCol < 0) {
+        perror("There must be at least one independent and one dependent colum!\n");
+        exit(EXIT_FAILURE);
+    }
+
+    GoFloat64 *values = NULL;
+    while(fgets(line, MAX_CHAR, fp)) {
+        trim(line);
+        currentC = 0;
+        values = (GoFloat64 *) realloc(values, (lineNr + 1) * (*nCol) * sizeof(GoFloat64));        
+        if(values == NULL) {
+            perror("Out of memory!\n");
+        }
+        char *partial = strtok(line, " ");
+        while(partial != NULL) {
+            GoFloat64 value = 0;
+            value = strtod(partial, NULL);
+            int pos = lineNr * (*nCol) + currentC;
+            values[pos] = (GoFloat64) value;
+            #ifdef DEBUG
+                printf("Value (%d, %d) %d: %f\n", lineNr, currentC, pos, values[pos]);
+            #endif        
+            currentC++;
+            partial = strtok(NULL, " ");
+        }
+        lineNr++;
+    }
+    *nEntries = lineNr;
+    fclose(fp);
+    return values;
+}
+
+//Print Test / Train data
+void PrintInputData(double *values, int nEntries, int nCols) {
+    for(int i = 0; i < nEntries; i++) {     //Rows
+        for(int j = 0; j < nCols; j++) {    //Cols
+            int pos = i * nCols + j;
+            printf("Value (%d, %d) %d: %f\n", i, j, pos, values[pos]);
+        }
+    }
+}
+
+GoInt* CreateUseableVars(long n) {
+	GoInt *data = malloc(sizeof(GoInt) * n);
+    for(GoInt i = 0; i < n; i++) {
+        data[i] = i;
+    }
+	return data;
+}
+
+int isTreeSetting(char *key) {
+    if(strcmp(key, "roots") == 0 || strcmp(key, "nodes") == 0 || strcmp(key, "nontrig") == 0 || strcmp(key, "leafs") == 0) {
+        return 1;
+    }
+    return 0;
+}
+
+char* MergeArgs(char **values, int nValues) {
+    char margs[MAX_CHAR] = "\0";
+    for(int i = 0; i < nValues; i++) {
+        strcat(margs, lowerCase(values[i]));
+        if(i + 1 < nValues) {
+            strcat(margs, " ");
+        }
+    }
+    return strdup(margs);
+}
+
+void SetConfValue(char *keySetting, char **values, int nValues) {
+    #ifdef DEBUG
+        for(int i = 0; i < nValues; i++) {
+            printf("Key: %s Nr: %d Value: %s\n", keySetting, i, values[i]);
+        }
+    #endif
+    void *data = NULL;
+    if (strcmp(keySetting, "sorttype") == 0) {
+        data = (GoInt *)malloc(sizeof(GoInt));
+        *((GoInt *)data) = 0;
+        if(strcmp("paretotesterror", lowerCase(values[0])) != 0) {
+            *((GoInt *)data) = 1;
+        }
+    } else if (strcmp(keySetting, "usablevars") == 0) {
+        data = (GoInt *)malloc(sizeof(GoInt));
+        *((GoInt *)data) = nValues;
+    } else if(strcmp(keySetting, "zeroepsilon") == 0 || strcmp(keySetting, "hitratio") == 0) {
+        data = (GoFloat64 *)malloc(sizeof(GoFloat64));
+        *((GoFloat64 *)data) = strtod(values[0], NULL);
+    } else if(isTreeSetting(keySetting) == 1) {
+        data = MergeArgs(values, nValues);
+    } else if(strcmp(keySetting, "problemtype") == 0 || strcmp(keySetting, "name") == 0) {
+        data = strdup(lowerCase(values[0]));
+    } else {    //Integer
+        data = (GoInt *)malloc(sizeof(GoInt));
+        *((GoInt *)data) = strtol(values[0], NULL, 10);
+    }
+    configPrepend(strdup(keySetting), (void *)data);
+}
+
+void ReadConfigFile(char *filePath) {
+    FILE *fp;
+    fp = fopen(filePath, "r");
+    if (fp == NULL) {
+        perror("Error in ReadConfigFile, failed to open file\n");
+        exit(EXIT_FAILURE);
+    }
+    char line[MAX_CHAR];
+    fgets(line, MAX_CHAR, fp);
+
+    while(fgets(line, MAX_CHAR, fp)) {
+        trim(line);
+        char *partial = strtok(line, " ");
+        int currentPart = 0;
+        char keySetting[MAX_CHAR] = "\0";
+        int valid = 0;
+        char **values = NULL;
+        int nValues = 0;
+        while(partial != NULL) {
+            trim(partial);
+            if(strlen(partial) > 0 && partial[0] == '#') {
+                break;
+            }
+            if(strlen(partial) > 0) { 
+                if(currentPart == 0) {                  //Name / Key
+                    sscanf(partial, "%s", keySetting);
+                } else if(currentPart == 1) {           //Eq char
+                    if(strlen(keySetting) > 0) {
+                        valid = 1;
+                    }
+                } else {                                //Value
+                    values = (char **) realloc(values, (nValues + 1) * MAX_CHAR * sizeof(char));
+                    values[nValues] = partial;
+                    nValues++;
+                }
+                currentPart++;
+            }
+            partial = strtok(NULL, " ");
+        }
+        if(valid == 1) {
+            SetConfValue(lowerCase(keySetting), values, nValues);
+        }
+    }
+}
+
+void RunTest(GoFloat64 *TrainData, int nTrainEntries, int nTrainCols, GoFloat64 *TestData, int nTestEntries, int nTestCols, char *depHeadTrain, char *indepHeadTrain, char *depHeadTest, char *indepHeadTest) {
+    putenv("GOGC=off");
+	putenv("GODEBUG=cgocheck=0");
+	putenv("CGO_ENABLED=1");
+    #ifdef DEBUG
+        putenv("PGEDEBUG=1");
+        printf("%s %s %s %s", indepHeadTest, indepHeadTrain, depHeadTest, depHeadTrain);
+    #endif
+    fflush(stdout);
+
+    AddTestData(indepHeadTest, depHeadTest, TestData, nTestEntries);
+	AddTrainData(indepHeadTrain, depHeadTrain, TrainData, nTrainEntries);
+    printf("Added Train- and Testdata\n");
+
+    GoInt MaxGen = *((GoInt *)configGet("maxgen"));
+    GoInt PgeRptEpoch = *((GoInt *)configGet("pgerptepoch")); 
+    GoInt PgeRptCount = *((GoInt *)configGet("pgerptcount"));
+    GoInt PgeArchiveCap = *((GoInt *)configGet("pgearchivecap"));
+    GoInt PeelCnt = *((GoInt *)configGet("peelcnt"));
+    GoInt EvalrCount = *((GoInt *)configGet("evalcnt"));
+    GoInt SortType = *((GoInt *)configGet("sorttype"));
+    GoFloat64 ZeroEpsilon = *((GoFloat64 *)configGet("zeroepsilon"));
+    char *InitMethod = (char *)configGet("initmethod");
+    char *GrowMethod = (char *)configGet("growmethod");
+    
+    #ifdef DEBUG
+        printf("1: %d 2: %d 3: %d 4: %d 5: %d 6: %d 7: %d 8: %lf 9: %s 10: %s\n", 
+        MaxGen, PgeRptEpoch, PgeRptCount, PgeArchiveCap, PeelCnt, EvalrCount, SortType, ZeroEpsilon, InitMethod, GrowMethod);
+    #endif
+
+    InitSearch(MaxGen, PgeRptEpoch, PgeRptCount, PgeArchiveCap, PeelCnt, EvalrCount, ZeroEpsilon, InitMethod, GrowMethod, SortType);
+    printf("Initialized Search\n");
+    fflush(stdout);
+
+    GoInt MaxSize = *((GoInt *)configGet("maxsize"));
+    GoInt MinSize = *((GoInt *)configGet("minsize")); 
+    GoInt MaxDepth = *((GoInt *)configGet("maxdepth"));
+    GoInt MinDepth = *((GoInt *)configGet("mindepth"));
+    char *Roots = (char *)configGet("roots");
+    char *Nodes = (char *)configGet("nodes");
+    char *NonTrig = (char *)configGet("nontrig");
+    char *Leafs = (char *)configGet("leafs");
+    GoInt nUsableVars = *((GoInt *)configGet("usablevars"));
+
+    #ifdef DEBUG
+        printf("1: %d 2: %d 3: %d 4: %d 5: %s 6: %s 7: %s 8: %s 9: %d\n", MaxSize, MinSize, MaxDepth, MinDepth, Roots, Nodes, NonTrig, Leafs, nUsableVars);
+    #endif
+
+    InitTreeParams(Roots, Nodes, NonTrig, Leafs, nUsableVars, MaxSize, MinSize, MaxDepth, MinDepth);
+	printf("Initialized TreeParams\n");
+    fflush(stdout);
+
+    GoInt MaxIter = *((GoInt *)configGet("maxiter"));
+    GoInt SearchVar = *((GoInt *)configGet("searchvar"));
+    GoFloat64 HitRatio = *((GoFloat64 *)configGet("hitratio"));
+    GoInt NumProcs = *((GoInt *)configGet("numprocs"));
+    char *Name = (char *)configGet("name");
+	char *ProblemType = (char *)configGet("problemtype");
+	
+    #ifdef DEBUG
+        printf("1: %d 2: %d 3: %lf 4: %d 5: %s 6: %s\n", MaxIter, SearchVar, HitRatio, NumProcs, Name, ProblemType);
+    #endif
+
+    InitProblem(Name, MaxIter, HitRatio, SearchVar, ProblemType, NumProcs);
+    printf("Initialized Problem\n");
+    fflush(stdout);
+
+    for (int fs1 = 1; fs1 <= MaxIter; fs1++) {		
+		printf("******************************** StepW: %d **********************************\n", fs1);
+		GoInt nresults = StepW();
+
+		for (int ires = 0; ires < nresults; ires++) {
+			GoInt testscore = 0;
+			GoInt ncoeff = 0;
+			
+			char* stepRes = GetStepResult(&testscore, &ncoeff);
+			GoFloat64 *coeff = (GoFloat64 *)malloc(nUsableVars * sizeof(GoFloat64));
+			
+			for(int icoeff = 0; icoeff < nUsableVars; icoeff++) {
+				coeff[icoeff] = 0;
+			}
+			printf("C: push/pop (%d,%d) %s\n", fs1, ires, stepRes);
+            printf("C: TestScore %d\n", testscore);
+			for(int icoeff = 0; icoeff < ncoeff; icoeff++){
+				GoFloat64 coeffVal = GetCoeffResult();
+				printf("C: coeff vals: %f\n", coeffVal);
+			}
+		}
+		fflush(stdout);
+	}
+}
+
+//TODO: Dynamic overwrite
+void ParseArgs(int argc, char *argv[], char** problemName, char **initMethod, char **growMethod, GoInt *nPeel, GoInt *nEvals, GoInt *maxIter) {
+    if(argc < 2 ){
+        printf("Usage: %s ProblemName [-evals=3] [-peel=3] [-iter=200] [-init=method1] [-grow=method1]\n\n", argv[0]);
+        printf("Using default Problem: %s\n", *problemName);
+        perror("Missing required argument 1: ProblemName, eg. Pagie_1, Korns_02\n");
+    } else {
+        *problemName = strdup(argv[1]);
+        for(int i = 2; i < argc; i++) {
+            if(strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) {
+                printf("Usage: %s ProblemName [-evals=3] [-peel=3] [-iter=200] [-init=method1] [-grow=method1]\n\n" , argv[0]);
+                exit(EXIT_SUCCESS);
+            } else if(strncmp(argv[i], "-evals", 6) == 0) {
+                sscanf(argv[i], "-evals=%ld", nEvals);
+            } else if(strncmp(argv[i], "-peel", 5) == 0) {
+                sscanf(argv[i], "-peel=%ld", nPeel);
+            } else if(strncmp(argv[i], "-iter", 5) == 0) {
+                sscanf(argv[i], "-iter=%ld", maxIter);
+            } else if(strncmp(argv[i], "-init", 5) == 0) {
+                sscanf(argv[i], "-init=%s", *initMethod);
+            } else if(strncmp(argv[i], "-grow", 5) == 0) {
+                sscanf(argv[i], "-grow=%s", *growMethod);
+            } else {
+                char msg[MAX_CHAR];
+                strcpy(msg, "Unkown argument: ");
+                perror(strcat(msg, argv[i]));
+            }
+        }
+    }
+}
+
+int main(int argc, char *argv[]) {
+    char *problemName = strdup("Pagie_1");
+    GoInt *nEvals = malloc(sizeof(GoInt));
+    GoInt *nPeel = malloc(sizeof(GoInt));
+    GoInt *maxIter = malloc(sizeof(GoInt));
+    GoInt *numProcs = malloc(sizeof(GoInt));
+    *nEvals = 3;
+    *nPeel = 3;
+    *maxIter = 200;
+    *numProcs = 12;
+    char *initMethod = strdup("method1");
+    char *growMethod = strdup("method1");
+    ParseArgs(argc, argv, &problemName, &initMethod, &growMethod, nPeel, nEvals, maxIter);
+
+    printf("MaxIter: %ld\n", *maxIter);
+    printf("Evals: %ld\n", *nEvals);
+    printf("InitMethod: %s\n", initMethod);
+
+    //* Testdata
+    char tstPath[MAX_CHAR] = "go-code/go-pge/data/benchmark/"; //"../data/benchmark/";
+    strcat(tstPath, problemName);
+    strcat(tstPath, ".tst");
+
+    printf("TestFile %s\n", tstPath);
+    GoInt nTestEntries = 0;
+    GoInt nTestCols = 0;
+    char *TestDepHead, *TestIndHead;
+    GoFloat64 *TestData = ReadInputData(tstPath, &nTestEntries, &nTestCols, &TestDepHead, &TestIndHead);
+    printf("TestData: Entries %ld, Colums %ld\n", nTestEntries, nTestCols);
+    #ifdef DEBUG
+        PrintInputData(TestData, nTestEntries, nTestCols);
+    #endif
+
+    //* Traindata
+    char trnPath[MAX_CHAR] = "go-code/go-pge/data/benchmark/"; //"../data/benchmark/";
+    strcat(trnPath, problemName);
+    strcat(trnPath, ".trn");
+
+    printf("TrainFile %s\n", trnPath);
+    GoInt nTrainEntries = 0;
+    GoInt nTrainCols = 0;
+    char *TrainDepHead, *TrainIndHead;
+    GoFloat64 *TrainData = ReadInputData(trnPath, &nTrainEntries, &nTrainCols, &TrainDepHead, &TrainIndHead);
+    printf("TrainData: Entries %ld, Colums %ld\n", nTrainEntries, nTrainCols);
+    #ifdef DEBUG
+        PrintInputData(TrainData, nTrainEntries, nTrainCols);
+    #endif
+
+    //* Configfiles
+    char defaultConfPath[] = "go-code/go-pge/config/pge/pge_default.cfg"; //"../config/pge/pge_default.cfg";
+    printf("Default Config Path %s\n", defaultConfPath);
+    ReadConfigFile(defaultConfPath);
+
+    char confPath[MAX_CHAR] = "go-code/go-pge/config/prob/bench/"; //"../config/prob/bench/";
+    strcat(confPath, problemName);
+    strcat(confPath, ".cfg");
+    printf("Config Path %s\n", confPath);
+    ReadConfigFile(confPath);
+
+    configPrint();
+    #ifdef DEBUG
+        configPrint();
+    #endif
+
+    //Overwrite with args
+    configPrepend(strdup("growmethod"), growMethod);
+    configPrepend(strdup("initmethod"), initMethod);
+    configPrepend(strdup("evalcnt"), nEvals);
+    configPrepend(strdup("peelcnt"), nPeel);
+    configPrepend(strdup("maxiter"), maxIter);
+    configPrepend(strdup("name"), problemName);
+    configPrepend(strdup("numprocs"), numProcs);
+
+    //* RunPGE
+    RunTest(TrainData, nTrainEntries, nTrainCols, TestData, nTestEntries, nTestCols, TrainDepHead, TrainIndHead, TestDepHead, TestIndHead);
+
+    //* Dispose
+    free(TestData);
+    TestData = NULL;
+
+    free(TrainData);
+    TrainData = NULL;
+
+    configDispose();
+
+    return EXIT_SUCCESS;
+}
