from icosagon.input import InputLayer, \ OneHotInputLayer from icosagon.convlayer import DecagonLayer, \ Convolutions from icosagon.data import Data import torch import pytest from icosagon.convolve import DropoutGraphConvActivation from decagon_pytorch.convolve import MultiDGCA import decagon_pytorch.convolve def _make_symmetric(x: torch.Tensor): x = (x + x.transpose(0, 1)) / 2 return x def _symmetric_random(n_rows, n_columns): return _make_symmetric(torch.rand((n_rows, n_columns), dtype=torch.float32).round()) def _some_data_with_interactions(): d = Data() d.add_node_type('Gene', 1000) d.add_node_type('Drug', 100) fam = d.add_relation_family('Drug-Gene', 1, 0, True) fam.add_relation_type('Target', 1, 0, torch.rand((100, 1000), dtype=torch.float32).round()) fam = d.add_relation_family('Gene-Gene', 0, 0, True) fam.add_relation_type('Interaction', 0, 0, _symmetric_random(1000, 1000)) fam = d.add_relation_family('Drug-Drug', 1, 1, True) fam.add_relation_type('Side Effect: Nausea', 1, 1, _symmetric_random(100, 100)) fam.add_relation_type('Side Effect: Infertility', 1, 1, _symmetric_random(100, 100)) fam.add_relation_type('Side Effect: Death', 1, 1, _symmetric_random(100, 100)) return d def test_decagon_layer_01(): d = _some_data_with_interactions() in_layer = InputLayer(d) d_layer = DecagonLayer(in_layer.output_dim, 32, d) seq = torch.nn.Sequential(in_layer, d_layer) _ = seq(None) # dummy call def test_decagon_layer_02(): d = _some_data_with_interactions() in_layer = OneHotInputLayer(d) d_layer = DecagonLayer(in_layer.output_dim, 32, d) seq = torch.nn.Sequential(in_layer, d_layer) _ = seq(None) # dummy call def test_decagon_layer_03(): d = _some_data_with_interactions() in_layer = OneHotInputLayer(d) d_layer = DecagonLayer(in_layer.output_dim, 32, d) assert d_layer.input_dim == [ 1000, 100 ] assert d_layer.output_dim == [ 32, 32 ] assert d_layer.data == d assert d_layer.keep_prob == 1. assert d_layer.rel_activation(0.5) == 0.5 x = torch.tensor([-1, 0, 0.5, 1]) assert (d_layer.layer_activation(x) == torch.nn.functional.relu(x)).all() assert not d_layer.is_sparse assert len(d_layer.next_layer_repr) == 2 for i in range(2): assert len(d_layer.next_layer_repr[i]) == 2 assert isinstance(d_layer.next_layer_repr[i], list) assert isinstance(d_layer.next_layer_repr[i][0], Convolutions) assert isinstance(d_layer.next_layer_repr[i][0].node_type_column, int) assert isinstance(d_layer.next_layer_repr[i][0].convolutions, list) assert all([ isinstance(dgca, DropoutGraphConvActivation) \ for dgca in d_layer.next_layer_repr[i][0].convolutions ]) assert all([ dgca.output_dim == 32 \ for dgca in d_layer.next_layer_repr[i][0].convolutions ]) def test_decagon_layer_04(): # check if it is equivalent to MultiDGCA, as it should be d = Data() d.add_node_type('Dummy', 100) fam = d.add_relation_family('Dummy-Dummy', 0, 0, True) fam.add_relation_type('Dummy Relation', 0, 0, _symmetric_random(100, 100).to_sparse()) in_layer = OneHotInputLayer(d) multi_dgca = MultiDGCA([10], 32, [r.adjacency_matrix for r in fam.relation_types[0, 0]], keep_prob=1., activation=lambda x: x) d_layer = DecagonLayer(in_layer.output_dim, 32, d, keep_prob=1., rel_activation=lambda x: x, layer_activation=lambda x: x) assert isinstance(d_layer.next_layer_repr[0][0].convolutions[0], DropoutGraphConvActivation) weight = d_layer.next_layer_repr[0][0].convolutions[0].graph_conv.weight assert isinstance(weight, torch.Tensor) assert len(multi_dgca.dgca) == 1 assert isinstance(multi_dgca.dgca[0], decagon_pytorch.convolve.DropoutGraphConvActivation) multi_dgca.dgca[0].graph_conv.weight = weight seq = torch.nn.Sequential(in_layer, d_layer) out_d_layer = seq(None) out_multi_dgca = multi_dgca(in_layer(None)) assert isinstance(out_d_layer, list) assert len(out_d_layer) == 1 assert torch.all(out_d_layer[0] == out_multi_dgca) def test_decagon_layer_05(): # check if it is equivalent to MultiDGCA, as it should be # this time for two relations, same edge type d = Data() d.add_node_type('Dummy', 100) fam = d.add_relation_family('Dummy-Dummy', 0, 0, True) fam.add_relation_type('Dummy Relation 1', 0, 0, _symmetric_random(100, 100).to_sparse()) fam.add_relation_type('Dummy Relation 2', 0, 0, _symmetric_random(100, 100).to_sparse()) in_layer = OneHotInputLayer(d) multi_dgca = MultiDGCA([100, 100], 32, [r.adjacency_matrix for r in fam.relation_types[0, 0]], keep_prob=1., activation=lambda x: x) d_layer = DecagonLayer(in_layer.output_dim, output_dim=32, data=d, keep_prob=1., rel_activation=lambda x: x, layer_activation=lambda x: x) assert all([ isinstance(dgca, DropoutGraphConvActivation) \ for dgca in d_layer.next_layer_repr[0][0].convolutions ]) weight = [ dgca.graph_conv.weight \ for dgca in d_layer.next_layer_repr[0][0].convolutions ] assert all([ isinstance(w, torch.Tensor) \ for w in weight ]) assert len(multi_dgca.dgca) == 2 for i in range(2): assert isinstance(multi_dgca.dgca[i], decagon_pytorch.convolve.DropoutGraphConvActivation) for i in range(2): multi_dgca.dgca[i].graph_conv.weight = weight[i] seq = torch.nn.Sequential(in_layer, d_layer) out_d_layer = seq(None) x = in_layer(None) out_multi_dgca = multi_dgca([ x[0], x[0] ]) assert isinstance(out_d_layer, list) assert len(out_d_layer) == 1 assert torch.all(out_d_layer[0] == out_multi_dgca)