{"action":"created","issue":{"url":"https://api.github.com/repos/zzhang-cn/dgl/issues/8","repository_url":"https://api.github.com/repos/zzhang-cn/dgl","labels_url":"https://api.github.com/repos/zzhang-cn/dgl/issues/8/labels{/name}","comments_url":"https://api.github.com/repos/zzhang-cn/dgl/issues/8/comments","events_url":"https://api.github.com/repos/zzhang-cn/dgl/issues/8/events","html_url":"https://github.com/zzhang-cn/dgl/issues/8","id":332333864,"node_id":"MDU6SXNzdWUzMzIzMzM4NjQ=","number":8,"title":"About message and update function","user":{"login":"jermainewang","id":4057701,"node_id":"MDQ6VXNlcjQwNTc3MDE=","avatar_url":"https://avatars1.githubusercontent.com/u/4057701?v=4","gravatar_id":"","url":"https://api.github.com/users/jermainewang","html_url":"https://github.com/jermainewang","followers_url":"https://api.github.com/users/jermainewang/followers","following_url":"https://api.github.com/users/jermainewang/following{/other_user}","gists_url":"https://api.github.com/users/jermainewang/gists{/gist_id}","starred_url":"https://api.github.com/users/jermainewang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jermainewang/subscriptions","organizations_url":"https://api.github.com/users/jermainewang/orgs","repos_url":"https://api.github.com/users/jermainewang/repos","events_url":"https://api.github.com/users/jermainewang/events{/privacy}","received_events_url":"https://api.github.com/users/jermainewang/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2018-06-14T10:00:35Z","updated_at":"2018-06-14T21:13:25Z","closed_at":null,"author_association":"COLLABORATOR","body":"I'm thinking about how to make the API cleaner. Basically, we only have two types of computations:\r\n* **Computation on edge**. It takes the states of the src and dst nodes, and the old states of the edge and returns the new states of the edges. The signature can be summarized as:\r\n  `(node_states, node_states, edge_states) -> edge_states`\r\n* **Computation on node**. It takes the states of the in-coming edges and the old node states to compute the new node states. The signature can be summarized as:\r\n  `(list[edge_states], node_states) -> node_states`\r\n\r\nIn networkx, all node and edge states are dictionaries (you can use `type(g.nodes[node])` to verify this).\r\n\r\nA message function can be viewed as a special edge computation as follows:\r\n```python\r\ndef edge_func(src_node_states, dst_node_states, edge_states):\r\n  msg = ...  # compute message\r\n  new_edge_states = edge_states\r\n  new_edge_states['msg'] = msg\r\n  return new_edge_states\r\n```\r\nBecause this pattern is so common, we can let user only returns the `msg` and handle the edge state update by ourselves:\r\n```python\r\ndef mfunc(node_states, edge_states):\r\n  #User-defined\r\n  msg = ... # compute message\r\n  return msg\r\ndef mfunc_wrapper(src_node_states, dst_node_states, edge_states):\r\n  #System wrapper\r\n  new_edge_states = edge_states\r\n  new_edge_states['msg'] = mfunc(src_node_states, edge_states)\r\n  return new_edge_states\r\n```\r\n\r\nSimilarly, we can wrap the update function as node function as well:\r\n```python\r\ndef ufunc(msgs, edge_states, node_states):\r\n  #User-defined\r\n  new_node_states = ...  # compute new node state\r\n  return new_node_states\r\ndef ufunc_wrapper(edge_states, node_states):\r\n  #System wrapper\r\n  msgs = [es['msg'] for es in edge_states]\r\n  new_node_states = ufunc(msgs, edge_states, node_states)\r\n  return new_node_states\r\n```\r\n\r\nI want to know your opinions about this implementation. Using this idea, we might have two basic APIs: `register_edge_func` and `register_node_func`. And have `register_message_func` and `register_update_func` be two APIs that simply wrap the above two."},"comment":{"url":"https://api.github.com/repos/zzhang-cn/dgl/issues/comments/397440190","html_url":"https://github.com/zzhang-cn/dgl/issues/8#issuecomment-397440190","issue_url":"https://api.github.com/repos/zzhang-cn/dgl/issues/8","id":397440190,"node_id":"MDEyOklzc3VlQ29tbWVudDM5NzQ0MDE5MA==","user":{"login":"jermainewang","id":4057701,"node_id":"MDQ6VXNlcjQwNTc3MDE=","avatar_url":"https://avatars1.githubusercontent.com/u/4057701?v=4","gravatar_id":"","url":"https://api.github.com/users/jermainewang","html_url":"https://github.com/jermainewang","followers_url":"https://api.github.com/users/jermainewang/followers","following_url":"https://api.github.com/users/jermainewang/following{/other_user}","gists_url":"https://api.github.com/users/jermainewang/gists{/gist_id}","starred_url":"https://api.github.com/users/jermainewang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jermainewang/subscriptions","organizations_url":"https://api.github.com/users/jermainewang/orgs","repos_url":"https://api.github.com/users/jermainewang/repos","events_url":"https://api.github.com/users/jermainewang/events{/privacy}","received_events_url":"https://api.github.com/users/jermainewang/received_events","type":"User","site_admin":false},"created_at":"2018-06-14T21:13:25Z","updated_at":"2018-06-14T21:13:25Z","author_association":"COLLABORATOR","body":"I'm thinking about having both, but `register_message_func` is implemented using `register_edge_func`, so in the system side, we still only see two kinds of computation.\r\n\r\nIf the user's model is like GCN style:\r\n```\r\n# on edge u->v\r\nmsg = f1(u)\r\nv' = f2(list[msg], v)\r\n```\r\n, then he only needs to `regsiter_message_func(f1)` and `register_update_func(f2)`.\r\n\r\nIf the user's model is like:\r\n```\r\n# on edge u->v\r\nmsg = f1(u, e_uv)\r\nv' = f2(list[msg], list[e_uv], v)\r\ne_uv' = f3(u, v, e_uv)\r\n```\r\n, then he needs to `register_message_func(f1)`, `register_update_func(f2)` and `register_edge_func(f3)`."}}
{"actor":{"display_login":"jermainewang"}}