google-deepmind / graph_nets

Build Graph Nets in Tensorflow
https://arxiv.org/abs/1806.01261
Apache License 2.0
5.34k stars 783 forks source link

networkxs_to_graphs_tuple should handle graphs with different keys. #133

Closed Joshuaalbert closed 3 years ago

Joshuaalbert commented 3 years ago

When you do networkxs_to_graphs_tuple(graphs) where graphs is a list of networkx graphs and some don't have edges, then it will raise an error:

File "/home/albert/miniconda3/envs/tf_py/lib/python3.8/site-packages/graph_nets/utils_np.py", line 83, in _check_valid_sets_of_keys
    raise ValueError(
ValueError: Different set of keys found when iterating over data dictionaries ({'n_node', 'n_edge', 'nodes', 'receivers', 'senders', 'edges'} vs {'n_node', 'n_edge', 'nodes', 'receivers', 'senders'})

But there are cases when these graphs which lack edges should be transparently treated as a graph with empty edge attribute. E.g. if you're using nx functionality to remove nodes and this results in a completely disconnected graph. This should not result in networkxs_to_graphs_tuple failing.

alvarosg commented 3 years ago

Thank you for the message and the nice catch!

I understand that this is a problem because it is not even possible to store the specification of the edge features in a networkx graph that does not have edges.

Our intent was to make sure that the user always has a way to specify shapes and types of edges and nodes, even for graphs that do no have any edges or any nodes, so there is no room for misunderstandings. This is one of the reasons why we prefer working with data_dicts, or building GraphsTuples directly, and the networkx methods are only intended as helper methods, but we expect that in some of the most sophisticated use cases, users may have to do the conversion from networkx to data dict manually.

Specifically, networkxs_to_graphs_tuple is just a light wrapper that first converts to a list of data_dicts (which have no problem in specifying empty arrays with trailing shapes for graphs with 0 nodes or 0 edges), and then transform those into a graphs tuple using data_dicts_to_graphs_tuple. We provided the node_shape_hint and edge_shape_hint attributes in networkxs_to_graphs_tuple, so the networkx graph can be converted into a data_dict with fully specified shapes even for graphs in the batch that have 0 edges/nodes, as well as a the data_type_hint for the type.

I think passing this argument edge_shape_hint(while a bit annoying) should make it work for your use case. Could you confirm?

It should be possible to implement the behavior that you are suggesting, but we slightly lean on preferring the user to specify it explicitly, in the cases where the data structure does not support it.

alvarosg commented 3 years ago

(closing due to inactivity)