# # Copyright (C) Stanislaw Adaszewski, 2020 # License: GPLv3 # from icosagon.trainprep import TrainValTest, \ train_val_test_split_edges, \ get_edges_and_degrees, \ prepare_adj_mat, \ prepare_relation_type, \ prep_rel_one_node_type, \ prep_rel_two_node_types_sym, \ prep_rel_two_node_types_asym import torch import pytest import numpy as np from itertools import chain from icosagon.data import RelationType import icosagon.trainprep def test_train_val_test_split_edges_01(): edges = torch.randint(0, 10, (10, 2)) with pytest.raises(ValueError): _ = train_val_test_split_edges(edges, TrainValTest(.5, .5, .5)) with pytest.raises(ValueError): _ = train_val_test_split_edges(edges, TrainValTest(.2, .2, .2)) with pytest.raises(ValueError): _ = train_val_test_split_edges(edges, None) with pytest.raises(ValueError): _ = train_val_test_split_edges(edges, (.8, .1, .1)) with pytest.raises(ValueError): _ = train_val_test_split_edges(np.random.randint(0, 10, (10, 2)), TrainValTest(.8, .1, .1)) with pytest.raises(ValueError): _ = train_val_test_split_edges(torch.randint(0, 10, (10, 3)), TrainValTest(.8, .1, .1)) with pytest.raises(ValueError): _ = train_val_test_split_edges(torch.randint(0, 10, (10, 2, 1)), TrainValTest(.8, .1, .1)) with pytest.raises(ValueError): _ = train_val_test_split_edges(None, TrainValTest(.8, .2, .2)) res = train_val_test_split_edges(edges, TrainValTest(.8, .1, .1)) assert res.train.shape == (8, 2) and res.val.shape == (1, 2) and \ res.test.shape == (1, 2) res = train_val_test_split_edges(edges, TrainValTest(.8, .0, .2)) assert res.train.shape == (8, 2) and res.val.shape == (0, 2) and \ res.test.shape == (2, 2) res = train_val_test_split_edges(edges, TrainValTest(.8, .2, .0)) assert res.train.shape == (8, 2) and res.val.shape == (2, 2) and \ res.test.shape == (0, 2) res = train_val_test_split_edges(edges, TrainValTest(.0, .5, .5)) assert res.train.shape == (0, 2) and res.val.shape == (5, 2) and \ res.test.shape == (5, 2) res = train_val_test_split_edges(edges, TrainValTest(.0, .0, 1.)) assert res.train.shape == (0, 2) and res.val.shape == (0, 2) and \ res.test.shape == (10, 2) res = train_val_test_split_edges(edges, TrainValTest(.0, 1., .0)) assert res.train.shape == (0, 2) and res.val.shape == (10, 2) and \ res.test.shape == (0, 2) def test_train_val_test_split_edges_02(): edges = torch.randint(0, 30, (30, 2)) ratios = TrainValTest(.8, .1, .1) res = train_val_test_split_edges(edges, ratios) edges = [ tuple(a) for a in edges ] res = [ tuple(a) for a in chain(res.train, res.val, res.test) ] assert all([ a in edges for a in res ]) def test_get_edges_and_degrees_01(): adj_mat_dense = (torch.rand((10, 10)) > .5) adj_mat_sparse = adj_mat_dense.to_sparse() edges_dense, degrees_dense = get_edges_and_degrees(adj_mat_dense) edges_sparse, degrees_sparse = get_edges_and_degrees(adj_mat_sparse) assert torch.all(degrees_dense == degrees_sparse) edges_dense = [ tuple(a) for a in edges_dense ] edges_sparse = [ tuple(a) for a in edges_dense ] assert len(edges_dense) == len(edges_sparse) assert all([ a in edges_dense for a in edges_sparse ]) assert all([ a in edges_sparse for a in edges_dense ]) # assert torch.all(edges_dense == edges_sparse) def test_prepare_adj_mat_01(): adj_mat = (torch.rand((10, 10)) > .5) adj_mat = adj_mat.to_sparse() ratios = TrainValTest(.8, .1, .1) _ = prepare_adj_mat(adj_mat, ratios) def test_prepare_adj_mat_02(): adj_mat = (torch.rand((10, 10)) > .5) adj_mat = adj_mat.to_sparse() ratios = TrainValTest(.8, .1, .1) (adj_mat_train, edges_pos, edges_neg) = prepare_adj_mat(adj_mat, ratios) assert isinstance(adj_mat_train, torch.Tensor) assert adj_mat_train.is_sparse assert adj_mat_train.shape == adj_mat.shape assert adj_mat_train.dtype == adj_mat.dtype assert isinstance(edges_pos, TrainValTest) assert isinstance(edges_neg, TrainValTest) for a in ['train', 'val', 'test']: for b in [edges_pos, edges_neg]: edges = getattr(b, a) assert isinstance(edges, torch.Tensor) assert len(edges.shape) == 2 assert edges.shape[1] == 2 def test_prepare_relation_type_01(): adj_mat = (torch.rand((10, 10)) > .5) r = RelationType('Test', 0, 0, adj_mat, True) ratios = TrainValTest(.8, .1, .1) _ = prepare_relation_type(r, ratios, False) def test_prep_rel_one_node_type_01(): adj_mat = torch.zeros(100) perm = torch.randperm(100) adj_mat[perm[:10]] = 1 adj_mat = adj_mat.view(10, 10) rel = RelationType('Dummy Relation', 0, 0, adj_mat, None) ratios = TrainValTest(.8, .1, .1) prep_rel = prep_rel_one_node_type(rel, ratios) assert prep_rel.name == rel.name assert prep_rel.node_type_row == rel.node_type_row assert prep_rel.node_type_column == rel.node_type_column assert prep_rel.adjacency_matrix.shape == rel.adjacency_matrix.shape assert prep_rel.adjacency_matrix_backward is None assert len(prep_rel.edges_pos.train) == 8 assert len(prep_rel.edges_pos.val) == 1 assert len(prep_rel.edges_pos.test) == 1 assert len(prep_rel.edges_neg.train) == 8 assert len(prep_rel.edges_neg.val) == 1 assert len(prep_rel.edges_neg.test) == 1 assert len(prep_rel.edges_back_pos.train) == 0 assert len(prep_rel.edges_back_pos.val) == 0 assert len(prep_rel.edges_back_pos.test) == 0 assert len(prep_rel.edges_back_neg.train) == 0 assert len(prep_rel.edges_back_neg.val) == 0 assert len(prep_rel.edges_back_neg.test) == 0 def test_prep_rel_two_node_types_sym_01(): adj_mat = torch.zeros(200) perm = torch.randperm(100) adj_mat[perm[:10]] = 1 adj_mat = adj_mat.view(10, 20) rel = RelationType('Dummy Relation', 0, 1, adj_mat, None) ratios = TrainValTest(.8, .1, .1) prep_rel = prep_rel_two_node_types_sym(rel, ratios) assert prep_rel.name == rel.name assert prep_rel.node_type_row == rel.node_type_row assert prep_rel.node_type_column == rel.node_type_column assert prep_rel.adjacency_matrix.shape == rel.adjacency_matrix.shape assert prep_rel.adjacency_matrix_backward.shape == (20, 10) assert len(prep_rel.edges_pos.train) == 8 assert len(prep_rel.edges_pos.val) == 1 assert len(prep_rel.edges_pos.test) == 1 assert len(prep_rel.edges_neg.train) == 8 assert len(prep_rel.edges_neg.val) == 1 assert len(prep_rel.edges_neg.test) == 1 assert len(prep_rel.edges_back_pos.train) == 0 assert len(prep_rel.edges_back_pos.val) == 0 assert len(prep_rel.edges_back_pos.test) == 0 assert len(prep_rel.edges_back_neg.train) == 0 assert len(prep_rel.edges_back_neg.val) == 0 assert len(prep_rel.edges_back_neg.test) == 0 def test_prep_rel_two_node_types_asym_01(): adj_mat = torch.zeros(200) perm = torch.randperm(100) adj_mat[perm[:10]] = 1 adj_mat = adj_mat.view(10, 20) adj_mat_back = torch.zeros(200) perm = torch.randperm(100) adj_mat_back[perm[:10]] = 1 adj_mat_back = adj_mat_back.view(20, 10) rel = RelationType('Dummy Relation', 0, 1, adj_mat, adj_mat_back) ratios = TrainValTest(.8, .1, .1) prep_rel = prep_rel_two_node_types_asym(rel, ratios) assert prep_rel.name == rel.name assert prep_rel.node_type_row == rel.node_type_row assert prep_rel.node_type_column == rel.node_type_column assert prep_rel.adjacency_matrix.shape == rel.adjacency_matrix.shape assert prep_rel.adjacency_matrix_backward.shape == rel.adjacency_matrix_backward.shape assert len(prep_rel.edges_pos.train) == 8 assert len(prep_rel.edges_pos.val) == 1 assert len(prep_rel.edges_pos.test) == 1 assert len(prep_rel.edges_neg.train) == 8 assert len(prep_rel.edges_neg.val) == 1 assert len(prep_rel.edges_neg.test) == 1 assert len(prep_rel.edges_back_pos.train) == 8 assert len(prep_rel.edges_back_pos.val) == 1 assert len(prep_rel.edges_back_pos.test) == 1 assert len(prep_rel.edges_back_neg.train) == 8 assert len(prep_rel.edges_back_neg.val) == 1 assert len(prep_rel.edges_back_neg.test) == 1 def test_prepare_relation_type_01(): with pytest.raises(ValueError): prepare_relation_type(None, None, True) adj_mat = torch.rand(10, 10).round() rel = RelationType('Dummy Relation', 0, 0, adj_mat, None) with pytest.raises(ValueError): prepare_relation_type(rel, None, True) ratios = TrainValTest(.8, .1, .1) with pytest.raises(ValueError): prepare_relation_type(None, ratios, True) _ = prepare_relation_type(rel, ratios, True) def test_prepare_relation_type_02(monkeypatch): a = 0 b = 0 c = 0 def fake_prep_rel_one_node_type(*args, **kwargs): nonlocal a a += 1 def fake_prep_rel_two_node_types_sym(*args, **kwargs): nonlocal b b += 1 def fake_prep_rel_two_node_types_asym(*args, **kwargs): nonlocal c c += 1 monkeypatch.setattr(icosagon.trainprep, 'prep_rel_one_node_type', fake_prep_rel_one_node_type) monkeypatch.setattr(icosagon.trainprep, 'prep_rel_two_node_types_sym', fake_prep_rel_two_node_types_sym) monkeypatch.setattr(icosagon.trainprep, 'prep_rel_two_node_types_asym', fake_prep_rel_two_node_types_asym) ratios = TrainValTest(.8, .1, .1) rel = RelationType('Dummy Relation', 0, 0, None, None) prepare_relation_type(rel, ratios, False) assert a == 1 rel = RelationType('Dummy Relation', 0, 0, None, None) prepare_relation_type(rel, ratios, True) assert a == 2 rel = RelationType('Dummy Relation', 0, 1, None, None) prepare_relation_type(rel, ratios, True) assert b == 1 rel = RelationType('Dummy Relation', 0, 1, None, None) prepare_relation_type(rel, ratios, False) assert c == 1 assert a == 2 and b == 1 and c == 1 # def prepare_relation(r, ratios): # adj_mat = r.adjacency_matrix # adj_mat_train, edges_pos, edges_neg = prepare_adj_mat(adj_mat) # # if r.node_type_row == r.node_type_column: # adj_mat_train = norm_adj_mat_one_node_type(adj_mat_train) # else: # adj_mat_train = norm_adj_mat_two_node_types(adj_mat_train) # # return PreparedRelation(r.name, r.node_type_row, r.node_type_column, # adj_mat_train, edges_pos, edges_neg)