@@ -1070,47 +1070,64 @@ defmodule Graph do
10701070 ...> g = Graph.split_edge(g, :a, :c, :b)
10711071 ...> Graph.edges(g)
10721072 [%Graph.Edge{v1: :a, v2: :b, weight: 2}, %Graph.Edge{v1: :b, v2: :c, weight: 2}]
1073+
1074+ iex> g = Graph.new |> Graph.add_vertices([:a, :c]) |> Graph.add_edge(:a, :c, label: :first_label, weight: 2) |> Graph.add_edge(:a, :c, label: :second_label, weight: 2)
1075+ ...> g = Graph.split_edge(g, :a, :c, :b)
1076+ ...> Graph.edges(g)
1077+ [%Graph.Edge{v1: :a, v2: :b, label: :first_label, weight: 2}, %Graph.Edge{v1: :a, v2: :b, label: :second_label, weight: 2}, %Graph.Edge{v1: :b, v2: :c, label: :first_label, weight: 2}, %Graph.Edge{v1: :b, v2: :c, label: :second_label, weight: 2}]
10731078 """
10741079 @ spec split_edge ( t , vertex , vertex , vertex ) :: t | { :error , :no_such_edge }
1075- def split_edge ( % __MODULE__ { type: :undirected } = g , v1 , v2 , v3 ) do
1080+ def split_edge ( % __MODULE__ { } = g , v1 , v2 , v3 ) do
1081+ split_labelled_edge ( g , v1 , v2 , v3 , nil )
1082+ end
1083+
1084+ @ doc """
1085+ Like `split_edge/4`, but requires you to specify the labelled edge to split.
1086+
1087+ Th implementation of `splt_edge/4` is actually `split_labelled_edge(g, v1, v2, v3, nil)`.
1088+
1089+ ## Example
1090+
1091+ iex> g = Graph.new |> Graph.add_vertices([:a, :c]) |> Graph.add_edge(:a, :c, label: :first_label, weight: 2) |> Graph.add_edge(:a, :c, label: :second_label, weight: 2)
1092+ ...> g = Graph.split_labelled_edge(g, :a, :c, :b, :first_label)
1093+ ...> Graph.edges(g)
1094+ [%Graph.Edge{v1: :a, v2: :b, label: :first_label, weight: 2}, %Graph.Edge{v1: :a, v2: :c, label: :second_label, weight: 2}, %Graph.Edge{v1: :b, v2: :c, label: :first_label, weight: 2}]
1095+ """
1096+ def split_labelled_edge ( % __MODULE__ { type: :undirected } = g , v1 , v2 , v3 , label ) do
10761097 if v1 > v2 do
1077- do_split_edge ( g , v2 , v1 , v3 )
1098+ do_split_labelled_edge ( g , v2 , v1 , v3 , label )
10781099 else
1079- do_split_edge ( g , v1 , v2 , v3 )
1100+ do_split_labelled_edge ( g , v1 , v2 , v3 , label )
10801101 end
10811102 end
10821103
1083- def split_edge ( % __MODULE__ { } = g , v1 , v2 , v3 ) do
1084- do_split_edge ( g , v1 , v2 , v3 )
1104+ def split_labelled_edge ( % __MODULE__ { } = g , v1 , v2 , v3 , label ) do
1105+ do_split_labelled_edge ( g , v1 , v2 , v3 , label )
10851106 end
10861107
1087- defp do_split_edge (
1088- % __MODULE__ { in_edges: ie , out_edges: oe , edges: em , vertex_identifier: vertex_identifier } =
1108+ defp do_split_labelled_edge (
1109+ % __MODULE__ { out_edges: oe , edges: em , vertex_identifier: vertex_identifier } =
10891110 g ,
10901111 v1 ,
10911112 v2 ,
1092- v3
1113+ v3 ,
1114+ label
10931115 ) do
10941116 with v1_id <- vertex_identifier . ( v1 ) ,
10951117 v2_id <- vertex_identifier . ( v2 ) ,
10961118 { :ok , v1_out } <- Map . fetch ( oe , v1_id ) ,
1097- { :ok , v2_in } <- Map . fetch ( ie , v2_id ) ,
10981119 true <- MapSet . member? ( v1_out , v2_id ) ,
1099- meta <- Map . get ( em , { v1_id , v2_id } ) ,
1100- v1_out <- MapSet . delete ( v1_out , v2_id ) ,
1101- v2_in <- MapSet . delete ( v2_in , v1_id ) do
1102- g = % __MODULE__ {
1103- g
1104- | in_edges: Map . put ( ie , v2_id , v2_in ) ,
1105- out_edges: Map . put ( oe , v1_id , v1_out )
1106- }
1107-
1120+ meta <- Map . get ( em , { v1_id , v2_id } ) do
11081121 g = add_vertex ( g , v3 )
1109-
1110- Enum . reduce ( meta , g , fn { label , weight } , acc ->
1111- acc
1112- |> add_edge ( v1 , v3 , label: label , weight: weight )
1113- |> add_edge ( v3 , v2 , label: label , weight: weight )
1122+ Enum . reduce ( meta , g , fn { edge_label , weight } , acc ->
1123+ if edge_label == label or label == nil do
1124+ acc
1125+ |> add_edge ( v1 , v3 , label: edge_label , weight: weight )
1126+ |> add_edge ( v3 , v2 , label: edge_label , weight: weight )
1127+ |> delete_edge ( v1 , v2 , edge_label )
1128+ else
1129+ acc
1130+ end
11141131 end )
11151132 else
11161133 _ -> { :error , :no_such_edge }
0 commit comments