anchor.diff:  
   is_edge_error(_) ->
       false.
  +
  +%% @doc Delete all edges between Src and Dst with the given label.
  +-spec delete_with_label(digraph:graph(), id(), id(), term()) -> digraph:graph().
  +delete_with_label(Graph, Src, Dst, Label) ->
  +  lists:filtermap(fun
  +                    ({E, _, _, L}) when L =:= Label -> {true, digraph:del_edge(Graph, E)};
  +                    (_) -> false
  +                  end, get_direct_edges(Graph, Src, Dst)),
  +  Graph.
  +
  +%% @doc Return all direct edges linking V1 and V2.
  +%%
  +%%      If V1 and V2 are not linked, return the empty list.
  +%%
  +%%      Otherwise, get all emanating edges from V1, and return
  +%%      only the ones linking to V2.
  +%%
  +-spec get_direct_edges(digraph:graph(),
  +    digraph:vertex(), digraph:vertex()) -> list(edge()).
  +
  +get_direct_edges(G, V1, V2) ->
  +  case directly_connected(G, V1, V2) of
  +    false -> [];
  +    true ->
  +      lists:flatmap(fun(Ed) ->
  +        case digraph:edge(G, Ed) of
  +          {_, _, To, _}=E when To =:= V2 -> [E];
  +          _ -> []
  +        end
  +                    end, digraph:out_edges(G, V1))
  +  end.
  +
  +%% @doc Are V1 and V2 linked directly?
  +%%
  +%%      digraph:get_short_path/3 returns a list of vertices if V1 and V2
  +%%      are connected, false otherwise.
  +%%
  +%%      If they are linked directly, this vertex list will only contain V1
  +%%      and V2.
  +%%
  +-spec directly_connected(digraph:graph(),
  +    digraph:vertex(), digraph:vertex()) -> boolean().
  +
  +directly_connected(G, V1, V2) ->
  +  case digraph:get_short_path(G, V1, V2) of
  +    [V1, V2] -> true;
  +    _        -> false
  +  end.
   
   to_dot(Graph) ->
       Start = ["digraph dag {\n"],
  
positive.code:     {reply, Response, State};
  
  %% @doc For all V in Src, create an edge from V to Dst labelled with Pid.
  handle_call({add_edges, Src, Dst, Pid}, _From, #state{dag=Dag}=State) ->
      %% @todo Add metadata and duplicate checking.
      Status = [digraph:add_edge(Dag, V, Dst, Pid) || V <- Src],
      R = case lists:any(fun is_graph_error/1, Status) of
          false -> ok;
          true -> error
      end,
      {reply, R, State}.
  
  %% @private
  -spec handle_cast(term(), #state{}) -> {noreply, #state{}}.
  
negative.code: 
  %% @private
  -spec handle_info(term(), #state{}) -> {noreply, #state{}}.
  
  %% @doc Remove the edges associated with a lasp process when it terminates.
  %%
  %%      Given that lasp processes might get restarted or terminated,
  %%      we have to know when it happens so we can delete the appropiate
  %%      edges in the graph.
  %%
  handle_info({'DOWN', _, process, Pid, _Reason}, #state{dag=Dag, process_map=PM}=State) ->
      {ok, Edges} = dict:find(Pid, PM),
      NewDag = lists:foldl(fun({F, T}, G) ->
          delete_with_label(G, F, T, Pid)
      end, Dag, Edges),
      {noreply, State#state{dag=NewDag, process_map=dict:erase(Pid, PM)}};
  
  handle_info(Msg, State) ->
      _ = lager:warning("Unhandled messages ~p", [Msg]),
      {noreply, State}.
  
  %% @private
  