anchor.diff:                        digraph:vertex(),
                         #edge_label{}}.
   
  --type contract_path() :: list(lasp_vertex()).
  -
   %%%===================================================================
   %%% API
   %%%===================================================================
  
positive.code:     apply_sequentially(Int(H(X)), T, Int, Final).
  
  %% @doc Get an unique identifier for a process in the graph.
  -spec process_hash(process_args()) -> contract_process_id().
  process_hash(Args) ->
      erlang:phash2(Args).
  
  
negative.code: %%% Type definitions
  %%%===================================================================
  
  %% To make contractions reversible, we have to hold all the
  %% information about the removed vertices and the edges that were
  %% connecting them. When a contraction is reversed, we use this infomation
  %% to restart the intermediate processes, linking together the correct
  %% vertices. One a contraction is reversed, all this metadata is removed.
  %%
  %% Stored metadata for a lasp process.
  %% We don't store the input(s) and output vertices as that information
  %% is implicitly stored by edges in the graph.
  %%
  %% Used to represent the metadata of processes inside a contracted path,
  %% that only can have one parent and one child, hence why there is only
  %% a single read function.
  -record(process_metadata, {read :: function(),
                             transform :: function(),
                             write :: function()}).
  
  
  %% A process hash is defined as the hash of their metadata (process_args).
  %% This hash keeps constant through process restarts, and is used to uniquely
  %% identify a process that connects the endpoints of a contracted path.
  %% Removed vertices keep a reference to a process hash to identify in what path
  %% they were before being removed (vertex_label).
  -type process_hash() :: non_neg_integer().
  -record(vertex_label, {process_pointer :: process_hash()}).
  -type process_args() :: {[{lasp_vertex(), function()}],
                           function(),
                           {lasp_vertex(), function()}}.
  
  %% We monitor all lasp processes, but the only information we get once that
  %% happens is the process pid. This table keeps a mapping between hashes and
  %% pids, and is used to during a cleaving pass to get to the information in
  %% the optimized map.
  -type pid_table() :: dict:dict(pid(), process_hash()).
  
  %% This structure maps process hashes, identifying processes that connect
  %% endpoints in a contracted path, to a list of vertices representing
  %% the old path before being contracted, and a list of the metadata of
  %% the lasp processes that linked those vertices together.
  %% In this metadata list, each element at a position i represents the metadata
  %% connecting the i-th and (i+1)-th vertices in the vertex list.
  -type optimized_map() :: dict:dict(process_hash(),
                                     {pid(),
                                      contract_path(),
                                      list(#process_metadata{})}).
  
  %% A step is defined as a call to add_edges. While we are defining our
  %% application topology, the graph is suitable to be changed regularly.
  %% See ?CONTRACTION_INTERVAL. One the step counter reaches that value,
  %% an optimization pass occurs, and then is reset to zero.
  -type contraction_step() :: non_neg_integer().
  
  %% Only used to represent paths suitable to be contracted. These paths
  %% consist of two necessary endpoints and a list of unnecessary vertices
  %% in between.
  -type contract_path() :: list(lasp_vertex()).
  
  %% We store a mapping Pid -> [{parent_node, child_node}] to
  %% find the edge labeled with it without traversing the graph.
  %%
  