Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Errors while exporting and importing graphs #2

Closed
ghost opened this issue Mar 8, 2016 · 6 comments
Closed

Errors while exporting and importing graphs #2

ghost opened this issue Mar 8, 2016 · 6 comments
Assignees

Comments

@ghost
Copy link

ghost commented Mar 8, 2016

@aggelgian
I'm using the graph module to export & import graphs.
While exporting a graph, I sometimes get this error

** (ArgumentError) argument error
    (stdlib) :ets.select(262184, [{{:"$1", :_, :_, :_}, [], [:"$1"]}])
    (stdlib) digraph.erl:312: :digraph.edges/1
[…]

When I export the graph to a file and call :graph.from_file/('priv/graph.txt'), I get this error:

iex(20)⋅❯ :graph.from_file('priv/graph.txt')
** (MatchError) no match of right hand side value: {:error, {:fread, :integer}}
             :graph.from_file/3
    (stdlib) :digraph.del_edge/2

Right now my priority is the ability to import a graph. Could you tell me what I'm missing?

@aggelgian
Copy link
Owner

@Annwenn
Hello! How exactly do you export the graph?
Could you provide me with a minimal example to reproduce the error?

@aggelgian aggelgian self-assigned this Mar 9, 2016
@ghost
Copy link
Author

ghost commented Mar 9, 2016

Yes sure, here's the code of the export_graph/2 function:

  def export_graph(graph, file \\ "priv/graph.txt") do
    n = :graph.num_of_vertices(graph)
    m = :graph.num_of_edges(graph)
    {:graph, t, _} = graph
    d = "d"
    first_line = ~s(#{n} #{m} #{t} #{d})
    data =
      :graph.edges_with_weights(graph) |>
        Enum.map_join("\n", fn(x) -> {{foo, bar}, w} = x ;
        "#{foo} #{bar} #{w}" end)
    content = """
    #{first_line}
    #{data}
    """
     IO.puts("Graph contains #{n} vertices, #{m} edges and is #{t}.")
     IO.inspect content
     File.write(file, content)
  end

Most of my functions are wrappers around yours and return the graph (which is stored as a state in the GenServer) so I can pipeline them with the |> (pipe) operator

iex(3)⋅❯ Uwotm8.add_user("foo")
{:graph, :directed, {:digraph, 290855, 294953, 299050, true}}
iex(4)⋅❯ Uwotm8.add_user("bar")
{:graph, :directed, {:digraph, 290855, 294953, 299050, true}}
iex(5)⋅❯ Uwotm8.add_user("baz")
{:graph, :directed, {:digraph, 290855, 294953, 299050, true}}
iex(6)⋅❯ Uwotm8.add_edge("foo", "bar", 20)
{:graph, :directed, {:digraph, 290855, 294953, 299050, true}}
iex(7)⋅❯ Uwotm8.add_edge("bar", "foo", 20)
{:graph, :directed, {:digraph, 290855, 294953, 299050, true}}
iex(8)⋅❯ Uwotm8.add_edge("bar", "baz", 80)
{:graph, :directed, {:digraph, 290855, 294953, 299050, true}}
iex(9)⋅❯ Uwotm8.print_graph
:ok
[{From, [{To, Weight}]}]
========================
iex(10)⋅❯ [{<<"bar">>,[{<<"foo">>,20},{<<"baz">>,80}]},
 {<<"baz">>,[]},
 {<<"foo">>,[{<<"bar">>,20}]}]
iex(10)⋅❯ Uwotm8.Worker.export_graph {:graph, :directed, {:digraph, 290855, 294953, 299050, true}}
Graph contains 3 vertices, 3 edges and is directed.
"3 3 directed d\nbar foo 20\nfoo bar 20\nbar baz 80\n"
:ok

Then the file looks like :

uniaika 17:53 ~/code/Elixir/POC/uwotm8 ❯❯ cat priv/graph.txt
3 3 directed d
bar foo 20
foo bar 20
bar baz 80

After a few corrections in the code, the error now looks like

iex(36)⋅❯ :graph.from_file('priv/graph.txt')
** (MatchError) no match of right hand side value: {:error, {:fread, :integer}}
             :graph.read_edge/2
             :graph.init_edges/6
             :graph.from_file/3
    (stdlib) :digraph.del_edge/2

@aggelgian
Copy link
Owner

@Annwenn

Hello!
Sorry for taking so long to address issue; I was really busy the last few weeks.

The problem is that graph:from_file/1 assumes that each vertex is an integer from 0 to N-1, where N is the number of vertices. Therefore, an exception occurs when trying to import vertices that are strings.

To facilitate importing / exporting graphs I just added two new MFAs:

  • graph:export/3
    • The 1st argument is the graph.
    • The 2nd argument is the file.
    • The 3rd argument is a function that shows how to dump each vertex to a string.
  • graph:import/2
    • The 1st argument is the file.
    • The 2nd argument is a function that shows how to parse a vertex from a string.

I've also added your use case an example in import_export.erl.

A possibly better example of importing a graph can be found in a_star_demo.

@ghost
Copy link
Author

ghost commented Mar 19, 2016

Woah, thank you!
Your library will come handy for my IRC bot. It has a Web of Trust module and I use the graph module to build relationships between users.
(here's the interesting part of the project.)

@aggelgian
Copy link
Owner

@Annwenn
I'm happy to hear that it will be useful for you. I'll check out your project ;)
If you need any other functionality, just tell me!

@ghost
Copy link
Author

ghost commented Mar 21, 2016

@aggelgian
Sure, thanks a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant