def add_edge(source, target, *args)
      if Vertex===source and Vertex===target
        edge = Digraph::Edge.new(self, @edges.length, source, target)
        apply_arg_conventions(edge, args)
        source.add_out_edge(edge)
        target.add_in_edge(edge)
        @edges << edge
        edge
      else
        sources, targets = to_vertices(source), to_vertices(target)
        created = EdgeSet[]
        sources.each do |src|
          targets.each do |trg|
            created << add_edge(src, trg, *args)
          end
        end
        created
      end
    end
def add_edge(source, target, *args)
      if Vertex===source and Vertex===target
        edge = Digraph::Edge.new(self, @edges.length, source, target)
        apply_arg_conventions(edge, args)
        source.add_out_edge(edge)
        target.add_in_edge(edge)
        @edges << edge
        edge
      else
        sources, targets = to_vertices(source), to_vertices(target)
        created = EdgeSet[]
        sources.each do |src|
          targets.each do |trg|
            created << add_edge(src, trg, *args)
          end
        end
        created
      end
    end
Connects source to target state(s). _source_ and _target_ may be any
 selection expression that can lead to vertex sets. _args_ can be module
 instances or hashes,  which are all installed on edges _e_ using
 <tt>e.tag</tt> and <tt>e.add_marks</tt>, respectively.