anchor.diff:          fun({AllDegree, InDegree}) ->
               {AllDegree + NodeDegree, InDegree + CommWeight}
           end, {NodeDegree, CommWeight}, Weights#louvain_weights.weights)}.
  +
  +compare_weights(WA, WB) ->
  +    ?ASSERTEQUAL(WA#louvain_weights.m, WB#louvain_weights.m),
  +    WeightsDA = lists:sort(lists:filter(fun({_,{0.0,0.0}}) -> false; (_) -> true end, dict:to_list(WA#louvain_weights.weights))),
  +    WeightsDB = lists:sort(lists:filter(fun({_,{0.0,0.0}}) -> false; (_) -> true end, dict:to_list(WB#louvain_weights.weights))),
  +    ?ASSERTEQUAL(WeightsDA, WeightsDB).
   
   % weight of all edges to neighbors, and weights to neighboring communities.
   % weights to neighboring communities exclude Node
  
positive.code: %% Python implementation - https://bitbucket.org/taynaud/python-louvain
  %% @end
  
  -define(ASSERTEQUAL(A,B), begin case A == B of true -> ok; false -> error({A, not_equal, B}) end end).
  
  -module(part_louvain).
  
  
negative.code:     {N1,N2};
  vsort({N1,N2}) ->
      {N2,N1}.
  
  validate_graph(GD = #louvain_graphd{communitiesd = CommunitiesD, edgesd = EdgesD, neighborsd = NeighborsD}) ->
      vg_neighbors_symmetric(GD),
      % edge in neighbors is edge in edges
      NeighborEdges = sets:from_list(
          dict:fold(
              fun(_, Neighbors, ES0) ->
                  lists:foldl(
                      fun({_, Edge}, ES1) ->
                          [Edge | ES1]
                      end, ES0, Neighbors)
              end, [], NeighborsD)),
      Edges = sets:from_list(dict:fetch_keys(EdgesD)),
      ?ASSERTEQUAL(true, sets:is_subset(NeighborEdges, Edges) andalso
                          sets:is_subset(Edges, NeighborEdges)),
  
      % node in community is node in neighbors
      CommunityKeys = sets:from_list(dict:fetch_keys(CommunitiesD)),
      NeighborKeys = sets:from_list(dict:fetch_keys(NeighborsD)),
      ?ASSERTEQUAL(true, sets:is_subset(CommunityKeys, NeighborKeys)).
  
  % When N2 is a neighbor of N1, then N1 is a neighbor of N2.
  vg_neighbors_symmetric(#louvain_graphd{neighborsd = NeighborsD}) ->
      {Left2Right, Right2Left} = dict:fold(
          fun(Node, Neighbors, {L2R, R2L}) ->
              {
                  % for {N, [N1, N2]} -> [{N, N1}, {N, N2}]
                  [ [{Node, NN1} || NN1 <- Neighbors] | L2R ],
                  % for {N, [N1, N2]} -> [{N1, N}, {N2, N}]
                  [ [{NN2, Node} || NN2 <- Neighbors] | R2L ]
              }
          end, {[], []}, NeighborsD),
      % Left2Right and Right2Left lists should be the same
      L2RSet = sets:from_list(lists:flatten(Left2Right)),
      R2LSet = sets:from_list(lists:flatten(Right2Left)),
      ?ASSERTEQUAL([], sets:to_list(sets:subtract(L2RSet, R2LSet))),
      ?ASSERTEQUAL([], sets:to_list(sets:subtract(R2LSet, L2RSet))).
  