diff --git a/.gitignore b/.gitignore index 735ed1d..aa33e60 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ erl_crash.dump # QuickCheck files /.eqc-info /*.eqc + +# Ignore logs from lexical +/.lexical diff --git a/.lexical/lexical.log b/.lexical/lexical.log new file mode 100644 index 0000000..8a60cde --- /dev/null +++ b/.lexical/lexical.log @@ -0,0 +1,37 @@ +19:58:35.632 [debug] Child {LoggerFileBackend, :general_log} of Supervisor Logger.Backends.Supervisor started +Pid: #PID<0.114.0> +Start Call: Logger.Backends.Watcher.start_link({{LoggerFileBackend, :general_log}, {LoggerFileBackend, :general_log}}) +Restart: :transient +Shutdown: 5000 +Type: :worker +19:58:35.632 [info] Child Logger.Backends.Supervisor of Supervisor Logger.Backends.Internal started +Pid: #PID<0.113.0> +Start Call: Logger.Backends.Supervisor.start_link([{LoggerFileBackend, :general_log}]) +Restart: :permanent +Shutdown: :infinity +Type: :supervisor +19:58:35.632 [info] Child Logger.Backends.Internal of Supervisor Logger.Supervisor started +Pid: #PID<0.109.0> +Start Call: Logger.Backends.Internal.start_link([]) +Restart: :permanent +Shutdown: :infinity +Type: :supervisor +19:58:35.633 [info] Application logger started at :nonode@nohost +19:58:36.702 [error] FATAL: Lexical is not compatible with Elixir 1.18.1 + +Lexical is compatible with the following versions of Elixir: + + >= 1.13.0 + >= 1.14.0 + >= 1.15.3 + >= 1.16.0 + + +FATAL: Lexical is not compatible with Erlang/OTP 27.1.3 + +Lexical is compatible with the following versions of Erlang/OTP: + + >= 24.3.4 + >= 25.0.0 + >= 26.0.2 + diff --git a/lib/graph.ex b/lib/graph.ex index b66670f..8759c81 100644 --- a/lib/graph.ex +++ b/lib/graph.ex @@ -800,64 +800,80 @@ defmodule Graph do """ @spec replace_vertex(t, vertex, vertex) :: t | {:error, :no_such_vertex} def replace_vertex( - %__MODULE__{out_edges: oe, in_edges: ie, edges: em, vertex_identifier: vertex_identifier} = + %__MODULE__{ + vertices: vs, + vertex_labels: labels, + out_edges: oe, + in_edges: ie, + edges: em, + vertex_identifier: vertex_identifier + } = g, v, rv ) do - vs = g.vertices - labels = g.vertex_labels - with v_id <- vertex_identifier.(v), true <- Map.has_key?(vs, v_id), rv_id <- vertex_identifier.(rv), - vs <- Map.put(Map.delete(vs, v_id), rv_id, rv) do - oe = - for {from_id, to} = e <- oe, into: %{} do - fid = if from_id == v_id, do: rv_id, else: from_id + vs <- Map.put(Map.delete(vs, v_id), rv_id, rv), + {vlbls, lbls} = Map.pop(labels, v_id), + {ovs, oe} = Map.pop(oe, v_id), + {ivs, ie} = Map.pop(ie, v_id) do + {em, oe, ie} = + em + |> Enum.reduce({em, oe, ie}, fn + {{^v_id, ^v_id} = k, meta}, {e, o, i} -> + o = + if is_nil(ovs) do + o + else + Map.put(o, rv_id, ovs) + end - cond do - MapSet.member?(to, v_id) -> - {fid, MapSet.put(MapSet.delete(to, v_id), rv_id)} + i = + if is_nil(ivs) do + i + else + Map.put(i, rv_id, ivs) + end - from_id != fid -> - {fid, to} + {Map.put(Map.delete(e, k), {rv_id, rv_id}, meta), o, i} - :else -> - e - end - end + {{^v_id, id2} = k, meta}, {e, o, i} -> + o = + if is_nil(ovs) do + o + else + Map.put(o, rv_id, ovs) + end - ie = - for {to_id, from} = e <- ie, into: %{} do - tid = if to_id == v_id, do: rv_id, else: to_id + i = + Map.update!(i, id2, fn set -> set |> MapSet.delete(v_id) |> MapSet.put(rv_id) end) - cond do - MapSet.member?(from, v_id) -> - {tid, MapSet.put(MapSet.delete(from, v_id), rv_id)} + {Map.put(Map.delete(e, k), {rv_id, id2}, meta), o, i} - to_id != tid -> - {tid, from} + {{id1, ^v_id} = k, meta}, {e, o, i} -> + o = + Map.update!(o, id1, fn set -> set |> MapSet.delete(v_id) |> MapSet.put(rv_id) end) - :else -> - e - end - end + i = + if is_nil(ivs) do + i + else + Map.put(i, rv_id, ivs) + end - meta = - em - |> Stream.map(fn - {{^v_id, ^v_id}, meta} -> {{rv_id, rv_id}, meta} - {{^v_id, v2_id}, meta} -> {{rv_id, v2_id}, meta} - {{v1_id, ^v_id}, meta} -> {{v1_id, rv_id}, meta} - edge -> edge + {Map.put(Map.delete(e, k), {id1, rv_id}, meta), o, i} + + _, acc -> + acc end) - |> Enum.into(%{}) labels = - case Map.get(labels, v_id) do - nil -> labels - label -> Map.put(Map.delete(labels, v_id), rv_id, label) + if is_nil(vlbls) do + lbls + else + Map.put(lbls, rv_id, vlbls) end %__MODULE__{ @@ -865,7 +881,7 @@ defmodule Graph do | vertices: vs, out_edges: oe, in_edges: ie, - edges: meta, + edges: em, vertex_labels: labels } else @@ -889,22 +905,49 @@ defmodule Graph do """ @spec delete_vertex(t, vertex) :: t def delete_vertex( - %__MODULE__{out_edges: oe, in_edges: ie, edges: em, vertex_identifier: vertex_identifier} = + %__MODULE__{ + vertices: vs, + vertex_labels: ls, + out_edges: oe, + in_edges: ie, + edges: em, + vertex_identifier: vertex_identifier + } = g, v ) do - vs = g.vertices - ls = g.vertex_labels - with v_id <- vertex_identifier.(v), true <- Map.has_key?(vs, v_id), - oe <- Map.delete(oe, v_id), - ie <- Map.delete(ie, v_id), + {outs, oe} <- Map.pop(oe, v_id), + {ins, ie} <- Map.pop(ie, v_id), vs <- Map.delete(vs, v_id), ls <- Map.delete(ls, v_id) do - oe = for {id, ns} <- oe, do: {id, MapSet.delete(ns, v_id)}, into: %{} - ie = for {id, ns} <- ie, do: {id, MapSet.delete(ns, v_id)}, into: %{} - em = for {{id1, id2}, _} = e <- em, v_id != id1 && v_id != id2, do: e, into: %{} + {ie, em} = + case outs do + nil -> + {ie, em} + + _ -> + outs + |> Enum.reduce({ie, em}, fn id1, {i, e} -> + {Map.update!(i, id1, fn ns -> MapSet.delete(ns, v_id) end), + Map.delete(e, {v_id, id1})} + end) + end + + {oe, em} = + case ins do + nil -> + {oe, em} + + _ -> + ins + |> Enum.reduce({oe, em}, fn id1, {o, e} -> + {Map.update!(o, id1, fn ns -> MapSet.delete(ns, v_id) end), + Map.delete(e, {id1, v_id})} + end) + end + %__MODULE__{g | vertices: vs, vertex_labels: ls, out_edges: oe, in_edges: ie, edges: em} else _ -> g diff --git a/test/priority_queue_test.exs b/test/priority_queue_test.exs index ab6b632..20d5d40 100644 --- a/test/priority_queue_test.exs +++ b/test/priority_queue_test.exs @@ -10,7 +10,7 @@ defmodule PriorityQueue.Test do end) str = "#{inspect(pq)}" - assert "#PriorityQueue" = str + assert "#PriorityQueue" = str end test "can enqueue random elements and pull them out in priority order" do