Index: /stable/HeuristicLab.Encodings.ScheduleEncoding.Views/3.3/JobView.Designer.cs
===================================================================
--- /stable/HeuristicLab.Encodings.ScheduleEncoding.Views/3.3/JobView.Designer.cs	(revision 11072)
+++ /stable/HeuristicLab.Encodings.ScheduleEncoding.Views/3.3/JobView.Designer.cs	(revision 11073)
@@ -80,5 +80,5 @@
       this.dueDateLabel.Name = "dueDateLabel";
       this.dueDateLabel.Size = new System.Drawing.Size(56, 13);
-      this.dueDateLabel.TabIndex = 0;
+      this.dueDateLabel.TabIndex = 2;
       this.dueDateLabel.Text = "Due Date:";
       // 
@@ -90,5 +90,5 @@
       this.dueDateTextBox.Name = "dueDateTextBox";
       this.dueDateTextBox.Size = new System.Drawing.Size(451, 20);
-      this.dueDateTextBox.TabIndex = 1;
+      this.dueDateTextBox.TabIndex = 3;
       this.dueDateTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.dueDateTextBox_Validating);
       // 
@@ -101,5 +101,5 @@
       this.tasksGroupBox.Name = "tasksGroupBox";
       this.tasksGroupBox.Size = new System.Drawing.Size(510, 214);
-      this.tasksGroupBox.TabIndex = 2;
+      this.tasksGroupBox.TabIndex = 4;
       this.tasksGroupBox.TabStop = false;
       this.tasksGroupBox.Text = "Tasks";
Index: /stable/HeuristicLab.Encodings.ScheduleEncoding.Views/3.3/TaskView.Designer.cs
===================================================================
--- /stable/HeuristicLab.Encodings.ScheduleEncoding.Views/3.3/TaskView.Designer.cs	(revision 11072)
+++ /stable/HeuristicLab.Encodings.ScheduleEncoding.Views/3.3/TaskView.Designer.cs	(revision 11073)
@@ -83,5 +83,5 @@
       this.resourceNrLabel.Name = "resourceNrLabel";
       this.resourceNrLabel.Size = new System.Drawing.Size(70, 13);
-      this.resourceNrLabel.TabIndex = 0;
+      this.resourceNrLabel.TabIndex = 2;
       this.resourceNrLabel.Text = "Resource Nr:";
       // 
@@ -93,5 +93,5 @@
       this.resourceNrTextBox.Name = "resourceNrTextBox";
       this.resourceNrTextBox.Size = new System.Drawing.Size(437, 20);
-      this.resourceNrTextBox.TabIndex = 1;
+      this.resourceNrTextBox.TabIndex = 3;
       this.resourceNrTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.resourceNrTextBox_Validating);
       // 
@@ -106,5 +106,5 @@
       this.jobNrLabel.Name = "jobNrLabel";
       this.jobNrLabel.Size = new System.Drawing.Size(41, 13);
-      this.jobNrLabel.TabIndex = 0;
+      this.jobNrLabel.TabIndex = 4;
       this.jobNrLabel.Text = "Job Nr:";
       // 
@@ -116,5 +116,5 @@
       this.jobNrTextBox.Name = "jobNrTextBox";
       this.jobNrTextBox.Size = new System.Drawing.Size(437, 20);
-      this.jobNrTextBox.TabIndex = 1;
+      this.jobNrTextBox.TabIndex = 5;
       this.jobNrTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.jobNrTextBox_Validating);
       // 
@@ -125,5 +125,5 @@
       this.durationLabel.Name = "durationLabel";
       this.durationLabel.Size = new System.Drawing.Size(50, 13);
-      this.durationLabel.TabIndex = 0;
+      this.durationLabel.TabIndex = 6;
       this.durationLabel.Text = "Duration:";
       // 
@@ -135,5 +135,5 @@
       this.durationTextBox.Name = "durationTextBox";
       this.durationTextBox.Size = new System.Drawing.Size(437, 20);
-      this.durationTextBox.TabIndex = 1;
+      this.durationTextBox.TabIndex = 7;
       this.durationTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.durationTextBox_Validating);
       // 
Index: /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/JobSequenceMatrix/JSMEncoding.cs
===================================================================
--- /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/JobSequenceMatrix/JSMEncoding.cs	(revision 11072)
+++ /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/JobSequenceMatrix/JSMEncoding.cs	(revision 11073)
@@ -20,4 +20,5 @@
 #endregion
 
+using System;
 using System.Text;
 using HeuristicLab.Common;
@@ -53,5 +54,5 @@
 
       foreach (Permutation p in JobSequenceMatrix) {
-        sb.Append(p.ToString() + " \n");
+        sb.AppendLine(p.ToString());
       }
 
@@ -59,38 +60,4 @@
       return sb.ToString();
     }
-
-
-    public override bool Equals(object obj) {
-      if (obj.GetType() == typeof(JSMEncoding))
-        return AreEqual(this, obj as JSMEncoding);
-
-      return false;
-    }
-    public override int GetHashCode() {
-      if (JobSequenceMatrix.Count == 1)
-        return JobSequenceMatrix[0].GetHashCode();
-      if (JobSequenceMatrix.Count == 2)
-        return JobSequenceMatrix[0].GetHashCode() ^ JobSequenceMatrix[1].GetHashCode();
-      return 0;
-    }
-    private static bool AreEqual(JSMEncoding jSMEncoding1, JSMEncoding jSMEncoding2) {
-      if (jSMEncoding1.JobSequenceMatrix.Count != jSMEncoding2.JobSequenceMatrix.Count)
-        return false;
-      for (int i = 0; i < jSMEncoding1.JobSequenceMatrix.Count; i++) {
-        if (!AreEqual(jSMEncoding1.JobSequenceMatrix[i], jSMEncoding2.JobSequenceMatrix[i]))
-          return false;
-      }
-      return true;
-    }
-
-    private static bool AreEqual(Permutation p1, Permutation p2) {
-      if (p1.Length != p2.Length)
-        return false;
-      for (int i = 0; i < p1.Length; i++) {
-        if (p1[i] != p2[i])
-          return false;
-      }
-      return true;
-    }
   }
 }
Index: /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/PermutationWithRepetition/PWREncoding.cs
===================================================================
--- /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/PermutationWithRepetition/PWREncoding.cs	(revision 11072)
+++ /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/PermutationWithRepetition/PWREncoding.cs	(revision 11073)
@@ -75,29 +75,4 @@
       return sb.ToString();
     }
-
-    public override bool Equals(object obj) {
-      if (obj.GetType() == typeof(PWREncoding))
-        return AreEqual(this, obj as PWREncoding);
-      else
-        return base.Equals(obj);
-    }
-
-    public override int GetHashCode() {
-      if (PermutationWithRepetition.Length == 1)
-        return PermutationWithRepetition[0].GetHashCode();
-      if (PermutationWithRepetition.Length == 2)
-        return PermutationWithRepetition[0].GetHashCode() ^ PermutationWithRepetition[1].GetHashCode();
-      return 0;
-    }
-
-    private bool AreEqual(PWREncoding pWREncoding1, PWREncoding pWREncoding2) {
-      if (pWREncoding1.PermutationWithRepetition.Length != pWREncoding2.PermutationWithRepetition.Length)
-        return false;
-      for (int i = 0; i < pWREncoding1.PermutationWithRepetition.Length; i++) {
-        if (pWREncoding1.PermutationWithRepetition[i] != pWREncoding2.PermutationWithRepetition[i])
-          return false;
-      }
-      return true;
-    }
   }
 }
Index: /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/PriorityRulesVector/PRVEncoding.cs
===================================================================
--- /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/PriorityRulesVector/PRVEncoding.cs	(revision 11072)
+++ /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/PriorityRulesVector/PRVEncoding.cs	(revision 11073)
@@ -74,5 +74,5 @@
 
       foreach (int i in PriorityRulesVector) {
-        sb.Append(i.ToString() + " ");
+        sb.Append(i + " ");
       }
 
Index: /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/ScheduleEncoding/Job.cs
===================================================================
--- /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/ScheduleEncoding/Job.cs	(revision 11072)
+++ /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/ScheduleEncoding/Job.cs	(revision 11073)
@@ -20,6 +20,8 @@
 #endregion
 
+using System;
 using System.ComponentModel;
 using System.Text;
+using HeuristicLab.Collections;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -38,5 +40,8 @@
         bool changed = dueDate != value;
         dueDate = value;
-        if (changed) OnPropertyChanged("DueDate");
+        if (changed) {
+          OnPropertyChanged("DueDate");
+          OnToStringChanged();
+        }
       }
     }
@@ -49,5 +54,8 @@
         bool changed = index != value;
         index = value;
-        if (changed) OnPropertyChanged("Index");
+        if (changed) {
+          OnPropertyChanged("Index");
+          OnToStringChanged();
+        }
       }
     }
@@ -68,14 +76,16 @@
     protected Job(Job original, Cloner cloner)
       : base(original, cloner) {
-      this.DueDate = original.DueDate;
-      this.Index = original.Index;
-      this.Tasks = cloner.Clone(original.Tasks);
+      this.dueDate = original.DueDate;
+      this.index = original.Index;
+      this.tasks = cloner.Clone(original.Tasks);
+      RegisterEventHandlers();
     }
     public Job() : this(-1, double.MaxValue) { }
     public Job(int index, double dueDate)
       : base() {
-      DueDate = dueDate;
-      Index = index;
-      Tasks = new ItemList<Task>();
+      this.dueDate = dueDate;
+      this.index = index;
+      this.tasks = new ItemList<Task>();
+      RegisterEventHandlers();
     }
 
@@ -84,9 +94,46 @@
     }
 
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEventHandlers();
+    }
+
+    private void RegisterEventHandlers() {
+      Tasks.ItemsAdded += TasksOnItemsChanged;
+      Tasks.ItemsRemoved += TasksOnItemsChanged;
+      Tasks.ItemsReplaced += TasksOnItemsChanged;
+      Tasks.CollectionReset += TasksOnItemsChanged;
+      foreach (var task in Tasks) {
+        task.PropertyChanged += TaskOnPropertyChanged;
+        task.ToStringChanged += TaskOnToStringChanged;
+      }
+    }
+
+    private void TasksOnItemsChanged(object sender, CollectionItemsChangedEventArgs<IndexedItem<Task>> e) {
+      foreach (var task in e.OldItems) {
+        task.Value.PropertyChanged -= TaskOnPropertyChanged;
+        task.Value.ToStringChanged -= TaskOnToStringChanged;
+      }
+      foreach (var task in e.Items) {
+        task.Value.PropertyChanged += TaskOnPropertyChanged;
+        task.Value.ToStringChanged += TaskOnToStringChanged;
+      }
+      OnTasksChanged();
+      OnToStringChanged();
+    }
+
+    private void TaskOnPropertyChanged(object sender, EventArgs e) {
+      OnTasksChanged();
+    }
+
+    private void TaskOnToStringChanged(object sender, EventArgs e) {
+      OnToStringChanged();
+    }
+
     public override string ToString() {
       var sb = new StringBuilder();
       sb.Append("Job#" + Index + " [ ");
       foreach (Task t in Tasks) {
-        sb.Append(t.ToString() + " ");
+        sb.Append(t + " ");
       }
       sb.Append("{" + DueDate + "} ");
@@ -100,4 +147,10 @@
     }
 
+    public event EventHandler TasksChanged;
+    protected virtual void OnTasksChanged() {
+      var handler = TasksChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
     public event PropertyChangedEventHandler PropertyChanged;
     protected virtual void OnPropertyChanged(string propertyName) {
Index: /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/ScheduleEncoding/Resource.cs
===================================================================
--- /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/ScheduleEncoding/Resource.cs	(revision 11072)
+++ /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/ScheduleEncoding/Resource.cs	(revision 11073)
@@ -73,36 +73,9 @@
       sb.Append("Resource#" + Index + " [ ");
       foreach (ScheduledTask t in Tasks) {
-        sb.Append(t.ToString() + " ");
+        sb.Append(t+ " ");
       }
       sb.Append("]");
       return sb.ToString();
     }
-
-
-    public override bool Equals(object obj) {
-      if (obj.GetType() == typeof(Resource))
-        return AreEqual(this, obj as Resource);
-      else
-        return false;
-    }
-
-    public override int GetHashCode() {
-      if (Tasks.Count == 1)
-        return Tasks[0].GetHashCode();
-      if (Tasks.Count == 2)
-        return Tasks[0].GetHashCode() ^ Tasks[1].GetHashCode();
-      return 0;
-    }
-
-    private static bool AreEqual(Resource res1, Resource res2) {
-      if (res1.Tasks.Count != res2.Tasks.Count)
-        return false;
-      for (int i = 0; i < res1.Tasks.Count; i++) {
-        if (!res1.Tasks[i].Equals(res2.Tasks[i]))
-          return false;
-      }
-
-      return true;
-    }
   }
 }
Index: /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/ScheduleEncoding/Schedule.cs
===================================================================
--- /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/ScheduleEncoding/Schedule.cs	(revision 11072)
+++ /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/ScheduleEncoding/Schedule.cs	(revision 11073)
@@ -149,5 +149,5 @@
       sb.Append("[ ");
       foreach (Resource r in Resources) {
-        sb.Append(r.ToString() + " \n");
+        sb.AppendLine(r.ToString());
       }
       sb.Append("]");
@@ -164,30 +164,4 @@
       return quality;
     }
-
-    public override bool Equals(object obj) {
-      if (obj.GetType() == typeof(Schedule))
-        return AreEqual(this, obj as Schedule);
-      else
-        return false;
-    }
-    public override int GetHashCode() {
-      if (Resources.Count == 1)
-        return Resources[0].GetHashCode();
-      if (Resources.Count == 2)
-        return Resources[0].GetHashCode() ^ Resources[1].GetHashCode();
-      return 0;
-    }
-
-    private static bool AreEqual(Schedule schedule1, Schedule schedule2) {
-      if (schedule1.Resources.Count != schedule2.Resources.Count)
-        return false;
-      for (int i = 0; i < schedule1.Resources.Count; i++) {
-        if (!schedule1.Resources[i].Equals(schedule2.Resources[i]))
-          return false;
-      }
-
-      return true;
-    }
-
   }
 }
Index: /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/ScheduleEncoding/ScheduledTask.cs
===================================================================
--- /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/ScheduleEncoding/ScheduledTask.cs	(revision 11072)
+++ /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/ScheduleEncoding/ScheduledTask.cs	(revision 11073)
@@ -75,25 +75,4 @@
       return sb.ToString();
     }
-
-    public override bool Equals(object obj) {
-      if (obj.GetType() == typeof(ScheduledTask))
-        return AreEqual(this, obj as ScheduledTask);
-      else
-        return false;
-    }
-
-    public override int GetHashCode() {
-      return TaskNr ^ JobNr;
-    }
-
-    public static bool AreEqual(ScheduledTask task1, ScheduledTask task2) {
-      return (
-        task1.TaskNr == task2.TaskNr &&
-        task1.Duration == task2.Duration &&
-        task1.JobNr == task2.JobNr &&
-        task1.ResourceNr == task2.ResourceNr &&
-        task1.StartTime == task2.StartTime &&
-        task1.EndTime == task2.EndTime);
-    }
   }
 }
Index: /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/ScheduleEncoding/Task.cs
===================================================================
--- /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/ScheduleEncoding/Task.cs	(revision 11072)
+++ /stable/HeuristicLab.Encodings.ScheduleEncoding/3.3/ScheduleEncoding/Task.cs	(revision 11073)
@@ -38,5 +38,8 @@
         bool changed = taskNr != value;
         taskNr = value;
-        if (changed) OnPropertyChanged("TaskNr");
+        if (changed) {
+          OnPropertyChanged("TaskNr");
+          OnToStringChanged();
+        }
       }
     }
@@ -48,5 +51,8 @@
         bool changed = resourceNr != value;
         resourceNr = value;
-        if (changed) OnPropertyChanged("ResourceNr");
+        if (changed) {
+          OnPropertyChanged("ResourceNr");
+          OnToStringChanged();
+        }
       }
     }
@@ -89,18 +95,18 @@
     protected Task(Task original, Cloner cloner)
       : base(original, cloner) {
-      this.ResourceNr = original.ResourceNr;
-      this.JobNr = original.JobNr;
-      this.Duration = original.Duration;
-      this.TaskNr = original.TaskNr;
-      this.IsScheduled = original.IsScheduled;
+      this.resourceNr = original.ResourceNr;
+      this.jobNr = original.JobNr;
+      this.duration = original.Duration;
+      this.taskNr = original.TaskNr;
+      this.isScheduled = original.IsScheduled;
     }
     public Task() : this(-1, -1, -1, 0) { }
     public Task(int taskNr, int resNr, int jobNr, double duration)
       : base() {
-      Duration = duration;
-      ResourceNr = resNr;
-      JobNr = jobNr;
-      TaskNr = taskNr;
-      IsScheduled = false;
+      this.duration = duration;
+      this.resourceNr = resNr;
+      this.jobNr = jobNr;
+      this.taskNr = taskNr;
+      this.isScheduled = false;
     }
 
@@ -115,23 +121,4 @@
     }
 
-    public override bool Equals(object obj) {
-      if (obj.GetType() == typeof(Task))
-        return AreEqual(this, obj as Task);
-      else
-        return false;
-    }
-
-    public override int GetHashCode() {
-      return TaskNr ^ JobNr;
-    }
-
-    public static bool AreEqual(Task task1, Task task2) {
-      return (task1.Duration == task2.Duration &&
-        task1.IsScheduled == task2.IsScheduled &&
-        task1.JobNr == task2.JobNr &&
-        task1.ResourceNr == task2.ResourceNr &&
-        task1.TaskNr == task2.TaskNr);
-    }
-
     public event PropertyChangedEventHandler PropertyChanged;
     protected virtual void OnPropertyChanged(string propertyName) {
Index: /stable/HeuristicLab.Problems.Scheduling.Views/3.3/JobShopSchedulingProblemView.cs
===================================================================
--- /stable/HeuristicLab.Problems.Scheduling.Views/3.3/JobShopSchedulingProblemView.cs	(revision 11072)
+++ /stable/HeuristicLab.Problems.Scheduling.Views/3.3/JobShopSchedulingProblemView.cs	(revision 11073)
@@ -20,5 +20,8 @@
 #endregion
 
+using System;
 using System.Windows.Forms;
+using HeuristicLab.Collections;
+using HeuristicLab.Encodings.ScheduleEncoding;
 using HeuristicLab.MainForm;
 using HeuristicLab.Optimization.Views;
@@ -43,17 +46,60 @@
     protected override void OnContentChanged() {
       base.OnContentChanged();
-      if (Content == null) {
-        ganttChart.Reset();
-      } else {
-        FillGanttChart(Content);
+      FillGanttChart();
+    }
+
+    protected override void DeregisterContentEvents() {
+      Content.JobDataParameter.ValueChanged -= JobDataParameterOnValueChanged;
+      Content.JobData.ItemsAdded -= JobsOnChanged;
+      Content.JobData.ItemsRemoved -= JobsOnChanged;
+      Content.JobData.ItemsReplaced -= JobsOnChanged;
+      Content.JobData.CollectionReset -= JobsOnChanged;
+      foreach (var job in Content.JobData) {
+        job.TasksChanged -= JobOnTasksChanged;
+      }
+      base.DeregisterContentEvents();
+    }
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.JobDataParameter.ValueChanged += JobDataParameterOnValueChanged;
+      Content.JobData.ItemsAdded += JobsOnChanged;
+      Content.JobData.ItemsRemoved += JobsOnChanged;
+      Content.JobData.ItemsReplaced += JobsOnChanged;
+      Content.JobData.CollectionReset += JobsOnChanged;
+      foreach (var job in Content.JobData) {
+        job.TasksChanged += JobOnTasksChanged;
       }
     }
 
-    private void FillGanttChart(JobShopSchedulingProblem content) {
+    private void JobsOnChanged(object sender, CollectionItemsChangedEventArgs<IndexedItem<Job>> e) {
+      foreach (var job in e.OldItems)
+        job.Value.TasksChanged -= JobOnTasksChanged;
+      foreach (var job in e.Items)
+        job.Value.TasksChanged += JobOnTasksChanged;
+      FillGanttChart();
+    }
+
+    private void JobDataParameterOnValueChanged(object sender, EventArgs e) {
+      Content.JobData.ItemsAdded += JobsOnChanged;
+      Content.JobData.ItemsRemoved += JobsOnChanged;
+      Content.JobData.ItemsReplaced += JobsOnChanged;
+      Content.JobData.CollectionReset += JobsOnChanged;
+      foreach (var job in Content.JobData) {
+        job.TasksChanged += JobOnTasksChanged;
+      }
+      FillGanttChart();
+    }
+
+    private void JobOnTasksChanged(object sender, EventArgs e) {
+      FillGanttChart();
+    }
+
+    private void FillGanttChart() {
       ganttChart.Reset();
+      if (Content == null) return;
       int jobCount = 0;
-      foreach (var j in content.JobData) {
+      foreach (var j in Content.JobData) {
         double lastEndTime = 0;
-        foreach (var t in content.JobData[jobCount].Tasks) {
+        foreach (var t in Content.JobData[jobCount].Tasks) {
           int categoryNr = t.JobNr;
           string categoryName = "Job" + categoryNr;
@@ -63,5 +109,5 @@
             lastEndTime + 1,
             lastEndTime + t.Duration,
-            "Job" + t.JobNr + " - " + "Task#" + t.TaskNr.ToString());
+            "Job" + t.JobNr + " - " + "Task#" + t.TaskNr);
           lastEndTime += t.Duration;
         }
Index: /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/DirectScheduleGTCrossoverTest.cs
===================================================================
--- /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/DirectScheduleGTCrossoverTest.cs	(revision 11072)
+++ /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/DirectScheduleGTCrossoverTest.cs	(revision 11073)
@@ -20,4 +20,5 @@
 #endregion
 
+using System.Linq;
 using HeuristicLab.Core;
 using HeuristicLab.Encodings.ScheduleEncoding.PermutationWithRepetition;
@@ -48,6 +49,7 @@
       actual = DirectScheduleGTCrossover.Apply(random, parent1, parent2, jobData, mutProp);
       Schedule expected = DirectScheduleRandomCreator.Apply(3, 3, new PWREncoding(3, 3, new TestRandom(new int[] { 0, 2, 1, 1, 0, 2, 1, 2, 0 }, null)), TestUtils.CreateJobData());
-      Assert.IsTrue(actual.Equals(expected));
+      Assert.IsTrue(TestUtils.ScheduleEquals(actual, expected));
     }
+
   }
 }
Index: /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/JSMJOXCrossoverTest.cs
===================================================================
--- /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/JSMJOXCrossoverTest.cs	(revision 11072)
+++ /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/JSMJOXCrossoverTest.cs	(revision 11073)
@@ -53,5 +53,5 @@
       actual = JSMJOXCrossover.Apply(random, p1, p2);
 
-      Assert.IsTrue(expected.Equals(actual));
+      Assert.IsTrue(TestUtils.JSMEncodingEquals(expected, actual));
     }
   }
Index: /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/JSMSXXCrossoverTest.cs
===================================================================
--- /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/JSMSXXCrossoverTest.cs	(revision 11072)
+++ /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/JSMSXXCrossoverTest.cs	(revision 11073)
@@ -53,5 +53,5 @@
       actual = JSMSXXCrossover.Apply(random, p1, p2);
 
-      Assert.IsTrue(expected.Equals(actual));
+      Assert.IsTrue(TestUtils.JSMEncodingEquals(expected, actual));
     }
   }
Index: /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/JSMShiftChangeManipulatorTest.cs
===================================================================
--- /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/JSMShiftChangeManipulatorTest.cs	(revision 11072)
+++ /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/JSMShiftChangeManipulatorTest.cs	(revision 11073)
@@ -51,5 +51,5 @@
       expected.JobSequenceMatrix = jsm;
 
-      Assert.IsTrue(individual.Equals(expected));
+      Assert.IsTrue(TestUtils.JSMEncodingEquals(expected, individual));
     }
   }
Index: /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/PWRGOXCrossoverTest.cs
===================================================================
--- /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/PWRGOXCrossoverTest.cs	(revision 11072)
+++ /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/PWRGOXCrossoverTest.cs	(revision 11073)
@@ -47,5 +47,5 @@
       PWREncoding actual;
       actual = PWRGOXCrossover.Apply(random, parent1, parent2);
-      Assert.IsTrue(actual.Equals(expected));
+      Assert.IsTrue(TestUtils.PRWEncodingEquals(expected, actual));
     }
   }
Index: /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/PWRPPXCrossoverTest.cs
===================================================================
--- /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/PWRPPXCrossoverTest.cs	(revision 11072)
+++ /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/PWRPPXCrossoverTest.cs	(revision 11073)
@@ -47,5 +47,5 @@
       PWREncoding actual;
       actual = PWRPPXCrossover.Apply(random, parent1, parent2);
-      Assert.IsTrue(actual.Equals(expected));
+      Assert.IsTrue(TestUtils.PRWEncodingEquals(expected, actual));
     }
   }
Index: /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/TestUtils.cs
===================================================================
--- /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/TestUtils.cs	(revision 11072)
+++ /stable/HeuristicLab.Tests/HeuristicLab.Encodings.ScheduleEncoding-3.3/TestUtils.cs	(revision 11073)
@@ -20,4 +20,5 @@
 #endregion
 
+using System.Linq;
 using HeuristicLab.Core;
 using HeuristicLab.Encodings.IntegerVectorEncoding;
@@ -97,4 +98,54 @@
       return result;
     }
+    public static bool ScheduleEquals(Schedule actual, Schedule expected) {
+      return actual.Resources.Count == expected.Resources.Count &&
+             actual.Resources.Zip(expected.Resources, (a, e) => ResourceEquals(a, e)).All(_ => _);
+    }
+
+    public static bool ResourceEquals(Resource actual, Resource expected) {
+      return actual.Index == expected.Index &&
+             actual.TotalDuration == expected.TotalDuration &&
+             actual.Tasks.Count == expected.Tasks.Count &&
+             actual.Tasks.Zip(expected.Tasks, (a, e) => TaskEquals(a, e)).All(_ => _);
+    }
+
+    public static bool TaskEquals(ScheduledTask actual, ScheduledTask expected) {
+      return
+        actual.StartTime == expected.StartTime &&
+        actual.EndTime == expected.EndTime &&
+        actual.Duration == expected.Duration &&
+        actual.ResourceNr == expected.ResourceNr &&
+        actual.JobNr == expected.JobNr &&
+        actual.TaskNr == expected.TaskNr;
+    }
+
+    public static bool JSMEncodingEquals(JSMEncoding expected, JSMEncoding actual) {
+      if (expected.JobSequenceMatrix.Count != actual.JobSequenceMatrix.Count)
+        return false;
+      for (int i = 0; i < expected.JobSequenceMatrix.Count; i++) {
+        if (!PermutationEquals(expected.JobSequenceMatrix[i], actual.JobSequenceMatrix[i]))
+          return false;
+      }
+      return true;
+    }
+    private static bool PermutationEquals(Permutation p1, Permutation p2) {
+      if (p1.Length != p2.Length)
+        return false;
+      for (int i = 0; i < p1.Length; i++) {
+        if (p1[i] != p2[i])
+          return false;
+      }
+      return true;
+    }
+
+    public static bool PRWEncodingEquals(PWREncoding expected, PWREncoding actual) {
+      if (expected.PermutationWithRepetition.Length != actual.PermutationWithRepetition.Length)
+        return false;
+      for (int i = 0; i < expected.PermutationWithRepetition.Length; i++) {
+        if (expected.PermutationWithRepetition[i] != actual.PermutationWithRepetition[i])
+          return false;
+      }
+      return true;
+    }
   }
 }
