Adds an edge to the edge list that will connect the specified nodes.

        Arguments:
            source (Node): The source node of the edge.
            target (Node): The target node of the edge.
            weight (float): The weight of the created edge.
            save_to_cache (bool): Whether the edge should be saved to the local database.

def add_edge(self,
                 source: Node,
                 target: Node,
                 weight: float = 1,
                 save_to_cache: bool = True) -> None:
        """
        Adds an edge to the edge list that will connect the specified nodes.

        Arguments:
            source (Node): The source node of the edge.
            target (Node): The target node of the edge.
            weight (float): The weight of the created edge.
            save_to_cache (bool): Whether the edge should be saved to the local database.
        """
        if not isinstance(source, Node):
            raise TypeError("Invalid source: expected Node instance, got {}.".format(source))
        if not isinstance(target, Node):
            raise TypeError("Invalid target: expected Node instance, got {}.".format(target))

        if source.index == target.index or\
           self.get_edge_by_index(source.index, target.index) is not None:
            return

        self._edges[(source.index, target.index)] = Edge(source, target, weight)

        if save_to_cache:
            should_commit: bool = False
            database: GraphDatabaseInterface = self._graph.database
            db_edge: DBEdge = database.Edge.find_by_name(source.name, target.name)
            if db_edge is None:
                database.session.add(database.Edge(source.name, target.name, weight))
                should_commit = True
            elif db_edge.weight != weight:
                db_edge.weight = weight
                should_commit = True

            if should_commit:
                database.session.commit()