Index: trunk/sources/HeuristicLab.CEDMA.Server/DispatcherBase.cs
===================================================================
--- trunk/sources/HeuristicLab.CEDMA.Server/DispatcherBase.cs	(revision 1287)
+++ trunk/sources/HeuristicLab.CEDMA.Server/DispatcherBase.cs	(revision 1287)
@@ -0,0 +1,209 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms;
+using HeuristicLab.PluginInfrastructure;
+using System.Net;
+using System.ServiceModel;
+using HeuristicLab.CEDMA.DB.Interfaces;
+using HeuristicLab.CEDMA.DB;
+using System.ServiceModel.Description;
+using System.Linq;
+using HeuristicLab.CEDMA.Core;
+using HeuristicLab.GP.StructureIdentification;
+using HeuristicLab.Data;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.CEDMA.Server {
+  public abstract class DispatcherBase : IDispatcher {
+    public enum ModelComplexity { Low, Medium, High };
+    public enum Algorithm { StandardGpRegression, OffspringGpRegression, StandardGpClassification, OffspringGpClassification, StandardGpForecasting, OffspringGpForecasting };
+
+    private IStore store;
+    private ModelComplexity[] possibleComplexities = new ModelComplexity[] { ModelComplexity.Low, ModelComplexity.Medium, ModelComplexity.High };
+    private Dictionary<LearningTask, Algorithm[]> possibleAlgorithms = new Dictionary<LearningTask, Algorithm[]>() {
+      {LearningTask.Classification, new Algorithm[] { Algorithm.StandardGpClassification, Algorithm.OffspringGpClassification }},
+      {LearningTask.Regression, new Algorithm[] { Algorithm.StandardGpRegression, Algorithm.OffspringGpRegression }},
+      {LearningTask.TimeSeries, new Algorithm[] { Algorithm.StandardGpForecasting, Algorithm.OffspringGpForecasting }}
+    };
+
+    private static int MaxGenerations {
+      get { return 3; }
+    }
+
+    private static int MaxEvaluatedSolutions {
+      get { return 3000; }
+    }
+
+    public DispatcherBase(IStore store) {
+      this.store = store;
+    }
+
+    public Execution GetNextJob() {
+      // find and select a dataset
+      var dataSetVar = new HeuristicLab.CEDMA.DB.Interfaces.Variable("DataSet");
+      var dataSetQuery = new Statement[] {
+        new Statement(dataSetVar, Ontology.PredicateInstanceOf, Ontology.TypeDataSet)
+      };
+
+      Entity[] datasets = store.Query("?DataSet <" + Ontology.PredicateInstanceOf.Uri + "> <" + Ontology.TypeDataSet.Uri + "> .")
+        .Select(x => (Entity)x.Get("DataSet"))
+        .ToArray();
+
+      // no datasets => do nothing
+      if (datasets.Length == 0) return null;
+
+      Entity dataSetEntity = SelectDataSet(datasets);
+      DataSet dataSet = new DataSet(store, dataSetEntity);
+
+      int targetVariable = SelectTargetVariable(dataSet, dataSet.Problem.AllowedTargetVariables.ToArray());
+      Algorithm selectedAlgorithm = SelectAlgorithm(dataSet, targetVariable, possibleAlgorithms[dataSet.Problem.LearningTask]);
+      string targetVariableName = dataSet.Problem.GetVariableName(targetVariable);
+      ModelComplexity selectedComplexity = SelectComplexity(dataSet, targetVariable, selectedAlgorithm, possibleComplexities);
+
+      Execution exec = CreateExecution(dataSet.Problem, targetVariable, selectedAlgorithm, selectedComplexity);
+      if (exec != null) {
+        exec.DataSetEntity = dataSetEntity;
+        exec.TargetVariable = targetVariableName;
+      }
+      return exec;
+    }
+
+    public abstract Entity SelectDataSet(Entity[] datasets);
+    public abstract int SelectTargetVariable(DataSet dataSet, int[] targetVariables);
+    public abstract Algorithm SelectAlgorithm(DataSet dataSet, int targetVariable, Algorithm[] possibleAlgorithms);
+    public abstract ModelComplexity SelectComplexity(DataSet dataSet, int targetVariable, Algorithm algorithm, ModelComplexity[] possibleComplexities);
+
+    private Execution CreateExecution(Problem problem, int targetVariable, Algorithm algorithm, ModelComplexity complexity) {
+      switch (algorithm) {
+        case Algorithm.StandardGpRegression: {
+            var algo = new HeuristicLab.GP.StructureIdentification.StandardGP();
+            SetComplexityParameters(algo, complexity);
+            SetProblemParameters(algo, problem, targetVariable);
+            algo.PopulationSize = 10000;
+            algo.MaxGenerations = MaxGenerations;
+            Execution exec = new Execution(algo.Engine);
+            exec.Description = "StandardGP - Complexity: " + complexity;
+            return exec;
+          }
+        case Algorithm.OffspringGpRegression: {
+            var algo = new HeuristicLab.GP.StructureIdentification.OffspringSelectionGP();
+            SetComplexityParameters(algo, complexity);
+            SetProblemParameters(algo, problem, targetVariable);
+            algo.MaxEvaluatedSolutions = MaxEvaluatedSolutions;
+            Execution exec = new Execution(algo.Engine);
+            exec.Description = "OffspringGP - Complexity: " + complexity;
+            return exec;
+          }
+        case Algorithm.StandardGpClassification: {
+            var algo = new HeuristicLab.GP.StructureIdentification.Classification.StandardGP();
+            SetComplexityParameters(algo, complexity);
+            SetProblemParameters(algo, problem, targetVariable);
+            algo.PopulationSize = 10000;
+            algo.MaxGenerations = MaxGenerations;
+            Execution exec = new Execution(algo.Engine);
+            exec.Description = "StandardGP - Complexity: " + complexity;
+            return exec;
+          }
+        case Algorithm.OffspringGpClassification: {
+            var algo = new HeuristicLab.GP.StructureIdentification.Classification.OffspringSelectionGP();
+            SetComplexityParameters(algo, complexity);
+            SetProblemParameters(algo, problem, targetVariable);
+            algo.MaxEvaluatedSolutions = MaxEvaluatedSolutions;
+            Execution exec = new Execution(algo.Engine);
+            exec.Description = "OffspringGP - Complexity: " + complexity;
+            return exec;
+          }
+        case Algorithm.StandardGpForecasting: {
+            var algo = new HeuristicLab.GP.StructureIdentification.TimeSeries.StandardGP();
+            SetComplexityParameters(algo, complexity);
+            SetProblemParameters(algo, problem, targetVariable);
+            algo.PopulationSize = 10000;
+            algo.MaxGenerations = MaxGenerations;
+            Execution exec = new Execution(algo.Engine);
+            exec.Description = "StandardGP - Complexity: " + complexity;
+            return exec;
+          }
+        case Algorithm.OffspringGpForecasting: {
+            var algo = new HeuristicLab.GP.StructureIdentification.TimeSeries.OffspringSelectionGP();
+            SetComplexityParameters(algo, complexity);
+            SetProblemParameters(algo, problem, targetVariable);
+            algo.MaxEvaluatedSolutions = MaxEvaluatedSolutions;
+            Execution exec = new Execution(algo.Engine);
+            exec.Description = "OffspringGP - Complexity: " + complexity;
+            return exec;
+          }
+        default: {
+            return null;
+          }
+      }
+    }
+
+    private void SetComplexityParameters(AlgorithmBase algo, ModelComplexity complexity) {
+      switch (complexity) {
+        case ModelComplexity.Low: {
+            algo.MaxTreeHeight = 5;
+            algo.MaxTreeSize = 20;
+            break;
+          }
+        case ModelComplexity.Medium: {
+            algo.MaxTreeHeight = 10;
+            algo.MaxTreeSize = 100;
+            break;
+          }
+        case ModelComplexity.High: {
+            algo.MaxTreeHeight = 12;
+            algo.MaxTreeSize = 200;
+            break;
+          }
+      }
+    }
+
+    private void SetProblemParameters(AlgorithmBase algo, Problem problem, int targetVariable) {
+      algo.ProblemInjector.GetVariable("Dataset").Value = problem.DataSet;
+      algo.ProblemInjector.GetVariable("TargetVariable").GetValue<IntData>().Data = targetVariable;
+      algo.ProblemInjector.GetVariable("TrainingSamplesStart").GetValue<IntData>().Data = problem.TrainingSamplesStart;
+      algo.ProblemInjector.GetVariable("TrainingSamplesEnd").GetValue<IntData>().Data = problem.TrainingSamplesEnd;
+      algo.ProblemInjector.GetVariable("ValidationSamplesStart").GetValue<IntData>().Data = problem.ValidationSamplesStart;
+      algo.ProblemInjector.GetVariable("ValidationSamplesEnd").GetValue<IntData>().Data = problem.ValidationSamplesEnd;
+      algo.ProblemInjector.GetVariable("TestSamplesStart").GetValue<IntData>().Data = problem.TestSamplesStart;
+      algo.ProblemInjector.GetVariable("TestSamplesEnd").GetValue<IntData>().Data = problem.TestSamplesEnd;
+      ItemList<IntData> allowedFeatures = algo.ProblemInjector.GetVariable("AllowedFeatures").GetValue<ItemList<IntData>>();
+      foreach (int allowedFeature in problem.AllowedInputVariables) allowedFeatures.Add(new IntData(allowedFeature));
+
+      if (problem.LearningTask == LearningTask.TimeSeries) {
+        algo.ProblemInjector.GetVariable("Autoregressive").GetValue<BoolData>().Data = problem.AutoRegressive;
+        algo.ProblemInjector.GetVariable("MinTimeOffset").GetValue<IntData>().Data = problem.MinTimeOffset;
+        algo.ProblemInjector.GetVariable("MaxTimeOffset").GetValue<IntData>().Data = problem.MaxTimeOffset;
+      } else if (problem.LearningTask == LearningTask.Classification) {
+        ItemList<DoubleData> classValues = algo.ProblemInjector.GetVariable("TargetClassValues").GetValue<ItemList<DoubleData>>();
+        foreach (double classValue in GetDifferentClassValues(problem.DataSet, targetVariable)) classValues.Add(new DoubleData(classValue));
+      }
+    }
+
+    private IEnumerable<double> GetDifferentClassValues(HeuristicLab.DataAnalysis.Dataset dataset, int targetVariable) {
+      return Enumerable.Range(0, dataset.Rows).Select(x => dataset.GetValue(x, targetVariable)).Distinct();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.CEDMA.Server/Executer.cs
===================================================================
--- trunk/sources/HeuristicLab.CEDMA.Server/Executer.cs	(revision 1287)
+++ trunk/sources/HeuristicLab.CEDMA.Server/Executer.cs	(revision 1287)
@@ -0,0 +1,181 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms;
+using HeuristicLab.PluginInfrastructure;
+using System.Net;
+using System.ServiceModel;
+using HeuristicLab.CEDMA.DB.Interfaces;
+using HeuristicLab.CEDMA.DB;
+using System.ServiceModel.Description;
+using System.Linq;
+using HeuristicLab.CEDMA.Core;
+using HeuristicLab.GP.StructureIdentification;
+using HeuristicLab.Data;
+using HeuristicLab.Grid;
+using System.Diagnostics;
+using HeuristicLab.Core;
+using System.Threading;
+
+namespace HeuristicLab.CEDMA.Server {
+  public class Executer {
+    private IDispatcher dispatcher;
+    private JobManager jobManager;
+    private IStore store;
+    private Dictionary<WaitHandle, Execution> activeExecutions;
+
+    private TimeSpan StartJobInterval {
+      get { return TimeSpan.FromMilliseconds(500); }
+    }
+
+    private TimeSpan WaitForFinishedJobsTimeout {
+      get { return TimeSpan.FromMilliseconds(100); }
+    }
+
+    private int maxActiveJobs;
+    public int MaxActiveJobs {
+      get { return maxActiveJobs; }
+      set {
+        if (value < 0) throw new ArgumentException("Only positive values are allowed for MaxActiveJobs");
+        maxActiveJobs = value;
+      }
+    }
+
+    public Executer(IDispatcher dispatcher, IStore store, string gridUrl) {
+      activeExecutions = new Dictionary<WaitHandle, Execution>();
+      maxActiveJobs = 10;
+      this.dispatcher = dispatcher;
+      this.store = store;
+      this.jobManager = new JobManager(gridUrl);
+      jobManager.Reset();
+    }
+
+    internal void Start() {
+      new Thread(StartJobs).Start();
+    }
+
+    private void StartJobs() {
+      List<WaitHandle> wh = new List<WaitHandle>();
+      Dictionary<WaitHandle, AtomicOperation> activeOperations = new Dictionary<WaitHandle, AtomicOperation>();
+      while (true) {
+        try {
+          // start new jobs as long as there are less than MaxActiveJobs 
+          while (wh.Count < MaxActiveJobs) {
+            Thread.Sleep(StartJobInterval);
+            // get an execution from the dispatcher and execute in grid via job-manager
+            Execution execution = dispatcher.GetNextJob();
+            if (execution != null) {
+              AtomicOperation op = new AtomicOperation(execution.Engine.OperatorGraph.InitialOperator, execution.Engine.GlobalScope);
+              WaitHandle opWh = jobManager.BeginExecuteOperation(execution.Engine.GlobalScope, op);
+              wh.Add(opWh);
+              activeOperations.Add(opWh, op);
+              lock (activeExecutions) {
+                activeExecutions.Add(opWh, execution);
+              }
+            }
+          }
+          // wait until any job is finished
+          WaitHandle[] whArr = wh.ToArray();
+          int readyHandleIndex = WaitHandle.WaitAny(whArr, WaitForFinishedJobsTimeout);
+          if (readyHandleIndex != WaitHandle.WaitTimeout) {
+            WaitHandle readyHandle = whArr[readyHandleIndex];
+            AtomicOperation finishedOp = activeOperations[readyHandle];
+            wh.Remove(readyHandle);
+            Execution finishedExecution = null;
+            lock (activeExecutions) {
+              finishedExecution = activeExecutions[readyHandle];
+              activeExecutions.Remove(readyHandle);
+            }
+            activeOperations.Remove(readyHandle);
+            ProcessingEngine finishedEngine = null;
+            try {
+              finishedEngine = jobManager.EndExecuteOperation(finishedOp);
+            }
+            catch (Exception badEx) {
+              Trace.WriteLine("CEDMA Executer: Exception in job execution thread. " + badEx.Message);
+            }
+            if (finishedEngine != null) {
+              StoreResults(finishedExecution, finishedEngine);
+            }
+          }
+        }
+        catch (Exception ex) {
+          Trace.WriteLine("CEDMA Executer: Exception in job-management thread. " + ex.Message);
+        }
+      }
+    }
+
+    private void StoreResults(Execution finishedExecution, ProcessingEngine finishedEngine) {
+      Entity model = new Entity(Ontology.CedmaNameSpace + Guid.NewGuid());
+      store.Add(new Statement(model, Ontology.PredicateInstanceOf, Ontology.TypeGeneticProgrammingFunctionTree));
+      store.Add(new Statement(finishedExecution.DataSetEntity, Ontology.PredicateHasModel, model));
+      StoreModelAttribute(model, Ontology.TargetVariable, finishedExecution.TargetVariable);
+      Scope bestModelScope = finishedEngine.GlobalScope.GetVariableValue<Scope>("BestValidationSolution", false);
+      StoreModelVariable(model, Ontology.TrainingMeanSquaredError, bestModelScope, "Quality");
+      StoreModelVariable(model, Ontology.ValidationMeanSquaredError, bestModelScope, "ValidationQuality");
+      StoreModelVariable(model, Ontology.TestMeanSquaredError, bestModelScope, "TestQuality");
+      StoreModelVariable(model, Ontology.TrainingMeanAbsolutePercentageError, bestModelScope, "TrainingMAPE");
+      StoreModelVariable(model, Ontology.ValidationMeanAbsolutePercentageError, bestModelScope, "ValidationMAPE");
+      StoreModelVariable(model, Ontology.TestMeanAbsolutePercentageError, bestModelScope, "TestMAPE");
+      StoreModelVariable(model, Ontology.TrainingMeanAbsolutePercentageOfRangeError, bestModelScope, "TrainingMAPRE");
+      StoreModelVariable(model, Ontology.ValidationMeanAbsolutePercentageOfRangeError, bestModelScope, "ValidationMAPRE");
+      StoreModelVariable(model, Ontology.TestMeanAbsolutePercentageOfRangeError, bestModelScope, "TestMAPRE");
+      StoreModelVariable(model, Ontology.TrainingCoefficientOfDetermination, bestModelScope, "TrainingR2");
+      StoreModelVariable(model, Ontology.ValidationCoefficientOfDetermination, bestModelScope, "ValidationR2");
+      StoreModelVariable(model, Ontology.TestCoefficientOfDetermination, bestModelScope, "TestR2");
+      StoreModelVariable(model, Ontology.TrainingTheilsInequalityCoefficient, bestModelScope, "TrainingTheilInequalityCoefficient");
+      StoreModelVariable(model, Ontology.ValidationTheilsInequalityCoefficient, bestModelScope, "ValidationTheilInequalityCoefficient");
+      StoreModelVariable(model, Ontology.TestTheilsInequalityCoefficient, bestModelScope, "TestTheilInequalityCoefficient");
+      StoreModelVariable(model, Ontology.TrainingAccuracy, bestModelScope, "TrainingAccuracy");
+      StoreModelVariable(model, Ontology.ValidationAccuracy, bestModelScope, "ValidationAccuracy");
+      StoreModelVariable(model, Ontology.TestAccuracy, bestModelScope, "TestAccuracy");
+      StoreModelVariable(model, Ontology.TreeSize, bestModelScope, "TreeSize");
+      StoreModelVariable(model, Ontology.TreeHeight, bestModelScope, "TreeHeight");
+      StoreModelVariable(model, Ontology.EvaluatedSolutions, bestModelScope, "EvaluatedSolutions");
+
+      byte[] serializedModel = PersistenceManager.SaveToGZip(bestModelScope.GetVariableValue("FunctionTree", false));
+      store.Add(new Statement(model, Ontology.PredicateSerializedData, new Literal(Convert.ToBase64String(serializedModel))));
+    }
+
+    private void StoreModelVariable(Entity model, Entity entity, Scope scope, string variableName) {
+      if (scope.GetVariable(variableName) != null)
+        StoreModelAttribute(model, entity, scope.GetVariableValue<ObjectData>(variableName, false).Data);
+    }
+
+    private void StoreModelAttribute(Entity model, Entity predicate, object value) {
+      store.Add(new Statement(model, predicate, new Literal(value)));
+    }
+
+    internal string[] GetJobs() {
+      lock (activeExecutions) {
+        string[] retVal = new string[activeExecutions.Count];
+        int i = 0;
+        foreach (Execution e in activeExecutions.Values) {
+          retVal[i++] = "Target-Variable: " + e.TargetVariable + " " + e.Description;
+        }
+        return retVal;
+      }
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.CEDMA.Server/Execution.cs
===================================================================
--- trunk/sources/HeuristicLab.CEDMA.Server/Execution.cs	(revision 1287)
+++ trunk/sources/HeuristicLab.CEDMA.Server/Execution.cs	(revision 1287)
@@ -0,0 +1,71 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms;
+using HeuristicLab.PluginInfrastructure;
+using System.Net;
+using System.ServiceModel;
+using HeuristicLab.CEDMA.DB.Interfaces;
+using HeuristicLab.CEDMA.DB;
+using System.ServiceModel.Description;
+using System.Linq;
+using HeuristicLab.CEDMA.Core;
+using HeuristicLab.GP.StructureIdentification;
+using HeuristicLab.Data;
+using HeuristicLab.Grid;
+using System.Diagnostics;
+using HeuristicLab.Core;
+using System.Threading;
+
+namespace HeuristicLab.CEDMA.Server {
+  public class Execution {
+    private Entity dataSetEntity;
+    public Entity DataSetEntity {
+      get { return dataSetEntity; }
+      set { dataSetEntity = value; }
+    }
+
+    private IEngine engine;
+    public IEngine Engine {
+      get { return engine; }
+      set { engine = value; }
+    }
+
+    private string targetVariable;
+    public string TargetVariable {
+      get { return targetVariable; }
+      set { targetVariable = value; }
+    }
+
+    private string description;
+    public string Description {
+      get { return description; }
+      set { description = value; }
+    }
+
+    public Execution(IEngine engine) {
+      this.engine = engine;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.CEDMA.Server/HeuristicLab.CEDMA.Server.csproj
===================================================================
--- trunk/sources/HeuristicLab.CEDMA.Server/HeuristicLab.CEDMA.Server.csproj	(revision 852)
+++ trunk/sources/HeuristicLab.CEDMA.Server/HeuristicLab.CEDMA.Server.csproj	(revision 1287)
@@ -75,5 +75,10 @@
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="RunScheduler.cs" />
+    <Compile Include="DispatcherBase.cs" />
+    <Compile Include="IDispatcher.cs" />
+    <Compile Include="Execution.cs" />
+    <Compile Include="Executer.cs" />
+    <Compile Include="RandomDispatcher.cs" />
+    <Compile Include="Server.cs" />
     <Compile Include="ServerApplication.cs" />
     <Compile Include="HeuristicLabCedmaServerPlugin.cs" />
@@ -103,7 +108,23 @@
       <Name>HeuristicLab.Core</Name>
     </ProjectReference>
+    <ProjectReference Include="..\HeuristicLab.DataAnalysis\HeuristicLab.DataAnalysis.csproj">
+      <Project>{7DD3A97A-56E9-462F-90E2-A351FE7AF5C2}</Project>
+      <Name>HeuristicLab.DataAnalysis</Name>
+    </ProjectReference>
     <ProjectReference Include="..\HeuristicLab.Data\HeuristicLab.Data.csproj">
       <Project>{F473D9AF-3F09-4296-9F28-3C65118DAFFA}</Project>
       <Name>HeuristicLab.Data</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\HeuristicLab.GP.StructureIdentification.Classification\HeuristicLab.GP.StructureIdentification.Classification.csproj">
+      <Project>{7C20D100-8BEB-433A-9499-F075E2CB9297}</Project>
+      <Name>HeuristicLab.GP.StructureIdentification.Classification</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\HeuristicLab.GP.StructureIdentification.TimeSeries\HeuristicLab.GP.StructureIdentification.TimeSeries.csproj">
+      <Project>{6084CFB5-733F-449D-9F92-2E40D13F0514}</Project>
+      <Name>HeuristicLab.GP.StructureIdentification.TimeSeries</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\HeuristicLab.GP.StructureIdentification\HeuristicLab.GP.StructureIdentification.csproj">
+      <Project>{74223A32-C726-4978-BE78-37113A18373C}</Project>
+      <Name>HeuristicLab.GP.StructureIdentification</Name>
     </ProjectReference>
     <ProjectReference Include="..\HeuristicLab.Grid\HeuristicLab.Grid.csproj">
Index: trunk/sources/HeuristicLab.CEDMA.Server/IDispatcher.cs
===================================================================
--- trunk/sources/HeuristicLab.CEDMA.Server/IDispatcher.cs	(revision 1287)
+++ trunk/sources/HeuristicLab.CEDMA.Server/IDispatcher.cs	(revision 1287)
@@ -0,0 +1,42 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms;
+using HeuristicLab.PluginInfrastructure;
+using System.Net;
+using System.ServiceModel;
+using HeuristicLab.CEDMA.DB.Interfaces;
+using HeuristicLab.CEDMA.DB;
+using System.ServiceModel.Description;
+using System.Linq;
+using HeuristicLab.CEDMA.Core;
+using HeuristicLab.GP.StructureIdentification;
+using HeuristicLab.Data;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.CEDMA.Server {
+  public interface IDispatcher {
+    Execution GetNextJob();
+  }
+}
Index: trunk/sources/HeuristicLab.CEDMA.Server/RandomDispatcher.cs
===================================================================
--- trunk/sources/HeuristicLab.CEDMA.Server/RandomDispatcher.cs	(revision 1287)
+++ trunk/sources/HeuristicLab.CEDMA.Server/RandomDispatcher.cs	(revision 1287)
@@ -0,0 +1,62 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms;
+using HeuristicLab.PluginInfrastructure;
+using System.Net;
+using System.ServiceModel;
+using HeuristicLab.CEDMA.DB.Interfaces;
+using HeuristicLab.CEDMA.DB;
+using System.ServiceModel.Description;
+using System.Linq;
+using HeuristicLab.CEDMA.Core;
+using HeuristicLab.GP.StructureIdentification;
+using HeuristicLab.Data;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.CEDMA.Server {
+  public class RandomDispatcher : DispatcherBase {
+    private Random random;
+    public RandomDispatcher(IStore store)
+      : base(store) {
+      random = new Random();
+    }
+
+    public override Algorithm SelectAlgorithm(DataSet dataSet, int targetVariable, Algorithm[] possibleAlgorithms) {
+      return possibleAlgorithms[random.Next(possibleAlgorithms.Length)];
+    }
+
+    public override ModelComplexity SelectComplexity(DataSet dataSet, int targetVariable, Algorithm algorithm, ModelComplexity[] possibleComplexities) {
+      return possibleComplexities[random.Next(possibleComplexities.Length)];
+    }
+
+    public override Entity SelectDataSet(Entity[] datasets) {
+      return datasets[random.Next(datasets.Length)];
+    }
+
+    public override int SelectTargetVariable(DataSet dataSet, int[] targetVariables) {
+      return targetVariables[random.Next(targetVariables.Length)];
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.CEDMA.Server/RunScheduler.cs
===================================================================
--- trunk/sources/HeuristicLab.CEDMA.Server/RunScheduler.cs	(revision 852)
+++ 	(revision )
@@ -1,165 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using HeuristicLab.CEDMA.DB;
-using HeuristicLab.CEDMA.DB.Interfaces;
-using HeuristicLab.Core;
-using System.Threading;
-using HeuristicLab.Grid;
-using System.Diagnostics;
-using HeuristicLab.Data;
-using HeuristicLab.CEDMA.Core;
-using HeuristicLab.Operators;
-
-namespace HeuristicLab.CEDMA.Server {
-  public class RunScheduler {
-    private class Job {
-      public long AgentId;
-      public WaitHandle WaitHandle;
-      public AtomicOperation Operation;
-    }
-    private string serverUri;
-    private Database database;
-    private JobManager jobManager;
-    private const int RELEASE_INTERVAL = 5;
-    private object remoteCommLock = new object();
-    private object queueLock = new object();
-    private Queue<Job> jobQueue;
-    private AutoResetEvent runningJobs = new AutoResetEvent(false);
-
-    public RunScheduler(Database database, JobManager jobManager, string serverUri) {
-      this.database = database;
-      this.jobManager = jobManager;
-      this.serverUri = serverUri;
-      jobQueue = new Queue<Job>();
-      Thread resultsGatheringThread = new Thread(GatherResults);
-      resultsGatheringThread.Start();
-    }
-    public void Run() {
-      while(true) {
-        ReleaseWaitingRuns();
-        Thread.Sleep(TimeSpan.FromSeconds(RELEASE_INTERVAL));
-      }
-    }
-    private void ReleaseWaitingRuns() {
-      ICollection<AgentEntry> agents;
-      lock(remoteCommLock) {
-        agents = database.GetAgents(ProcessStatus.Waiting);
-      }
-      foreach(AgentEntry entry in agents) {
-        Scope scope = new Scope();
-        // initialize CEDMA variables for the execution of the agent
-        scope.AddVariable(new Variable("AgentId", new IntData((int)entry.Id)));
-        scope.AddVariable(new Variable("CedmaServerUri", new StringData(serverUri)));
-
-        byte[] rawData = database.GetAgentRawData(entry.Id);
-        IOperatorGraph opGraph = (IOperatorGraph)PersistenceManager.RestoreFromGZip(rawData);
-
-        PatchLinks(opGraph, new Dictionary<long, IOperator>());
-
-        AtomicOperation operation = new AtomicOperation(opGraph.InitialOperator, scope);
-        WaitHandle wHandle;
-        lock(remoteCommLock) {
-          wHandle = jobManager.BeginExecuteOperation(operation.Scope, operation);
-          database.UpdateAgent(entry.Id, ProcessStatus.Active);
-        }
-
-        Job job = new Job();
-        job.AgentId = entry.Id;
-        job.Operation = operation;
-        job.WaitHandle = wHandle;
-
-        lock(queueLock) {
-          jobQueue.Enqueue(job);
-          runningJobs.Set();
-        }
-      }
-    }
-
-    private void PatchLinks(IOperatorGraph opGraph, Dictionary<long, IOperator> patchedOperators) {
-      Dictionary<IOperator, IOperator> patchDictionary = new Dictionary<IOperator, IOperator>();
-      foreach(IOperator op in opGraph.Operators) {
-        IOperator patched = PatchLinks(op, patchedOperators);
-        patchDictionary.Add(op, patched);
-      }
-      foreach(KeyValuePair<IOperator, IOperator> p in patchDictionary) {
-        IOperator original = p.Key;
-        IOperator patch = p.Value;
-        if(original != patch) {
-          foreach(IOperator subOperator in original.SubOperators) {
-            patch.AddSubOperator(subOperator);
-          }
-          if(opGraph.InitialOperator == original)
-            opGraph.InitialOperator = patch;
-          opGraph.RemoveOperator(original.Guid);
-          opGraph.AddOperator(patch);
-        }
-      }
-    }
-
-    private IOperator PatchLinks(IOperator op, Dictionary<long, IOperator> patchedOperators) {
-      if(op is OperatorLink) {
-        OperatorLink link = op as OperatorLink;
-        if(patchedOperators.ContainsKey(link.Id)) {
-          return patchedOperators[link.Id];
-        } else {
-          OperatorEntry targetEntry = database.GetOperator(link.Id);
-          IOperator target = (IOperator)PersistenceManager.RestoreFromGZip(targetEntry.RawData);
-          patchedOperators.Add(link.Id, target);
-          PatchLinks(target, patchedOperators);
-          return target;
-        }
-      } else if(op is CombinedOperator) {
-        PatchLinks(((CombinedOperator)op).OperatorGraph, patchedOperators);
-        return op;
-      }
-      return op;
-    }
-
-    private void GatherResults() {
-      try {
-        while(true) {
-          Job job = null;
-          lock(queueLock) if(jobQueue.Count > 0) job = jobQueue.Dequeue();
-          if(job == null) runningJobs.WaitOne();
-          else {
-            job.WaitHandle.WaitOne();
-            job.WaitHandle.Close();
-            lock(remoteCommLock) {
-              try {
-                jobManager.EndExecuteOperation(job.Operation);
-                database.UpdateAgent(job.AgentId, ProcessStatus.Finished);
-              } catch(JobExecutionException ex) {
-                database.UpdateAgent(job.AgentId, ProcessStatus.Error);
-              }
-            }
-          }
-        }
-      } finally {
-        Debug.Assert(false); // make sure we are notified when this thread is killed while debugging
-      }
-    }
-  }
-}
Index: trunk/sources/HeuristicLab.CEDMA.Server/Server.cs
===================================================================
--- trunk/sources/HeuristicLab.CEDMA.Server/Server.cs	(revision 1287)
+++ trunk/sources/HeuristicLab.CEDMA.Server/Server.cs	(revision 1287)
@@ -0,0 +1,86 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms;
+using HeuristicLab.PluginInfrastructure;
+using System.Net;
+using System.ServiceModel;
+using HeuristicLab.CEDMA.DB.Interfaces;
+using HeuristicLab.CEDMA.DB;
+using System.ServiceModel.Description;
+
+namespace HeuristicLab.CEDMA.Server {
+  public class Server {
+    private ServiceHost host;
+    private IStore store;
+
+    private string gridServiceUrl;
+
+    public string GridServiceUrl {
+      get { return gridServiceUrl; }
+      set { gridServiceUrl = value; }
+    }
+
+    private string cedmaServiceUrl;
+
+    public string CedmaServiceUrl {
+      get { return cedmaServiceUrl; }
+      set { cedmaServiceUrl = value; }
+    }
+
+    public Server(IStore store) {
+      IPAddress[] addresses = Dns.GetHostAddresses(Dns.GetHostName());
+      // windows XP returns the external ip on index 0 while windows vista returns the external ip as one of the last entries
+      // also if IPv6 protocol is installed we want to find an entry that is IPv4
+      int index = 0;
+      if (System.Environment.OSVersion.Version.Major >= 6) {
+        for (index = addresses.Length - 1; index >= 0; index--)
+          if (addresses[index].AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
+            break;
+      }
+      cedmaServiceUrl = "net.tcp://" + addresses[index] + ":8002/CEDMA";
+      this.store = store;
+    }
+
+    public void Start() {
+      host = new ServiceHost(store, new Uri(cedmaServiceUrl));
+      ServiceThrottlingBehavior throttlingBehavior = new ServiceThrottlingBehavior();
+      throttlingBehavior.MaxConcurrentSessions = 20;
+      host.Description.Behaviors.Add(throttlingBehavior);
+      try {
+        NetTcpBinding binding = new NetTcpBinding();
+        binding.SendTimeout = new TimeSpan(1, 0, 0);
+        binding.MaxReceivedMessageSize = 1000000000; // 100Mbytes
+        binding.ReaderQuotas.MaxStringContentLength = 1000000000; // also 100M chars
+        binding.ReaderQuotas.MaxArrayLength = 1000000000; // also 100M elements;
+        host.AddServiceEndpoint(typeof(IStore), binding, cedmaServiceUrl);
+        host.Open();
+      }
+      catch (CommunicationException ex) {
+        MessageBox.Show("An exception occurred: " + ex.Message);
+        host.Abort();
+      }
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.CEDMA.Server/ServerForm.cs
===================================================================
--- trunk/sources/HeuristicLab.CEDMA.Server/ServerForm.cs	(revision 852)
+++ trunk/sources/HeuristicLab.CEDMA.Server/ServerForm.cs	(revision 1287)
@@ -42,77 +42,36 @@
 namespace HeuristicLab.CEDMA.Server {
   public partial class ServerForm : Form {
-    private ServiceHost host;
-    private ServiceHost rdfHost;
-    private Database database;
+    private Server server;
     private Store store;
-    private static readonly string dbFile = AppDomain.CurrentDomain.BaseDirectory + "/test.db3";
-    private static readonly string connectionString = "Data Source=\"" + dbFile + "\";Pooling=False";
+    private IDispatcher dispatcher;
+    private Executer executer;
+
     private static readonly string rdfFile = AppDomain.CurrentDomain.BaseDirectory + "rdf_store.db3";
     private static readonly string rdfConnectionString = "sqlite:rdf:Data Source=\"" + rdfFile + "\"";
+
     public ServerForm() {
       InitializeComponent();
-      // windows XP returns the external ip on index 0 while windows vista returns the external ip on index 2
-      if(System.Environment.OSVersion.Version.Major >= 6) {
-        addressTextBox.Text = "net.tcp://" + Dns.GetHostAddresses(Dns.GetHostName())[2] + ":8002/CEDMA/World";
-      } else {
-        addressTextBox.Text = "net.tcp://" + Dns.GetHostAddresses(Dns.GetHostName())[0] + ":8002/CEDMA/World";
-      }
+      store = new Store(rdfConnectionString);
+      server = new Server(store);
+      server.Start();
+      addressTextBox.Text = server.CedmaServiceUrl;
     }
 
-    private void InitRunScheduler() {
-      JobManager jobManager = new JobManager(gridAddress.Text);
-      jobManager.Reset();
-      RunScheduler scheduler = new RunScheduler(database, jobManager, addressTextBox.Text);
-      Thread runSchedulerThread = new Thread(scheduler.Run);
-      runSchedulerThread.Start();
+    private void refreshTimer_Tick(object sender, EventArgs e) {
+      listBox.DataSource = executer.GetJobs();
     }
 
-    private void InitDatabase() {
-      DbProviderFactory fact;
-      fact = DbProviderFactories.GetFactory("System.Data.SQLite");
-      if(!System.IO.File.Exists(dbFile)) {
-        database = new Database(connectionString);
-        database.CreateNew();
-      } else {
-        database = new Database(connectionString);
-      }
+    private void connectButton_Click(object sender, EventArgs e) {
+      dispatcher = new RandomDispatcher(store);
+      executer = new Executer(dispatcher, store, gridAddress.Text);
+      executer.Start();
+      maxActiveJobsUpDown.Enabled = true;
+      maxActiveJobsUpDown.Value = executer.MaxActiveJobs;
+      connectButton.Enabled = false;
+      refreshTimer.Start();
     }
 
-    private void InitRdfStore() {
-      store = new Store(rdfConnectionString);
-    }
-
-    private void Start() {
-      InitDatabase();
-      InitRdfStore();
-      InitRunScheduler();
-
-      host = new ServiceHost(database, new Uri(addressTextBox.Text));
-      rdfHost = new ServiceHost(store, new Uri(addressTextBox.Text+"/RdfStore"));
-      ServiceThrottlingBehavior throttlingBehavior = new ServiceThrottlingBehavior();
-      throttlingBehavior.MaxConcurrentSessions = 20;
-      host.Description.Behaviors.Add(throttlingBehavior);
-      rdfHost.Description.Behaviors.Add(throttlingBehavior);
-      try {
-        NetTcpBinding binding = new NetTcpBinding();
-        binding.MaxReceivedMessageSize = 100000000; // 100Mbytes
-        binding.ReaderQuotas.MaxStringContentLength = 100000000; // also 100M chars
-        binding.ReaderQuotas.MaxArrayLength = 100000000; // also 100M elements;
-        binding.Security.Mode = SecurityMode.None;
-
-        host.AddServiceEndpoint(typeof(IDatabase), binding, addressTextBox.Text);
-        host.Open();
-        rdfHost.AddServiceEndpoint(typeof(IStore), binding, addressTextBox.Text+"/RdfStore");
-        rdfHost.Open();
-      } catch(CommunicationException ex) {
-        MessageBox.Show("An exception occurred: " + ex.Message);
-        host.Abort();
-        rdfHost.Abort();
-      }
-    }
-
-    private void startButton_Click(object sender, EventArgs e) {
-      Start();
-      startButton.Enabled = false;
+    private void maxActiveJobsUpDown_ValueChanged(object sender, EventArgs e) {
+      executer.MaxActiveJobs = Convert.ToInt32(maxActiveJobsUpDown.Value);
     }
   }
Index: trunk/sources/HeuristicLab.CEDMA.Server/ServerForm.designer.cs
===================================================================
--- trunk/sources/HeuristicLab.CEDMA.Server/ServerForm.designer.cs	(revision 852)
+++ trunk/sources/HeuristicLab.CEDMA.Server/ServerForm.designer.cs	(revision 1287)
@@ -45,11 +45,15 @@
     /// </summary>
     private void InitializeComponent() {
+      this.components = new System.ComponentModel.Container();
       this.addressTextBox = new System.Windows.Forms.TextBox();
       this.externalAddressLabel = new System.Windows.Forms.Label();
-      this.activeAgentsLabel = new System.Windows.Forms.Label();
-      this.activeAgentsTextBox = new System.Windows.Forms.TextBox();
       this.gridAddressLabel = new System.Windows.Forms.Label();
       this.gridAddress = new System.Windows.Forms.TextBox();
-      this.startButton = new System.Windows.Forms.Button();
+      this.connectButton = new System.Windows.Forms.Button();
+      this.listBox = new System.Windows.Forms.ListBox();
+      this.refreshTimer = new System.Windows.Forms.Timer(this.components);
+      this.maxActiveJobsUpDown = new System.Windows.Forms.NumericUpDown();
+      this.label1 = new System.Windows.Forms.Label();
+      ((System.ComponentModel.ISupportInitialize)(this.maxActiveJobsUpDown)).BeginInit();
       this.SuspendLayout();
       // 
@@ -71,23 +75,4 @@
       this.externalAddressLabel.Text = "&Address:";
       // 
-      // activeAgentsLabel
-      // 
-      this.activeAgentsLabel.AutoSize = true;
-      this.activeAgentsLabel.Location = new System.Drawing.Point(12, 61);
-      this.activeAgentsLabel.Name = "activeAgentsLabel";
-      this.activeAgentsLabel.Size = new System.Drawing.Size(75, 13);
-      this.activeAgentsLabel.TabIndex = 7;
-      this.activeAgentsLabel.Text = "A&ctive agents:";
-      // 
-      // activeAgentsTextBox
-      // 
-      this.activeAgentsTextBox.Location = new System.Drawing.Point(106, 58);
-      this.activeAgentsTextBox.Name = "activeAgentsTextBox";
-      this.activeAgentsTextBox.ReadOnly = true;
-      this.activeAgentsTextBox.Size = new System.Drawing.Size(90, 20);
-      this.activeAgentsTextBox.TabIndex = 6;
-      this.activeAgentsTextBox.Text = "0";
-      this.activeAgentsTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
-      // 
       // gridAddressLabel
       // 
@@ -103,16 +88,56 @@
       this.gridAddress.Location = new System.Drawing.Point(106, 32);
       this.gridAddress.Name = "gridAddress";
-      this.gridAddress.Size = new System.Drawing.Size(229, 20);
+      this.gridAddress.Size = new System.Drawing.Size(160, 20);
       this.gridAddress.TabIndex = 8;
       // 
-      // startButton
+      // connectButton
       // 
-      this.startButton.Location = new System.Drawing.Point(15, 84);
-      this.startButton.Name = "startButton";
-      this.startButton.Size = new System.Drawing.Size(75, 23);
-      this.startButton.TabIndex = 10;
-      this.startButton.Text = "Start";
-      this.startButton.UseVisualStyleBackColor = true;
-      this.startButton.Click += new System.EventHandler(this.startButton_Click);
+      this.connectButton.Location = new System.Drawing.Point(272, 30);
+      this.connectButton.Name = "connectButton";
+      this.connectButton.Size = new System.Drawing.Size(75, 23);
+      this.connectButton.TabIndex = 10;
+      this.connectButton.Text = "Connect";
+      this.connectButton.UseVisualStyleBackColor = true;
+      this.connectButton.Click += new System.EventHandler(this.connectButton_Click);
+      // 
+      // listBox
+      // 
+      this.listBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                  | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.listBox.FormattingEnabled = true;
+      this.listBox.Location = new System.Drawing.Point(12, 84);
+      this.listBox.Name = "listBox";
+      this.listBox.Size = new System.Drawing.Size(350, 251);
+      this.listBox.TabIndex = 11;
+      // 
+      // refreshTimer
+      // 
+      this.refreshTimer.Interval = 1000;
+      this.refreshTimer.Tick += new System.EventHandler(this.refreshTimer_Tick);
+      // 
+      // maxActiveJobsUpDown
+      // 
+      this.maxActiveJobsUpDown.Enabled = false;
+      this.maxActiveJobsUpDown.Location = new System.Drawing.Point(106, 59);
+      this.maxActiveJobsUpDown.Maximum = new decimal(new int[] {
+            64,
+            0,
+            0,
+            0});
+      this.maxActiveJobsUpDown.Name = "maxActiveJobsUpDown";
+      this.maxActiveJobsUpDown.Size = new System.Drawing.Size(120, 20);
+      this.maxActiveJobsUpDown.TabIndex = 12;
+      this.maxActiveJobsUpDown.ValueChanged += new System.EventHandler(this.maxActiveJobsUpDown_ValueChanged);
+      // 
+      // label1
+      // 
+      this.label1.AutoSize = true;
+      this.label1.Enabled = false;
+      this.label1.Location = new System.Drawing.Point(12, 61);
+      this.label1.Name = "label1";
+      this.label1.Size = new System.Drawing.Size(84, 13);
+      this.label1.TabIndex = 13;
+      this.label1.Text = "&Max active jobs:";
       // 
       // ServerForm
@@ -120,14 +145,16 @@
       this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-      this.ClientSize = new System.Drawing.Size(347, 119);
-      this.Controls.Add(this.startButton);
+      this.ClientSize = new System.Drawing.Size(374, 342);
+      this.Controls.Add(this.label1);
+      this.Controls.Add(this.maxActiveJobsUpDown);
+      this.Controls.Add(this.listBox);
+      this.Controls.Add(this.connectButton);
       this.Controls.Add(this.gridAddressLabel);
       this.Controls.Add(this.gridAddress);
-      this.Controls.Add(this.activeAgentsLabel);
-      this.Controls.Add(this.activeAgentsTextBox);
       this.Controls.Add(this.externalAddressLabel);
       this.Controls.Add(this.addressTextBox);
       this.Name = "ServerForm";
-      this.Text = "Agent Server";
+      this.Text = "CEDMA Server";
+      ((System.ComponentModel.ISupportInitialize)(this.maxActiveJobsUpDown)).EndInit();
       this.ResumeLayout(false);
       this.PerformLayout();
@@ -139,9 +166,11 @@
     private System.Windows.Forms.TextBox addressTextBox;
     private System.Windows.Forms.Label externalAddressLabel;
-    private System.Windows.Forms.Label activeAgentsLabel;
-    private System.Windows.Forms.TextBox activeAgentsTextBox;
     private System.Windows.Forms.Label gridAddressLabel;
     private System.Windows.Forms.TextBox gridAddress;
-    private System.Windows.Forms.Button startButton;
+    private System.Windows.Forms.Button connectButton;
+    private System.Windows.Forms.ListBox listBox;
+    private System.Windows.Forms.Timer refreshTimer;
+    private System.Windows.Forms.NumericUpDown maxActiveJobsUpDown;
+    private System.Windows.Forms.Label label1;
   }
 }
Index: trunk/sources/HeuristicLab.CEDMA.Server/ServerForm.resx
===================================================================
--- trunk/sources/HeuristicLab.CEDMA.Server/ServerForm.resx	(revision 852)
+++ trunk/sources/HeuristicLab.CEDMA.Server/ServerForm.resx	(revision 1287)
@@ -118,3 +118,6 @@
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
+  <metadata name="refreshTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
 </root>
