MCPcopy Create free account
hub / github.com/RolnickLab/climart / forward

Method forward

climart/models/GraphNet/graph_network_block.py:136–205  ·  view source on GitHub ↗
(self, graph: GraphComponentToTensor)

Source from the content-addressed store, hash-verified

134 # batch_size = edge_feats_old.shape[0]
135
136 def forward(self, graph: GraphComponentToTensor) -> GraphComponentToTensor:
137 if self.use_edge_features:
138 edge_feats_old = graph[EDGES] # edge_feats_old have shape (b, #edges, #edge-feats)
139 if edge_feats_old.shape[gn_constants.SPATIAL_DIM] != self._n_edges:
140 raise ValueError(f"Edge features imply {edge_feats_old.shape[gn_constants.SPATIAL_DIM]} edges, "
141 f"while sender and receiver lists imply {self._n_edges} edges.")
142 node_feats_old = graph[NODES] # node_feats_old have shape (b, #nodes, #node-feats)
143 n_nodes = node_feats_old.shape[gn_constants.SPATIAL_DIM]
144 if self.use_global_features:
145 global_feats_old = graph[GLOBALS] # global_feats_old have shape (b, #global-feats)
146 batch_size, n_glob_feats = global_feats_old.shape
147
148 out = {c: None for c in self.components}
149
150 # ----------------------- Update edges
151 # self.senders and self.receivers are a sequence of indices with #edges elements
152 sender_feats = node_feats_old.index_select(index=self._senders, dim=gn_constants.SPATIAL_DIM)
153 receiver_feats = node_feats_old.index_select(index=self._receivers, dim=gn_constants.SPATIAL_DIM)
154
155 # print('E:', edge_feats_old.shape, 'V:', node_feats_old.shape, 'U:', global_feats_old.shape)
156 # print('Senders', sender_feats.shape, 'Recvs', receiver_feats.shape, global_feats_unsqueezed.shape)
157 mlp_input_e = torch.cat([
158 edge_feats_old, # (b, #edges, #edge-feats)
159 sender_feats, # (b, #edges, #node-feats)
160 receiver_feats, # (b, #edges, #node-feats)
161 repeat(global_feats_old, 'b g -> b e g', e=self._n_edges) # (1, self.n_edges, 1) (b, 1, #global-feats)
162 ], dim=-1)
163
164 mlp_input_e = rearrange(mlp_input_e, 'b e d1 -> (b e) d1')
165
166 out[EDGES] = self.update_funcs[EDGES](mlp_input_e)
167 out[EDGES] = rearrange(out[EDGES], '(b e) d2 -> b e d2', b=batch_size, e=self._n_edges)
168 if self.residual[EDGES]:
169 out[EDGES] += edge_feats_old
170 # ----------------------- Update nodes
171 aggregated_edge_feats_for_node = self.aggregator_funcs[AggregationTypes.AGG_E_TO_N](
172 out[EDGES], index=self._receivers
173 )
174
175 mlp_input_n = torch.cat([
176 aggregated_edge_feats_for_node, # (b, #nodes, #edge-feats)
177 node_feats_old, # (b, #nodes, #node-feats)
178 repeat(global_feats_old, 'b g -> b n g', n=n_nodes) # (b, #nodes, #global-feats)
179 ], dim=-1)
180 mlp_input_n = rearrange(mlp_input_n, 'b n d1 -> (b n) d1')
181
182 # print('Agg E:', aggregated_edge_feats_for_node.shape, 'V:', node_feats_old.shape, mlp_input_n.shape)
183 out[NODES] = self.update_funcs[NODES](mlp_input_n)
184 out[NODES] = rearrange(out[NODES], '(b n) d2 -> b n d2', b=batch_size, n=n_nodes)
185 if self.residual[NODES]:
186 out[NODES] += node_feats_old
187 # ----------------------- Update global features
188 aggregated_edge_feats_for_global = self.aggregator_funcs[AggregationTypes.AGG_E_TO_U](out[EDGES])
189 aggregated_node_feats_for_global = self.aggregator_funcs[AggregationTypes.AGG_N_TO_U](out[NODES])
190 # print('Agg EU:', aggregated_edge_feats_for_global.shape, 'VU:', aggregated_node_feats_for_global.shape)
191
192 mlp_input_u = torch.cat([
193 aggregated_edge_feats_for_global, # (b, #edge-feats)

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected