def existence_accuracy(target, output, use_nodes=True, use_edges=True): if not use_nodes and not use_edges: raise ValueError("Nodes or edges (or both) must be used") tdds = utils_np.graphs_tuple_to_data_dicts(target) odds = utils_np.graphs_tuple_to_data_dicts(output) cs = [] ss = [] for td, od in zip(tdds, odds): nodes_to_predict = td["nodes"][:, 0] == 0 xn = np.argmax(td["nodes"][:, 1:], axis=-1) xn = xn[nodes_to_predict] yn = np.argmax(softmax(od["nodes"][:, 1:], axis=1), axis=-1) yn = yn[nodes_to_predict] edges_to_predict = td["edges"][:, 0] == 0 xe = np.argmax(td["edges"][:, 1:], axis=-1) xe = xe[edges_to_predict] ye = np.argmax(softmax(od["edges"][:, 1:], axis=1), axis=-1) ye = ye[edges_to_predict] c = [] if use_nodes: c.append(xn == yn) if use_edges: c.append(xe == ye) c = np.concatenate(c, axis=0) s = np.all(c) cs.append(c) ss.append(s) correct = np.mean(np.concatenate(cs, axis=0)) solved = np.mean(np.stack(ss)) return correct, solved
def _compute_metrics(self, target, output): """Calculate model accuracy, precision, recall. Returns list with metrics Args: target: A List of `graphs.GraphsTuple` that contains the target graph. output: A List of `graphs.GraphsTuple` that contains the output graph. Returns: metrics: A List with accuracy, recall and precision scores Raises: ValueError: Nodes or edges (or both) must be used """ true, preds = [], [] # Unzip list of graphs for t, o in zip(target, output): d_t = utils_np.graphs_tuple_to_data_dicts(t) d_o = utils_np.graphs_tuple_to_data_dicts(o) # Obtain target and prediction for every graph for td, od in zip(d_t, d_o): true.append(np.argmax(td['globals'])) preds.append(np.argmax(od['globals'])) metrics = [accuracy_score(true, preds), recall_score(true, preds), precision_score(true, preds)] return metrics, classification_report(true, preds, output_dict = True)
def compute_jaccard_accuracy(target, output, use_nodes=True, use_edges=False): if not use_nodes and not use_edges: raise ValueError("Nodes or edges (or both) must be used") tdds = utils_np.graphs_tuple_to_data_dicts(target) odds = utils_np.graphs_tuple_to_data_dicts(output) cs = [] ss = [] for td, od in zip(tdds, odds): xn = np.argmax(td["nodes"], axis=-1) yn = np.argmax(od["nodes"], axis=-1) xe = np.argmax(td["edges"], axis=-1) ye = np.argmax(od["edges"], axis=-1) c = [] solved_pixels = [] if use_nodes: c.append(float(1 - jaccard(xn, yn))) solved_pixels.append(xn == yn) if use_edges: c.append(float(1 - jaccard(xe, ye))) solved_pixels.append(xe == ye) "c = np.concatenate(c, axis=0)" s = np.all(solved_pixels) cs.append(c) ss.append(s) mean_koeficient = np.mean(cs) solved = np.mean(np.stack(ss)) return mean_koeficient, solved
def save_predicted_graphs(path, inputs, outputs, accurately=False): """ Saves the predicted graphs to a jsonl file :param path: The path where the file shall be saved :param inputs: Training input graphs :param outputs: Training output graphs :param accurately: Whether to save the scores or just whether the result was one or zero """ inputs_dict = utils_np.graphs_tuple_to_data_dicts(inputs) outputs_dict = utils_np.graphs_tuple_to_data_dicts(outputs) mode = 'a' if os.path.exists(path) else 'w' with open(path, mode) as output: for (in_, out_) in zip(inputs_dict, outputs_dict): if not accurately: out_dict = {"nodes": [[i.tolist(), int(np.argmax(o))] for (i, o) in zip(in_["nodes"], out_["nodes"])], "edges": [[i[0], int(np.argmax(o))] for (i, o) in zip(in_["edges"], out_["edges"])], "globals": [float(g) for g in in_["globals"]], "senders": in_["senders"].tolist(), "receivers": in_["receivers"].tolist()} else: out_dict = {"nodes": [[i.tolist(), o[1]] for (i, o) in zip(in_["nodes"], out_["nodes"])], "edges": [[i[0], o[1]] for (i, o) in zip(in_["edges"], out_["edges"])], "globals": [float(g) for g in in_["globals"]], "senders": in_["senders"].tolist(), "receivers": in_["receivers"].tolist()} print(json.dumps(out_dict), file=output)
def compute_accuracy_ratio(target, output, is_categorical=False): """ Computes the accuracy ratio on nodes and edges, and also on the whole correctly predicted graph itself :param target: The target graphs :param output: The output graphs :param is_categorical: Whether the output is categorical (feature size = 1) or not :return: The ratio of correctly predicted nodes and edges, and the correctly predicted full graphs """ target_dicts = utils_np.graphs_tuple_to_data_dicts(target) output_dicts = utils_np.graphs_tuple_to_data_dicts(output) solved = 0 corrects = [] for target_dict, output_dict in zip(target_dicts, output_dicts): solved_nodes = False solved_edges = False num_elements = target_dict["nodes"].shape[0] num_edges = target_dict["edges"].shape[0] correct_nodes = 0 correct_edges = 0 for target_nodes, output_nodes in zip(target_dict["nodes"], output_dict["nodes"]): if not is_categorical and (target_nodes[0] + 0.5 > output_nodes[0] >= target_nodes[0] - 0.5) and \ ((target_nodes[1] == 1. and output_nodes[1] >= 0.5) or (target_nodes[1] == 0. and output_nodes[1] < 0.5)): correct_nodes += 1 elif is_categorical and ( (target_nodes[0] == 1. and output_nodes[0] >= 0.5) or (target_nodes[0] == 0. and output_nodes[0] < 0.5)): correct_nodes += 1 if correct_nodes == num_elements: solved_nodes = True for target_edges, output_edges in zip(target_dict["edges"], output_dict["edges"]): if not is_categorical and (target_edges[0] + 0.5 > output_edges[0] >= target_edges[0] - 0.5) and \ ((target_edges[1] == 1. and output_edges[1] >= 0.5) or (target_edges[1] == 0. and output_edges[1] < 0.5)): correct_edges += 1 elif is_categorical and ( (target_edges[0] == 1. and output_edges[0] >= 0.5) or (target_edges[0] == 0. and output_edges[0] < 0.5)): correct_edges += 1 if correct_edges == num_edges: solved_edges = True if solved_edges and solved_nodes: solved += 1 corrects.append((correct_nodes, num_elements)) corrects.append((correct_edges, num_edges)) corr_, all_ = 0, 0 for c in corrects: corr_ += c[0] all_ += c[1] return corr_ / all_, solved / len(target)
def compute_accuracy_class(target, output): if(TARGET_MODE=='globalstate'): tds = utils_np.graphs_tuple_to_data_dicts(target) solved = [ int(np.argmax(t["globals"]) == np.argmax(o)) for t,o in zip(tds,output[0]) ] if(TARGET_MODE=='activesite'): tds = utils_np.graphs_tuple_to_data_dicts(target) ods = utils_np.graphs_tuple_to_data_dicts(output) solved = [ int(np.argmax(t["nodes"]) == np.argmax(o)) for t,o in zip(tds,ods) ] return sum(solved), len(solved)
def eval_output(target, output): tdds = utils_np.graphs_tuple_to_data_dicts(target) odds = utils_np.graphs_tuple_to_data_dicts(output) test_target = [] test_pred = [] for td, od in zip(tdds, odds): test_target.append(td['edges']) test_pred.append(od['edges']) test_target = np.concatenate(test_target, axis=0) test_pred = np.concatenate(test_pred, axis=0) return test_pred, test_target
def graphs_tuples_to_darwin_batches(graph_nets): ''' Args: graphs_tuple : GraphTuple from graph_nets Returns: graph : adjacency matrix of the graph, shape = (num_graphs, num_nodes, num_nodes) node_features : Matrix of node features, shape = (num_graphs, num_nodes, num_node_features) ''' adjs_gt = [] node_features = [] adjs_inp = [] data_dicts = utils_np.graphs_tuple_to_data_dicts(graph_nets) for data_dict in data_dicts: nodes = data_dict['nodes'] num_nodes = len(nodes) adj_inp = np.zeros(shape=(num_nodes, num_nodes)) adj_gt = np.zeros(shape=(num_nodes, num_nodes)) senders = data_dict['senders'] receivers = data_dict['receivers'] edges = data_dict['edges'] adj_inp[senders, receivers] = 1.0 adjs_gt[senders, receivers] = edges adjs_inp.append(adj_inp) adjs_gt.append(adj_gt) node_features.append(nodes) return np.array(adjs_gt), np.array(node_features), np.array(adjs_inp)
def eval_output(target, output): """ target, output are graph-tuple from TF-GNN, each of them contains N=batch-size graphs """ tdds = utils_np.graphs_tuple_to_data_dicts(target) odds = utils_np.graphs_tuple_to_data_dicts(output) test_target = [] test_pred = [] for td, od in zip(tdds, odds): test_target.append(np.squeeze(td['edges'])) test_pred.append(np.squeeze(od['edges'])) test_target = np.concatenate(test_target, axis=0) test_pred = np.concatenate(test_pred, axis=0) return test_pred, test_target
def GraphsTupleToQpos(graphs_tuple, mean, std, env_len): edges = utils_np.graphs_tuple_to_data_dicts(graphs_tuple)[0]['edges'] # Initialise an array with all zeros (which will initialise the root position to 0) qpos = [0] * env_len for i in range(int(len(edges) / 2)): # edges are copied over as a mean of edges going both ways # +7 is required to skip over the root pos and quat qpos[i + 7] = (edges[i * 2] + edges[(i * 2) + 1]) / 2 qpos[i + 7] = (qpos[i + 7] * std[i + 7]) + mean[i + 7] return np.array(qpos).flatten()
def compute_accuracy(target, output, use_nodes=True, use_edges=False): """Calculate model accuracy. Returns the number of correctly predicted shortest path nodes and the number of completely solved graphs (100% correct predictions). Args: target: A `graphs.GraphsTuple` that contains the target graph. output: A `graphs.GraphsTuple` that contains the output graph. use_nodes: A `bool` indicator of whether to compute node accuracy or not. use_edges: A `bool` indicator of whether to compute edge accuracy or not. Returns: correct: A `float` fraction of correctly labeled nodes/edges. solved: A `float` fraction of graphs that are completely correctly labeled. Raises: ValueError: Nodes or edges (or both) must be used """ if not use_nodes and not use_edges: raise ValueError("Nodes or edges (or both) must be used") tdds = utils_np.graphs_tuple_to_data_dicts(target) odds = utils_np.graphs_tuple_to_data_dicts(output) cs = [] ss = [] for td, od in zip(tdds, odds): xn = np.argmax(td["nodes"], axis=-1) yn = np.argmax(od["nodes"], axis=-1) xe = np.argmax(td["edges"], axis=-1) ye = np.argmax(od["edges"], axis=-1) c = [] if use_nodes: c.append(xn == yn) if use_edges: c.append(xe == ye) c = np.concatenate(c, axis=0) s = np.all(c) cs.append(c) ss.append(s) correct = np.mean(np.concatenate(cs, axis=0)) solved = np.mean(np.stack(ss)) return correct, solved
def test_graphs_tuple_to_data_dicts(self, none_fields): graphs_tuple = utils_np.data_dicts_to_graphs_tuple(self.graphs_dicts_in) graphs_tuple = graphs_tuple.map(lambda _: None, none_fields) data_dicts = utils_np.graphs_tuple_to_data_dicts(graphs_tuple) for none_field, data_dict in itertools.product(none_fields, data_dicts): self.assertEqual(None, data_dict[none_field]) for expected_data_dict, data_dict in zip(self.graphs_dicts_out, data_dicts): for k, v in expected_data_dict.items(): if k not in none_fields: self.assertAllClose(v, data_dict[k])
def make_feed_dict(val): if isinstance(val, GraphsTuple): graphs_tuple = val else: dicts = [] for graphs_tuple in val: dicts.append( utils_np.graphs_tuple_to_data_dicts(graphs_tuple)[0]) graphs_tuple = utils_np.data_dicts_to_graphs_tuple(dicts) return utils_tf.get_feed_dict(placeholders, graphs_tuple)
def test_get_single_item(self): index = 2 expected = self.graphs_dicts_out[index] graphs = utils_np.data_dicts_to_graphs_tuple(self.graphs_dicts_in) graph = utils_np.get_graph(graphs, index) actual, = utils_np.graphs_tuple_to_data_dicts(graph) for k, v in expected.items(): self.assertAllClose(v, actual[k])
def compute_tp_tn_fp_fn(target, output, types, print_steps=False): """ Calculates the True Positive, True Negative, False Positive and False Negative values in the batch. :param target: The expected values in the graph :param output: The calculated values in the graph :param types: The labels in the graph. (eq. edges0 means the edges with value 0) :param print_steps: Whether to print each batch's report """ results = {type_: {"tp": 0, "tn": 0, "fp": 0, "fn": 0} for type_ in types} tdds = utils_np.graphs_tuple_to_data_dicts(target) odds = utils_np.graphs_tuple_to_data_dicts(output) for td, od in zip(tdds, odds): if print_steps: print("\tprecision\trecall\tf1") for type_ in types: compute_one_tp_tn_fp_fn(results, type_, int(type_[-1]), np.argmax(td[type_[:-1]], axis=-1), np.argmax(od[type_[:-1]], axis=-1), print_steps) return results
def test_get_many_items(self): index = slice(1, 3) expected = self.graphs_dicts_out[index] graphs = utils_np.data_dicts_to_graphs_tuple(self.graphs_dicts_in) graphs2 = utils_np.get_graph(graphs, index) actual = utils_np.graphs_tuple_to_data_dicts(graphs2) for ex, ac in zip(expected, actual): for k, v in ex.items(): self.assertAllClose(v, ac[k])
def predicted_graphs_to_nxs(gnn_output, input_graphs, target_graphs, **kwargs): output_nxs = utils_np.graphs_tuple_to_networkxs(gnn_output) input_dds = utils_np.graphs_tuple_to_data_dicts(input_graphs) target_dds = utils_np.graphs_tuple_to_data_dicts(target_graphs) total_graphs = len(output_nxs) print("total_graphs", total_graphs) graphs = [] for ig in range(total_graphs): input_dd = input_dds[ig] target_dd = target_dds[ig] graph = data_dict_to_nx(input_dd, target_dd, **kwargs) ## update edge features with TF output for edge in graph.edges(): graph.edges[edge]['predict'] = output_nxs[ig].edges[ edge + (0, )]['features'] graphs.append(graph) return graphs
def graphTupleValEqual(self, feat, val0, val1): if isinstance(val0, graphs.GraphsTuple) and isinstance(val1, dict): val0 = utils_np.graphs_tuple_to_data_dicts(val0)[0] else: val0 = utils_np.data_dicts_to_graphs_tuple([val0]) val0 = utils_np.graphs_tuple_to_data_dicts(val0)[0] if isinstance(val1, graphs.GraphsTuple): val1 = utils_np.graphs_tuple_to_data_dicts(val1)[0] else: val1 = utils_np.data_dicts_to_graphs_tuple([val1]) val1 = utils_np.graphs_tuple_to_data_dicts(val1)[0] for k in val0.keys(): sub_feat = feat.features[k] if val0[k] is None or val1[k] is None: val0_none = val0[k] is None or val0[k].shape[0] == 0 val1_none = val1[k] is None or val1[k].shape[0] == 0 if val0_none != val1_none: return False elif not self.isEqualSampleVals(sub_feat, val0[k], val1[k]): return False return True
def compute_accuracy_on_nodes(target, output): """ Computes the accuracy ratio on nodes, and also on the whole correctly predicted graph (its nodes) itself :param target: The target graphs :param output: The output graphs :return: The ratio of correctly predicted nodes and edges, and the correctly predicted full graphs """ tdds = utils_np.graphs_tuple_to_data_dicts(target) odds = utils_np.graphs_tuple_to_data_dicts(output) cs = [] ss = [] for td, od in zip(tdds, odds): xn = np.argmax(td["nodes"], axis=-1) yn = np.argmax(od["nodes"], axis=-1) c = [xn == yn] c = np.concatenate(c, axis=0) s = np.all(c) cs.append(c) ss.append(s) correct = np.mean(np.concatenate(cs, axis=0)) solved = np.mean(np.stack(ss)) return correct, solved
def predict_one_graph(model, checkpoint, json_data, device='/device:GPU:0'): """ Predicts one output for the one given input :param model: The model used for prediction :param checkpoint: The path to the previously saved checkpoint file :param json_data: The dictionary containing the information of one article :param device: Which device to use. GPU:0 is the default. :return: The scored ooutput """ data_dict_list = [ process_line(json_dict=json_data, keep_features=True, existence_as_vector=False) ] inputs = utils_tf.data_dicts_to_graphs_tuple(data_dict_list) outputs = model(inputs, 1) saver = tf.train.Saver() with tf.device(device): with tf.Session() as sess: sess.run(tf.global_variables_initializer()) checkpoint = checkpoint if checkpoint.endswith( ".ckpt") else "{}.ckpt".format(checkpoint) saver.restore(sess, checkpoint) values = sess.run({"inputs": inputs, "outputs": outputs}) inputs_dict = utils_np.graphs_tuple_to_data_dicts(values["inputs"])[0] outputs_dict = utils_np.graphs_tuple_to_data_dicts(values["outputs"][0])[0] return { "nodes": [[[j.decode("utf-8") for j in i], o[1]] for (i, o) in zip(inputs_dict["nodes"], outputs_dict["nodes"])], "edges": [[i[0].decode("utf-8"), o[1]] for (i, o) in zip(inputs_dict["edges"], outputs_dict["edges"])], "globals": [float(g) for g in inputs_dict["globals"]], "senders": inputs_dict["senders"].tolist(), "receivers": inputs_dict["receivers"].tolist() }
def compute_accuracy(target, output): """Calculate model accuracy. Returns the number of correctly predicted links and the number of completely solved list sorts (100% correct predictions). Args: target: A `graphs.GraphsTuple` that contains the target graph. output: A `graphs.GraphsTuple` that contains the output graph. Returns: correct: A `float` fraction of correctly labeled nodes/edges. solved: A `float` fraction of graphs that are completely correctly labeled. """ tdds = utils_np.graphs_tuple_to_data_dicts(target) odds = utils_np.graphs_tuple_to_data_dicts(output) cs = [] ss = [] for td, od in zip(tdds, odds): num_elements = td["nodes"].shape[0] xn = np.argmax(td["nodes"], axis=-1) yn = np.argmax(od["nodes"], axis=-1) xe = np.reshape( np.argmax( np.reshape(td["edges"], (num_elements, num_elements, 2)), axis=-1), (-1,)) ye = np.reshape( np.argmax( np.reshape(od["edges"], (num_elements, num_elements, 2)), axis=-1), (-1,)) c = np.concatenate((xn == yn, xe == ye), axis=0) s = np.all(c) cs.append(c) ss.append(s) correct = np.mean(np.concatenate(cs, axis=0)) solved = np.mean(np.stack(ss)) return correct, solved
def test_getitem_one(self, use_tensor_index): index = 2 expected = self.graphs_dicts_out[index] if use_tensor_index: index = tf.constant(index) graphs_tuple = utils_tf.data_dicts_to_graphs_tuple(self.graphs_dicts_in) graph = utils_tf.get_graph(graphs_tuple, index) graph = utils_tf.nest_to_numpy(graph) actual, = utils_np.graphs_tuple_to_data_dicts(graph) for k, v in expected.items(): self.assertAllClose(v, actual[k]) self.assertEqual(expected["nodes"].shape[0], actual["n_node"]) self.assertEqual(expected["edges"].shape[0], actual["n_edge"])
def test_getitem_one(self): index = 2 expected = self.graphs_dicts_out[index] graphs_tuple = utils_tf.data_dicts_to_graphs_tuple( self.graphs_dicts_in) graph_op = utils_tf.get_graph(graphs_tuple, index) graph_op = utils_tf.make_runnable_in_session(graph_op) with self.test_session() as sess: graph = sess.run(graph_op) actual, = utils_np.graphs_tuple_to_data_dicts(graph) for k, v in expected.items(): self.assertAllClose(v, actual[k]) self.assertEqual(expected["nodes"].shape[0], actual["n_node"]) self.assertEqual(expected["edges"].shape[0], actual["n_edge"])
def test_getitem(self): index = slice(1, 3) expected = self.graphs_dicts_out[index] graphs_tuple = utils_tf.data_dicts_to_graphs_tuple( self.graphs_dicts_in) graphs2_op = utils_tf.get_graph(graphs_tuple, index) graphs2_op = utils_tf.make_runnable_in_session(graphs2_op) with self.test_session() as sess: graphs2 = sess.run(graphs2_op) actual = utils_np.graphs_tuple_to_data_dicts(graphs2) for ex, ac in zip(expected, actual): for k, v in ex.items(): self.assertAllClose(v, ac[k]) self.assertEqual(ex["nodes"].shape[0], ac["n_node"]) self.assertEqual(ex["edges"].shape[0], ac["n_edge"])
def test_getitem(self, use_tensor_slice): index = slice(1, 3) expected = self.graphs_dicts_out[index] if use_tensor_slice: index = slice(tf.constant(index.start), tf.constant(index.stop)) graphs_tuple = utils_tf.data_dicts_to_graphs_tuple(self.graphs_dicts_in) graphs2 = utils_tf.get_graph(graphs_tuple, index) graphs2 = utils_tf.nest_to_numpy(graphs2) actual = utils_np.graphs_tuple_to_data_dicts(graphs2) for ex, ac in zip(expected, actual): for k, v in ex.items(): self.assertAllClose(v, ac[k]) self.assertEqual(ex["nodes"].shape[0], ac["n_node"]) self.assertEqual(ex["edges"].shape[0], ac["n_edge"])
gradients = tape.gradient(loss_tr, graph_network.trainable_variables) optimizer.apply_gradients(zip(gradients, graph_network.trainable_variables)) return outputs_tr, loss_tr def specs_from_tensor(tensor_sample,description_fn=tf.TensorSpec): shape = list(tensor_sample.shape) dtype = tensor_sample.dtype return description_fn(shape=shape, dtype=dtype) # Get some example data that resembles the tensors that will be fed # into update_step(): Input_data, example_target_data = code.next_batch(0) graph_dicts = utils_np.graphs_tuple_to_data_dicts(Input_data) example_input_data = utils_tf.data_dicts_to_graphs_tuple(graph_dicts) # Get the input signature for that function by obtaining the specs input_signature = [ utils_tf.specs_from_graphs_tuple(example_input_data), specs_from_tensor(example_target_data) ] # Compile the update function using the input signature for speedy code. compiled_update_step = tf.function(update_step, input_signature=input_signature) ############# tf_function ################### for echo in range(max_iteration): code.mess_up_order()
ax.plot(x, y_ge, "k--", label="Test/generalization") ax.set_title("Fraction solved across training") ax.set_xlabel("Training iteration") ax.set_ylabel("Fraction examples solved") # Plot graphs and results after each processing step. # The white node is the start, and the black is the end. Other nodes are colored # from red to purple to blue, where red means the model is confident the node is # off the shortest path, blue means the model is confident the node is on the # shortest path, and purplish colors mean the model isn't sure. max_graphs_to_plot = 8 #@param{type:"slider", min:4, max:8, step:1} num_steps_to_plot = 4 #@param{type:"slider", min:1, max:8, step:1} node_size = 120 #@param{type:"slider", min:64, max:2048, step:1} min_c = 0.3 num_graphs = len(raw_graphs) targets = utils_np.graphs_tuple_to_data_dicts(test_values["target"]) step_indices = np.floor( np.linspace(0, num_processing_steps_ge - 1, num_steps_to_plot)).astype(int).tolist() outputs = list( zip(*(utils_np.graphs_tuple_to_data_dicts(test_values["outputs"][i]) for i in step_indices))) h = min(num_graphs, max_graphs_to_plot) w = num_steps_to_plot + 1 fig = plt.figure(101, figsize=(18, h * 3)) fig.clf() ncs = [] for j, (graph, target, output) in enumerate(zip(raw_graphs, targets, outputs)): if j >= h: break
def get_graph_dict(graph_tuple): return utils_np.graphs_tuple_to_data_dicts(graph_tuple)
def copy_graph(graphs_tuple): return utils_np.data_dicts_to_graphs_tuple( utils_np.graphs_tuple_to_data_dicts(graphs_tuple))
# def print_graphs_tuple(graphs_tuple): print("Shapes of `GraphsTuple`'s fields:") print( graphs_tuple.map(lambda x: x if x is None else x.shape, fields=graphs.ALL_FIELDS)) print("\nData contained in `GraphsTuple`'s fields:") print("globals:\n{}".format(graphs_tuple.globals)) print("nodes:\n{}".format(graphs_tuple.nodes)) print("edges:\n{}".format(graphs_tuple.edges)) print("senders:\n{}".format(graphs_tuple.senders)) print("receivers:\n{}".format(graphs_tuple.receivers)) print("n_node:\n{}".format(graphs_tuple.n_node)) print("n_edge:\n{}".format(graphs_tuple.n_edge)) # print_graphs_tuple(graphs_tuple) recovered_data_dict_list = utils_np.graphs_tuple_to_data_dicts(graphs_tuple) # print(recovered_data_dict_list) n_node = 3 senders = [0, 1, 2] receivers = [1, 2, 0] data_dict = {"n_node": n_node, "senders": senders, "receivers": receivers} graphs_tuple = utils_np.data_dicts_to_graphs_tuple([data_dict]) print_graphs_tuple(graphs_tuple) print(graphs_tuple)