@@ -33,7 +33,7 @@ defmodule Graph do
3333 vertices: % { } ,
3434 type: :directed ,
3535 vertex_identifier: & Graph.Utils . vertex_id / 1 ,
36- partition_by: & Graph.Utils . edge_label / 1 ,
36+ partition_by: & Graph.Utils . by_edge_label / 1 ,
3737 multigraph: false
3838
3939 alias Graph . { Edge , EdgeSpecificationError }
@@ -65,7 +65,7 @@ defmodule Graph do
6565 vertices: % { vertex_id => vertex } ,
6666 type: graph_type ,
6767 vertex_identifier: ( vertex ( ) -> term ( ) ) ,
68- partition_by: ( Edge . t ( ) -> edge_index_key ) ,
68+ partition_by: ( Edge . t ( ) -> list ( edge_index_key ) ) ,
6969 multigraph: boolean ( )
7070 }
7171 @ type graph_info :: % {
@@ -86,8 +86,8 @@ defmodule Graph do
8686 - `multigraph: true | false | fn edge -> key end`, enables edge indexing by a key.
8787 - When `true`, the key is the edge label itself.
8888 - When `false` no additional memory is used for sets of .
89- - `partition_by`: a function which accepts an `%Edge{}` and returns a unique identifier of said edge .
90- Defaults to `Graph.Utils.edge_label /1`, the edge label itself when multigraphs are enabled.
89+ - `partition_by`: a function which accepts an `%Edge{}` and returns a list of unique identifiers used as the partition keys .
90+ Defaults to `Graph.Utils.by_edge_label /1`, which partitions edges by the label when multigraphs are enabled.
9191
9292 ### Multigraph Edge Indexing
9393
@@ -113,11 +113,15 @@ defmodule Graph do
113113 iex> g = Graph.new(vertex_identifier: fn v -> :erlang.phash2(v) end) |> Graph.add_edges([{:a, :b}, {:b, :a}])
114114 ...> Graph.edges(g)
115115 [%Graph.Edge{v1: :a, v2: :b}, %Graph.Edge{v1: :b, v2: :a}]
116+
117+ iex> g = Graph.new(multigraph: true, partition_by: fn edge -> [edge.weight] end) |> Graph.add_edges([{:a, :b, weight: 1}, {:b, :a, weight: 2}])
118+ ...> Graph.edges(g, by: 1)
119+ [%Graph.Edge{v1: :a, v2: :b, weight: 1}]
116120 """
117121 def new ( opts \\ [ ] ) do
118122 type = Keyword . get ( opts , :type ) || :directed
119123 vertex_identifier = Keyword . get ( opts , :vertex_identifier ) || ( & Graph.Utils . vertex_id / 1 )
120- partition_by = Keyword . get ( opts , :partition_by ) || ( & Graph.Utils . edge_label / 1 )
124+ partition_by = Keyword . get ( opts , :partition_by ) || ( & Graph.Utils . by_edge_label / 1 )
121125 multigraph = Keyword . get ( opts , :multigraph , false )
122126
123127 % __MODULE__ {
@@ -555,7 +559,7 @@ defmodule Graph do
555559 v2 = Map . get ( vs , v2_id )
556560
557561 for { label , meta_value } <- edge_meta do
558- Edge . new ( v2 , v ,
562+ Edge . new ( v , v2 ,
559563 label: label ,
560564 weight: meta_value . weight ,
561565 properties: meta_value . properties
@@ -658,9 +662,9 @@ defmodule Graph do
658662 properties: edge_meta . properties
659663 )
660664
661- edge_partition = g . partition_by . ( edge )
665+ edge_partitions = g . partition_by . ( edge )
662666
663- if include_edge_for_filtered_partitions? ( edge , edge_partition , partitions , where_fun ) do
667+ if include_edge_for_filtered_partitions? ( edge , edge_partitions , partitions , where_fun ) do
664668 [ edge | acc ]
665669 else
666670 acc
@@ -711,9 +715,9 @@ defmodule Graph do
711715 properties: edge_meta . properties
712716 )
713717
714- edge_partition = g . partition_by . ( edge )
718+ edge_partitions = g . partition_by . ( edge )
715719
716- if include_edge_for_filtered_partitions? ( edge , edge_partition , partitions , where_fun ) do
720+ if include_edge_for_filtered_partitions? ( edge , edge_partitions , partitions , where_fun ) do
717721 [ edge | acc ]
718722 else
719723 acc
@@ -1216,34 +1220,36 @@ defmodule Graph do
12161220 end
12171221
12181222 defp index_multigraph_edge (
1219- % __MODULE__ { multigraph: true , edge_index: edge_index } = g ,
1223+ % __MODULE__ { multigraph: true } = graph ,
12201224 { v1_id , v2_id } ,
12211225 % Edge { } = edge
12221226 ) do
1223- partition = g . partition_by . ( edge )
1227+ partitions = graph . partition_by . ( edge )
12241228
1225- edge_partition = Map . get ( edge_index , partition , % { } )
1229+ Enum . reduce ( partitions , graph , fn partition , g ->
1230+ edge_partition = Map . get ( g . edge_index , partition , % { } )
12261231
1227- v1_set = Map . get ( edge_partition , v1_id , MapSet . new ( ) )
1228- v2_set = Map . get ( edge_partition , v2_id , MapSet . new ( ) )
1232+ v1_set = Map . get ( edge_partition , v1_id , MapSet . new ( ) )
1233+ v2_set = Map . get ( edge_partition , v2_id , MapSet . new ( ) )
12291234
1230- new_edge_partition =
1231- edge_partition
1232- |> Map . put (
1233- v1_id ,
1234- MapSet . put ( v1_set , { v1_id , v2_id } )
1235- )
1236- |> Map . put (
1237- v2_id ,
1238- MapSet . put ( v2_set , { v1_id , v2_id } )
1239- )
1235+ new_edge_partition =
1236+ edge_partition
1237+ |> Map . put (
1238+ v1_id ,
1239+ MapSet . put ( v1_set , { v1_id , v2_id } )
1240+ )
1241+ |> Map . put (
1242+ v2_id ,
1243+ MapSet . put ( v2_set , { v1_id , v2_id } )
1244+ )
12401245
1241- % __MODULE__ {
1242- g
1243- | edge_index:
1244- edge_index
1245- |> Map . put ( partition , new_edge_partition )
1246- }
1246+ % __MODULE__ {
1247+ g
1248+ | edge_index:
1249+ g . edge_index
1250+ |> Map . put ( partition , new_edge_partition )
1251+ }
1252+ end )
12471253 end
12481254
12491255 @ doc """
@@ -1530,20 +1536,22 @@ defmodule Graph do
15301536 edge =
15311537 Edge . new ( v1 , v2 , label: label , weight: edge_meta . weight , properties: edge_meta . properties )
15321538
1533- edge_p = partition_by . ( edge )
1539+ edge_partitions = partition_by . ( edge )
15341540
1535- v1_key = { v1_id , edge_p }
1536- v2_key = { v2_id , edge_p }
1541+ Enum . reduce ( edge_partitions , acc , fn edge_p , acc ->
1542+ v1_key = { v1_id , edge_p }
1543+ v2_key = { v2_id , edge_p }
15371544
1538- edge_index =
1539- edge_index
1540- |> Map . delete ( v1_key )
1541- |> Map . delete ( v2_key )
1545+ edge_index =
1546+ edge_index
1547+ |> Map . delete ( v1_key )
1548+ |> Map . delete ( v2_key )
15421549
1543- % __MODULE__ {
1544- acc
1545- | edge_index: edge_index
1546- }
1550+ % __MODULE__ {
1551+ acc
1552+ | edge_index: edge_index
1553+ }
1554+ end )
15471555 end )
15481556 end
15491557
@@ -1568,27 +1576,29 @@ defmodule Graph do
15681576 edge =
15691577 Edge . new ( v1 , v2 , label: label , weight: edge_meta . weight , properties: edge_meta . properties )
15701578
1571- edge_p = partition_by . ( edge )
1579+ edge_partitions = partition_by . ( edge )
15721580
1573- partition =
1574- edge_index
1575- |> Map . get ( edge_p , % { } )
1576- |> Map . reject ( fn { k , v } ->
1577- ( k == v1_id and MapSet . member? ( v , { v1_id , v2_id } ) ) or
1578- ( k == v2_id and MapSet . member? ( v , { v1_id , v2_id } ) )
1579- end )
1581+ Enum . reduce ( edge_partitions , g , fn edge_p , acc ->
1582+ partition =
1583+ edge_index
1584+ |> Map . get ( edge_p , % { } )
1585+ |> Map . reject ( fn { k , v } ->
1586+ ( k == v1_id and MapSet . member? ( v , { v1_id , v2_id } ) ) or
1587+ ( k == v2_id and MapSet . member? ( v , { v1_id , v2_id } ) )
1588+ end )
15801589
1581- edge_index =
1582- if not Enum . empty? ( partition ) do
1583- Map . put ( edge_index , edge_p , partition )
1584- else
1585- Map . delete ( edge_index , edge_p )
1586- end
1590+ edge_index =
1591+ if not Enum . empty? ( partition ) do
1592+ Map . put ( edge_index , edge_p , partition )
1593+ else
1594+ Map . delete ( edge_index , edge_p )
1595+ end
15871596
1588- % __MODULE__ {
1589- g
1590- | edge_index: edge_index
1591- }
1597+ % __MODULE__ {
1598+ acc
1599+ | edge_index: edge_index
1600+ }
1601+ end )
15921602 end
15931603
15941604 defp prune_edge_index ( % __MODULE__ { multigraph: false } = g , _v1 , _v2 , _label ) do
@@ -2527,9 +2537,9 @@ defmodule Graph do
25272537 properties: edge_meta . properties
25282538 )
25292539
2530- edge_partition = partition_by . ( edge )
2540+ edge_partitions = partition_by . ( edge )
25312541
2532- if edge_partition == partition do
2542+ if Enum . any? ( edge_partitions , fn edge_partition -> edge_partition == partition end ) do
25332543 edge
25342544 else
25352545 nil
@@ -2681,9 +2691,9 @@ defmodule Graph do
26812691 properties: edge_meta . properties
26822692 )
26832693
2684- edge_partition = partition_by . ( edge )
2694+ edges_in_partitions = partition_by . ( edge )
26852695
2686- if include_edge_for_filtered_partitions? ( edge , edge_partition , partitions , where_fun ) do
2696+ if include_edge_for_filtered_partitions? ( edge , edges_in_partitions , partitions , where_fun ) do
26872697 [ edge | acc ]
26882698 else
26892699 acc
@@ -2692,13 +2702,13 @@ defmodule Graph do
26922702 end )
26932703 end
26942704
2695- defp include_edge_for_filtered_partitions? ( _edge , edge_partition , partitions , nil = _where_fun ) do
2696- edge_partition in partitions
2705+ defp include_edge_for_filtered_partitions? ( _edge , edge_partitions , partitions , nil = _where_fun ) do
2706+ Enum . any? ( edge_partitions , fn ep -> ep in partitions end )
26972707 end
26982708
2699- defp include_edge_for_filtered_partitions? ( edge , edge_partition , partitions , where_fun )
2709+ defp include_edge_for_filtered_partitions? ( edge , edge_partitions , partitions , where_fun )
27002710 when is_function ( where_fun ) do
2701- edge_partition in partitions and where_fun . ( edge )
2711+ Enum . any? ( edge_partitions , fn ep -> ep in partitions and where_fun . ( edge ) end )
27022712 end
27032713
27042714 defp include_edge_for_filtered_partitions? ( edge , _edge_partition , _partitions , where_fun )
0 commit comments