diff --git a/b_asic/schedule.py b/b_asic/schedule.py
index 4b34d5802d13a8662c3bf2a20640bfaaea48d35f..3f8a0592680e1ec9230a84af3ada73fbe4ba966b 100644
--- a/b_asic/schedule.py
+++ b/b_asic/schedule.py
@@ -36,6 +36,7 @@ from b_asic.resources import ProcessCollection
 from b_asic.signal_flow_graph import SFG
 from b_asic.special_operations import Delay, Input, Output
 from b_asic.types import TypeName
+from b_asic.scheduling_algorithm import SchedAlg
 
 # Need RGB from 0 to 1
 _EXECUTION_TIME_COLOR: Tuple[float, ...] = tuple(
@@ -68,13 +69,8 @@ class Schedule:
         algorithm.
     cyclic : bool, default: False
         If the schedule is cyclic.
-    algorithm : {'ASAP', 'ALAP', 'provided'}, default: 'ASAP'
-        The scheduling algorithm to use. The following algorithm are available:
-
-        * ``'ASAP'``: As-soon-as-possible scheduling.
-        * ``'ALAP'``: As-late-as-possible scheduling.
-
-        If 'provided', use provided *start_times*  and *laps* dictionaries.
+    algorithm : SchedulingAlgorithm, default: 'ASAP'
+        The scheduling algorithm to use.
     start_times : dict, optional
         Dictionary with GraphIDs as keys and start times as values.
         Used when *algorithm* is 'provided'.
@@ -100,7 +96,7 @@ class Schedule:
         sfg: SFG,
         schedule_time: Optional[int] = None,
         cyclic: bool = False,
-        algorithm: Literal["ASAP", "ALAP", "provided"] = "ASAP",
+        algorithm: SchedAlg = "ASAP",
         start_times: Optional[Dict[GraphID, int]] = None,
         laps: Optional[Dict[GraphID, int]] = None,
         max_resources: Optional[Dict[TypeName, int]] = None,
@@ -115,10 +111,14 @@ class Schedule:
         self._cyclic = cyclic
         self._y_locations = defaultdict(_y_locations_default)
         self._schedule_time = schedule_time
+
+        self.scheduler = Scheduler(self)
         if algorithm == "ASAP":
-            self._schedule_asap()
+            self.scheduler.schedule_asap()
         elif algorithm == "ALAP":
-            self._schedule_alap()
+            self.scheduler.schedule_alap()
+        elif algorithm == "earliest_deadline":
+            self.scheduler.schedule_earliest_deadline()
         elif algorithm == "provided":
             if start_times is None:
                 raise ValueError("Must provide start_times when using 'provided'")
@@ -797,116 +797,116 @@ class Schedule:
                 new_sfg = new_sfg.insert_operation_before(op, Delay(), port)
         return new_sfg()
 
-    def _schedule_alap(self) -> None:
-        """Schedule the operations using as-late-as-possible scheduling."""
-        precedence_list = self._sfg.get_precedence_list()
-        self._schedule_asap()
-        max_end_time = self.get_max_end_time()
-
-        if self.schedule_time is None:
-            self._schedule_time = max_end_time
-        elif self.schedule_time < max_end_time:
-            raise ValueError(f"Too short schedule time. Minimum is {max_end_time}.")
-
-        for output in self._sfg.find_by_type_name(Output.type_name()):
-            output = cast(Output, output)
-            self.move_operation_alap(output.graph_id)
-        for step in reversed(precedence_list):
-            graph_ids = {
-                outport.operation.graph_id
-                for outport in step
-                if not isinstance(outport.operation, Delay)
-            }
-            for graph_id in graph_ids:
-                self.move_operation_alap(graph_id)
-
-    def _schedule_asap(self) -> None:
-        """Schedule the operations using as-soon-as-possible scheduling."""
-        precedence_list = self._sfg.get_precedence_list()
-
-        if len(precedence_list) < 2:
-            raise ValueError("Empty signal flow graph cannot be scheduled.")
-
-        non_schedulable_ops = set()
-        for outport in precedence_list[0]:
-            operation = outport.operation
-            if operation.type_name() not in [Delay.type_name()]:
-                if operation.graph_id not in self._start_times:
-                    # Set start time of all operations in the first iter to 0
-                    self._start_times[operation.graph_id] = 0
-            else:
-                non_schedulable_ops.add(operation.graph_id)
-
-        for outport in precedence_list[1]:
-            operation = outport.operation
-            if operation.graph_id not in self._start_times:
-                # Set start time of all operations in the first iter to 0
-                self._start_times[operation.graph_id] = 0
-
-        for outports in precedence_list[2:]:
-            for outport in outports:
-                operation = outport.operation
-                if operation.graph_id not in self._start_times:
-                    # Schedule the operation if it does not have a start time yet.
-                    op_start_time = 0
-                    for current_input in operation.inputs:
-                        if len(current_input.signals) != 1:
-                            raise ValueError(
-                                "Error in scheduling, dangling input port detected."
-                            )
-                        if current_input.signals[0].source is None:
-                            raise ValueError(
-                                "Error in scheduling, signal with no source detected."
-                            )
-                        source_port = current_input.signals[0].source
-
-                        if source_port.operation.graph_id in non_schedulable_ops:
-                            source_end_time = 0
-                        else:
-                            source_op_time = self._start_times[
-                                source_port.operation.graph_id
-                            ]
-
-                            if source_port.latency_offset is None:
-                                raise ValueError(
-                                    f"Output port {source_port.index} of"
-                                    " operation"
-                                    f" {source_port.operation.graph_id} has no"
-                                    " latency-offset."
-                                )
-
-                            source_end_time = (
-                                source_op_time + source_port.latency_offset
-                            )
-
-                        if current_input.latency_offset is None:
-                            raise ValueError(
-                                f"Input port {current_input.index} of operation"
-                                f" {current_input.operation.graph_id} has no"
-                                " latency-offset."
-                            )
-                        op_start_time_from_in = (
-                            source_end_time - current_input.latency_offset
-                        )
-                        op_start_time = max(op_start_time, op_start_time_from_in)
-
-                    self._start_times[operation.graph_id] = op_start_time
-        for output in self._sfg.find_by_type_name(Output.type_name()):
-            output = cast(Output, output)
-            source_port = cast(OutputPort, output.inputs[0].signals[0].source)
-            if source_port.operation.graph_id in non_schedulable_ops:
-                self._start_times[output.graph_id] = 0
-            else:
-                if source_port.latency_offset is None:
-                    raise ValueError(
-                        f"Output port {source_port.index} of operation"
-                        f" {source_port.operation.graph_id} has no"
-                        " latency-offset."
-                    )
-                self._start_times[output.graph_id] = self._start_times[
-                    source_port.operation.graph_id
-                ] + cast(int, source_port.latency_offset)
-        self._remove_delays()
+    # def _schedule_alap(self) -> None:
+    #     """Schedule the operations using as-late-as-possible scheduling."""
+    #     precedence_list = self._sfg.get_precedence_list()
+    #     self._schedule_asap()
+    #     max_end_time = self.get_max_end_time()
+
+    #     if self.schedule_time is None:
+    #         self._schedule_time = max_end_time
+    #     elif self.schedule_time < max_end_time:
+    #         raise ValueError(f"Too short schedule time. Minimum is {max_end_time}.")
+
+    #     for output in self._sfg.find_by_type_name(Output.type_name()):
+    #         output = cast(Output, output)
+    #         self.move_operation_alap(output.graph_id)
+    #     for step in reversed(precedence_list):
+    #         graph_ids = {
+    #             outport.operation.graph_id
+    #             for outport in step
+    #             if not isinstance(outport.operation, Delay)
+    #         }
+    #         for graph_id in graph_ids:
+    #             self.move_operation_alap(graph_id)
+
+    # def _schedule_asap(self) -> None:
+    #     """Schedule the operations using as-soon-as-possible scheduling."""
+    #     precedence_list = self._sfg.get_precedence_list()
+
+    #     if len(precedence_list) < 2:
+    #         raise ValueError("Empty signal flow graph cannot be scheduled.")
+
+    #     non_schedulable_ops = set()
+    #     for outport in precedence_list[0]:
+    #         operation = outport.operation
+    #         if operation.type_name() not in [Delay.type_name()]:
+    #             if operation.graph_id not in self._start_times:
+    #                 # Set start time of all operations in the first iter to 0
+    #                 self._start_times[operation.graph_id] = 0
+    #         else:
+    #             non_schedulable_ops.add(operation.graph_id)
+
+    #     for outport in precedence_list[1]:
+    #         operation = outport.operation
+    #         if operation.graph_id not in self._start_times:
+    #             # Set start time of all operations in the first iter to 0
+    #             self._start_times[operation.graph_id] = 0
+
+    #     for outports in precedence_list[2:]:
+    #         for outport in outports:
+    #             operation = outport.operation
+    #             if operation.graph_id not in self._start_times:
+    #                 # Schedule the operation if it does not have a start time yet.
+    #                 op_start_time = 0
+    #                 for current_input in operation.inputs:
+    #                     if len(current_input.signals) != 1:
+    #                         raise ValueError(
+    #                             "Error in scheduling, dangling input port detected."
+    #                         )
+    #                     if current_input.signals[0].source is None:
+    #                         raise ValueError(
+    #                             "Error in scheduling, signal with no source detected."
+    #                         )
+    #                     source_port = current_input.signals[0].source
+
+    #                     if source_port.operation.graph_id in non_schedulable_ops:
+    #                         source_end_time = 0
+    #                     else:
+    #                         source_op_time = self._start_times[
+    #                             source_port.operation.graph_id
+    #                         ]
+
+    #                         if source_port.latency_offset is None:
+    #                             raise ValueError(
+    #                                 f"Output port {source_port.index} of"
+    #                                 " operation"
+    #                                 f" {source_port.operation.graph_id} has no"
+    #                                 " latency-offset."
+    #                             )
+
+    #                         source_end_time = (
+    #                             source_op_time + source_port.latency_offset
+    #                         )
+
+    #                     if current_input.latency_offset is None:
+    #                         raise ValueError(
+    #                             f"Input port {current_input.index} of operation"
+    #                             f" {current_input.operation.graph_id} has no"
+    #                             " latency-offset."
+    #                         )
+    #                     op_start_time_from_in = (
+    #                         source_end_time - current_input.latency_offset
+    #                     )
+    #                     op_start_time = max(op_start_time, op_start_time_from_in)
+
+    #                 self._start_times[operation.graph_id] = op_start_time
+    #     for output in self._sfg.find_by_type_name(Output.type_name()):
+    #         output = cast(Output, output)
+    #         source_port = cast(OutputPort, output.inputs[0].signals[0].source)
+    #         if source_port.operation.graph_id in non_schedulable_ops:
+    #             self._start_times[output.graph_id] = 0
+    #         else:
+    #             if source_port.latency_offset is None:
+    #                 raise ValueError(
+    #                     f"Output port {source_port.index} of operation"
+    #                     f" {source_port.operation.graph_id} has no"
+    #                     " latency-offset."
+    #                 )
+    #             self._start_times[output.graph_id] = self._start_times[
+    #                 source_port.operation.graph_id
+    #             ] + cast(int, source_port.latency_offset)
+    #     self._remove_delays()
 
     def _get_memory_variables_list(self) -> List[MemoryVariable]:
         ret: List[MemoryVariable] = []
@@ -1227,3 +1227,149 @@ class Schedule:
 
     # SVG is valid HTML. This is useful for e.g. sphinx-gallery
     _repr_html_ = _repr_svg_
+
+
+class Scheduler():
+    def __init__(self, schedule: Schedule) -> None:
+        self.schedule = schedule
+    
+    def schedule_asap(self) -> None:
+        """Schedule the operations using as-soon-as-possible scheduling."""
+        sched = self.schedule
+        prec_list = sched.sfg.get_precedence_list()
+        if len(prec_list) < 2:
+            raise ValueError("Empty signal flow graph cannot be scheduled.")
+
+        # handle the first set in precedence graph (input and delays)
+        non_schedulable_ops = set()
+        for outport in prec_list[0]:
+            operation = outport.operation
+            if operation.type_name() == Delay.type_name():
+                non_schedulable_ops.add(operation.graph_id)
+            elif operation.graph_id not in sched._start_times:
+                sched._start_times[operation.graph_id] = 0
+
+        # handle second set in precedence graph (first operations)
+        for outport in prec_list[1]:
+            operation = outport.operation
+            if operation.graph_id not in sched._start_times:
+                sched._start_times[operation.graph_id] = 0
+
+        # handle the remaining sets
+        for outports in prec_list[2:]:
+            for outport in outports:
+                operation = outport.operation
+                if operation.graph_id not in sched._start_times:
+                    op_start_time = 0
+                    for current_input in operation.inputs:
+                        if len(current_input.signals) != 1:
+                            raise ValueError(
+                                "Error in scheduling, dangling input port detected."
+                            )
+                        if current_input.signals[0].source is None:
+                            raise ValueError(
+                                "Error in scheduling, signal with no source detected."
+                            )
+                        source_port = current_input.signals[0].source
+
+                        if source_port.operation.graph_id in non_schedulable_ops:
+                            source_end_time = 0
+                        else:
+                            source_op_time = sched._start_times[
+                                source_port.operation.graph_id
+                            ]
+
+                            if source_port.latency_offset is None:
+                                raise ValueError(
+                                    f"Output port {source_port.index} of"
+                                    " operation"
+                                    f" {source_port.operation.graph_id} has no"
+                                    " latency-offset."
+                                )
+
+                            source_end_time = (
+                                source_op_time + source_port.latency_offset
+                            )
+
+                        if current_input.latency_offset is None:
+                            raise ValueError(
+                                f"Input port {current_input.index} of operation"
+                                f" {current_input.operation.graph_id} has no"
+                                " latency-offset."
+                            )
+                        op_start_time_from_in = (
+                            source_end_time - current_input.latency_offset
+                        )
+                        op_start_time = max(op_start_time, op_start_time_from_in)
+
+                    sched._start_times[operation.graph_id] = op_start_time
+        
+        # handle output and remove delays
+        for output in sched._sfg.find_by_type_name(Output.type_name()):
+            output = cast(Output, output)
+            source_port = cast(OutputPort, output.inputs[0].signals[0].source)
+            if source_port.operation.graph_id in non_schedulable_ops:
+                sched._start_times[output.graph_id] = 0
+            else:
+                if source_port.latency_offset is None:
+                    raise ValueError(
+                        f"Output port {source_port.index} of operation"
+                        f" {source_port.operation.graph_id} has no"
+                        " latency-offset."
+                    )
+                sched._start_times[output.graph_id] = sched._start_times[
+                    source_port.operation.graph_id
+                ] + cast(int, source_port.latency_offset)
+        sched._remove_delays()
+
+    def schedule_alap(self) -> None:
+        """Schedule the operations using as-late-as-possible scheduling."""
+        self.schedule_asap()
+        sched = self.schedule
+        max_end_time = sched.get_max_end_time()
+
+        if sched.schedule_time is None:
+            sched.set_schedule_time(max_end_time)
+        elif sched.schedule_time < max_end_time:
+            raise ValueError(f"Too short schedule time. Minimum is {max_end_time}.")
+
+        # move all outputs ALAP before operations
+        for output in sched.sfg.find_by_type_name(Output.type_name()):
+            output = cast(Output, output)
+            sched.move_operation_alap(output.graph_id)
+        
+        # move all operations ALAP
+        for step in reversed(sched.sfg.get_precedence_list()):
+            for outport in step:
+                if not isinstance(outport.operation, Delay):
+                    sched.move_operation_alap(outport.operation.graph_id)
+
+    def schedule_earliest_deadline(self) -> None:
+        """Schedule the operations using earliest deadline scheduling."""
+        pass
+        # sched = self.schedule
+        # prec_list = sched.sfg.get_precedence_list()
+        # if len(prec_list) < 2:
+        #     raise ValueError("Empty signal flow graph cannot be scheduled.")
+
+        # # handle the first set in precedence graph (input and delays)
+        # non_schedulable_ops = set()
+        # for outport in prec_list[0]:
+        #     operation = outport.operation
+        #     if operation.type_name() == Delay.type_name():
+        #         non_schedulable_ops.add(operation.graph_id)
+        #     elif operation.graph_id not in sched._start_times:
+        #         sched._start_times[operation.graph_id] = 0
+
+        # # handle second set in precedence graph (first operations)
+        # for outport in prec_list[1]:
+        #     operation = outport.operation
+        #     if operation.graph_id not in sched._start_times:
+        #         sched._start_times[operation.graph_id] = 0
+        
+        # # handle the remaining sets
+        # for outports in prec_list[2:]:
+        #     for outport in outports:
+        #         operation = outport.operation
+        #         if operation.graph_id not in sched._start_times:
+        #             pass
\ No newline at end of file
diff --git a/b_asic/scheduling_algorithm.py b/b_asic/scheduling_algorithm.py
new file mode 100644
index 0000000000000000000000000000000000000000..8a1dbcd31dbc0f064cd9bfb97ea5bd4dbf61453e
--- /dev/null
+++ b/b_asic/scheduling_algorithm.py
@@ -0,0 +1,8 @@
+from enum import Enum
+
+class SchedAlg(Enum):
+    ASAP = "ASAP"
+    ALAP = "ALAP"
+    EARLIEST_DEADLINE = "earliest_deadline"
+    LEAST_SLACK = "least_slack"
+    PROVIDED = "provided"