diff --git a/b_asic/operation.py b/b_asic/operation.py
index 629da3690e9684af1406c91da6895e14aecbf66f..c0985f9f6db1bd0c02ee143ad56070f1831310b1 100644
--- a/b_asic/operation.py
+++ b/b_asic/operation.py
@@ -248,13 +248,6 @@ class Operation(GraphComponent, SignalSourceProvider):
         """
         raise NotImplementedError
 
-    @abstractmethod
-    def set_execution_time(self, latency: int) -> None:
-        """Sets the execution time of the operation to the specified integer
-        value. The execution time cannot be a negative integer.
-        """
-        raise NotImplementedError
-
     @property
     @abstractmethod
     def execution_time(self) -> int:
@@ -263,6 +256,14 @@ class Operation(GraphComponent, SignalSourceProvider):
         """
         raise NotImplementedError
 
+    @execution_time.setter
+    @abstractmethod
+    def execution_time(self, latency: int) -> None:
+        """Sets the execution time of the operation to the specified integer
+        value. The execution time cannot be a negative integer.
+        """
+        raise NotImplementedError
+
     @abstractmethod
     def get_plot_coordinates(self) -> Tuple[List[List[Number]], List[List[Number]]]:
         """Get a tuple constaining coordinates for the two polygons outlining
@@ -556,6 +557,7 @@ class AbstractOperation(Operation, AbstractGraphComponent):
             new_component.input(i).latency_offset = inp.latency_offset
         for i, outp in enumerate(self.outputs):
             new_component.output(i).latency_offset = outp.latency_offset
+        new_component.execution_time = self._execution_time
         return new_component
 
     def inputs_required_for_output(self, output_index: int) -> Iterable[int]:
@@ -654,8 +656,9 @@ class AbstractOperation(Operation, AbstractGraphComponent):
             raise ValueError("No execution time specified.")
         return self._execution_time
 
-    def set_execution_time(self, execution_time: int) -> None:
-        assert execution_time >= 0, "Negative execution time entered."
+    @execution_time.setter
+    def execution_time(self, execution_time: int) -> None:
+        assert execution_time is None or execution_time >= 0 , "Negative execution time entered."
         self._execution_time = execution_time
 
     def get_plot_coordinates(self) -> Tuple[List[List[Number]], List[List[Number]]]:
diff --git a/b_asic/schema.py b/b_asic/schema.py
index a01825490f97942959e320724266d20b23fc75f3..3fd66f58f7afb8ab50675c60f6f3a2d9f6a602d0 100644
--- a/b_asic/schema.py
+++ b/b_asic/schema.py
@@ -3,10 +3,12 @@
 Contains the schema class for scheduling operations in an SFG.
 """
 
+from collections import defaultdict
 from typing import Dict, List, Optional
 import matplotlib.pyplot as plt
 import numpy as np
 from scipy import interpolate
+import sys
 
 from b_asic.signal_flow_graph import SFG
 from b_asic.graph_component import GraphID
@@ -28,7 +30,7 @@ class Schema:
         """Construct a Schema from an SFG."""
         self._sfg = sfg
         self._start_times = dict()
-        self._laps = dict()
+        self._laps = defaultdict(lambda: 0)
         self._cyclic = cyclic
         self._resolution = resolution
 
@@ -38,12 +40,7 @@ class Schema:
             raise NotImplementedError(
                 f"No algorithm with name: {scheduling_alg} defined.")
 
-        max_end_time = 0
-        for op_id, op_start_time in self._start_times.items():
-            op = self._sfg.find_by_id(op_id)
-            for outport in op.outputs:
-                max_end_time = max(
-                    max_end_time, op_start_time + outport.latency_offset)
+        max_end_time = self._get_max_end_time()
 
         if not self._cyclic:
             if schedule_time is None:
@@ -59,15 +56,68 @@ class Schema:
         assert op_id in self._start_times, "No operation with the specified op_id in this schema."
         return self._start_times[op_id]
 
+    def _get_max_end_time(self) -> int:
+        max_end_time = 0
+        for op_id, op_start_time in self._start_times.items():
+            op = self._sfg.find_by_id(op_id)
+            for outport in op.outputs:
+                max_end_time = max(
+                    max_end_time, op_start_time + outport.latency_offset)
+        return max_end_time
+
     def forward_slack(self, op_id: GraphID) -> int:
-        raise NotImplementedError
+        assert op_id in self._start_times, "No operation with the specified op_id in this schema."
+        start_time = self._start_times[op_id]
+        op = self._sfg.find_by_id(op_id)
+        slack = sys.maxsize
+        for output_port in op.outputs:
+            available_time = start_time + output_port.latency_offset
+
+            for signal in output_port.signals:
+                usage_time = (signal.destination.latency_offset +
+                             self._start_times[signal.destination.operation.graph_id] +
+                             self._schedule_time*self._laps[signal.graph_id])
+                slack = min(slack, usage_time - available_time)
+        return slack
 
     def backward_slack(self, op_id: GraphID) -> int:
-        raise NotImplementedError
+        assert op_id in self._start_times, "No operation with the specified op_id in this schema."
+        start_time = self._start_times[op_id]
+        op = self._sfg.find_by_id(op_id)
+        slack = sys.maxsize
+        for input_port in op.inputs:
+            usage_time = start_time + input_port.latency_offset
+
+            for signal in input_port.signals:
+                available_time = (signal.source.latency_offset +
+                             self._start_times[signal.source.operation.graph_id] -
+                             self._schedule_time*self._laps[signal.graph_id])
+                slack = min(slack, usage_time - available_time)
+        return slack
 
     def print_slacks(self) -> None:
         raise NotImplementedError
 
+    def set_schedule_time(self, time: int) -> None:
+        assert self._get_max_end_time() < time, "New schedule time to short."
+        self._schedule_time = time
+
+    @property
+    def schedule_time(self) -> int:
+        return self._schedule_time
+
+    def _remove_delays(self) -> None:
+        delay_list = self._sfg.find_by_type_name(Delay.type_name())
+        while delay_list:
+            delay_op = delay_list[0]
+            delay_input_id = delay_op.input(0).signals[0].graph_id
+            delay_output_ids = [sig.graph_id for sig in delay_op.output(0).signals]
+            self._sfg = self._sfg.remove_operation(delay_op.graph_id)
+            for output_id in delay_output_ids:
+                self._laps[output_id] += 1 + self._laps[delay_input_id]
+            del self._laps[delay_input_id]
+            delay_list = self._sfg.find_by_type_name(Delay.type_name())
+
     def _schedule_asap(self) -> None:
         pl = self._sfg.get_precedence_list()
 
@@ -90,7 +140,6 @@ class Schema:
                     # Schedule the operation if it doesn't have a start time yet.
                     op_start_time = 0
                     for inport in op.inputs:
-                        print(inport.operation.graph_id)
                         assert len(
                             inport.signals) == 1, "Error in scheduling, dangling input port detected."
                         assert inport.signals[0].source is not None, "Error in scheduling, signal with no source detected."
@@ -114,6 +163,8 @@ class Schema:
                             op_start_time, op_start_time_from_in)
 
                     self._start_times[op.graph_id] = op_start_time
+        self._remove_delays()
+        print(self._laps)
 
     def plot_schedule(self) -> None:
         def _draw_arrow2(start, end):
@@ -137,10 +188,13 @@ class Schema:
             out = interpolate.splev(u3, tck)
             plt.plot(out[0], out[1], color='black')
 
-        def _draw_arrow(start, end):
+        def _draw_arrow(start, end, name="", laps=0):
             if end[0] < start[0]: # Wrap around
-                plt.plot([start[0], self._schedule_time], [start[1], start[1]], color='black')
-                plt.plot([0, end[0]], [end[1], end[1]], color='black')
+                plt.plot([start[0], self._schedule_time + 0.2], [start[1], start[1]], color='black')
+                plt.plot([-0.2, end[0]], [end[1], end[1]], color='black')
+                plt.text(self._schedule_time + 0.2, start[1], name, verticalalignment='center')
+                plt.text(-0.2, end[1], "{}: {}".format(name, laps), verticalalignment='center', horizontalalignment='right')
+
             elif end[0] == start[0]:
                 _draw_spline([start[0], start[0] + 0.2, start[0] + 0.2, start[0] - 0.2, start[0] - 0.2, start[0]],
                              [start[1], start[1], (start[1] + end[1])/2, (start[1] + end[1])/2, end[1], end[1]])
@@ -148,15 +202,15 @@ class Schema:
                 _draw_spline([start[0], (start[0] + end[0])/2, (start[0] + end[0])/2, end[0]],
                              [start[1], start[1], end[1], end[1]])
 
-        def _draw_offset_arrow(start, end, start_offset, end_offset):
+        def _draw_offset_arrow(start, end, start_offset, end_offset, name="", laps=0):
             _draw_arrow([start[0] + start_offset[0], start[1] + start_offset[1]],
-                        [end[0] + end_offset[0], end[1] + end_offset[1]])
+                        [end[0] + end_offset[0], end[1] + end_offset[1]], name=name, laps=laps)
 
         ypos = 0.5
         ytickpositions = []
         yticklabels = []
         plt.figure()
-        plt.grid()
+        plt.grid(zorder=0.5)
         ypositions = dict()
         for op_id, op_start_time in self._start_times.items():
             op = self._sfg.find_by_id(op_id)
@@ -169,7 +223,7 @@ class Schema:
             x = np.array(_x)
             y = np.array(_y)
             plt.plot(x + op_start_time, y + ypos, color='black', linewidth=3, alpha=0.5)
-            ytickpositions.append(ypos + 0.75)
+            ytickpositions.append(ypos + 0.5)
             yticklabels.append(self._sfg.find_by_id(op_id).name)
             ypositions[op_id] = ypos
             ypos += 1.5
@@ -181,15 +235,18 @@ class Schema:
             for output_port in op.outputs:
                 for output_signal in output_port.signals:
                     dest_op = output_signal.destination.operation
-                    if dest_op.type_name() != Delay.type_name() and dest_op.type_name() != Output.type_name():
+                    if dest_op.type_name() and dest_op.type_name() != Output.type_name():
                         dest_start_time = self._start_times[dest_op.graph_id]
                         dest_ypos = ypositions[dest_op.graph_id]
                         dest_in_coords, _ = output_signal.destination.operation.get_io_coordinates()
                         _draw_offset_arrow(out_coords[output_port.index],
                                            dest_in_coords[output_signal.destination.index],
                                            [op_start_time, source_ypos],
-                                           [dest_start_time, dest_ypos])
+                                           [dest_start_time, dest_ypos], name=op_id,
+                                           laps=self._laps[output_signal.graph_id])
 
         plt.yticks(ytickpositions, yticklabels)
-        plt.axis([0, self._schedule_time, 0, ypos])
+        plt.axis([-1, self._schedule_time+1, 0, ypos])
+        plt.plot([0, 0], [0, ypos], linestyle='--', color='black')
+        plt.plot([self._schedule_time, self._schedule_time], [0, ypos], linestyle='--', color='black')
         plt.show()
diff --git a/b_asic/signal_flow_graph.py b/b_asic/signal_flow_graph.py
index 4436ca6f43abc539b1492427f2120cff22968bad..3b1d530b866a35a198ea374400e8ac8c7f1257cb 100644
--- a/b_asic/signal_flow_graph.py
+++ b/b_asic/signal_flow_graph.py
@@ -10,6 +10,7 @@ from io import StringIO
 from queue import PriorityQueue
 import itertools as it
 from graphviz import Digraph
+import re
 
 from b_asic.port import SignalSourceProvider, OutputPort
 from b_asic.operation import Operation, AbstractOperation, ResultKey, DelayMap, MutableResultMap, MutableDelayMap
@@ -345,14 +346,9 @@ class SFG(AbstractOperation):
         Keyword arguments:
         type_name: The type_name of the desired components.
         """
-        i = self.id_number_offset + 1
-        components = []
-        found_comp = self.find_by_id(type_name + str(i))
-        while found_comp is not None:
-            components.append(found_comp)
-            i += 1
-            found_comp = self.find_by_id(type_name + str(i))
-
+        reg = "{}[0-9]+".format(type_name)
+        p = re.compile(reg)
+        components = [val for key, val in self._components_by_id.items() if p.match(key)]
         return components
 
     def find_by_id(self, graph_id: GraphID) -> Optional[GraphComponent]:
@@ -652,7 +648,7 @@ class SFG(AbstractOperation):
     def set_execution_time_of_type(self, type_name: TypeName, execution_time: int) -> None:
         """Set the execution time of all components with the given type name."""
         for op in self.find_by_type_name(type_name):
-            op.set_execution_time(execution_time)
+            op.execution_time = execution_time
 
     def set_latency_offsets_of_type(self, type_name: TypeName, latency_offsets: Dict[str, int]) -> None:
         """Set the latency offset of all components with the given type name."""
@@ -692,9 +688,10 @@ class SFG(AbstractOperation):
         assert original_component not in self._original_components_to_new, "Tried to add duplicate SFG component"
         new_component = original_component.copy_component()
         self._original_components_to_new[original_component] = new_component
-        new_id = self._graph_id_generator.next_id(new_component.type_name())
-        new_component.graph_id = new_id
-        self._components_by_id[new_id] = new_component
+        if not new_component.graph_id or new_component.graph_id in self._components_by_id:
+            new_id = self._graph_id_generator.next_id(new_component.type_name())
+            new_component.graph_id = new_id
+        self._components_by_id[new_component.graph_id] = new_component
         self._components_by_name[new_component.name].append(new_component)
         return new_component