text: import __init__
  import torch
  from gcn_lib.sparse.torch_vertex import GENConv
  from gcn_lib.sparse.torch_nn import norm_layer
  import torch.nn.functional as F
  from torch.utils.checkpoint import checkpoint
  import logging
  import numpy as np
  
  
  class DeeperGCN(torch.nn.Module):
      def __init__(self, args):
          super(DeeperGCN, self).__init__()
          self.args = args
  
          self.num_layers = args.num_layers
          self.dropout = args.dropout
          self.block = args.block
  
          self.checkpoint_grad = False
  
          in_channels = args.in_channels
          hidden_channels = args.hidden_channels
          num_tasks = args.num_tasks
          conv = args.conv
          aggr = args.gcn_aggr
  
          t = args.t
          self.learn_t = args.learn_t
          p = args.p
          self.learn_p = args.learn_p
          self.msg_norm = args.msg_norm
          learn_msg_scale = args.learn_msg_scale
  
          norm = args.norm
          mlp_layers = args.mlp_layers
  
          if aggr in ['softmax_sg', 'softmax', 'power'] and self.num_layers > 3:
              self.checkpoint_grad = True
              self.ckp_k = self.num_layers // 2
  
          print('The number of layers {}'.format(self.num_layers),
                'Aggregation method {}'.format(aggr),
                'block: {}'.format(self.block))
  
          if self.block == 'res+':
              print('LN/BN->ReLU->GraphConv->Res')
          elif self.block == 'res':
              print('GraphConv->LN/BN->ReLU->Res')
          elif self.block == 'dense':
              raise NotImplementedError('To be implemented')
          elif self.block == "plain":
              print('GraphConv->LN/BN->ReLU')
          else:
              raise Exception('Unknown block Type')
  
          self.gcns = torch.nn.ModuleList()
          self.norms = torch.nn.ModuleList()
  
          self.node_features_encoder = torch.nn.Linear(in_channels, hidden_channels)
          self.node_pred_linear = torch.nn.Linear(hidden_channels, num_tasks)
  
          for layer in range(self.num_layers):
  
              if conv == 'gen':
                  gcn = GENConv(hidden_channels, hidden_channels,
                                aggr=aggr,
                                t=t, learn_t=self.learn_t,
                                p=p, learn_p=self.learn_p,
                                msg_norm=self.msg_norm, learn_msg_scale=learn_msg_scale,
                                norm=norm, mlp_layers=mlp_layers)
              else:
                  raise Exception('Unknown Conv Type')
  
              self.gcns.append(gcn)
              self.norms.append(norm_layer(norm, hidden_channels))
  
      def forward(self,  x, edge_index):
  
          h = self.node_features_encoder(x)
          loss_reg = []
          std_list = []
  
          if self.block == 'res+':
  
              h = self.gcns[0](h, edge_index)
              h0 = h
              std = torch.std(h, dim=0, keepdim=False)
              std_list.append(std.mean().data.item())
              if self.checkpoint_grad:
  
                  for layer in range(1, self.num_layers):
                      h1 = self.norms[layer - 1](h)
                      h2 = F.relu(h1)
                      h2 = F.dropout(h2, p=self.dropout, training=self.training)
  
                      if layer % self.ckp_k != 0:
                          res = checkpoint(self.gcns[layer], h2, edge_index)
                          h = res + h
                      else:
                          h = self.gcns[layer](h2, edge_index) + h
  
                      std = torch.std(h, dim=0, keepdim=False)
                      std_list.append(std.mean().data.item())
                      loss_reg.append((torch.sigmoid(h) - torch.sigmoid(h0)).square().mean().sqrt())
                      h0 = h
              else:
                  for layer in range(1, self.num_layers):
                      h1 = self.norms[layer - 1](h)
                      h2 = F.relu(h1)
                      h2 = F.dropout(h2, p=self.dropout, training=self.training)
                      h = self.gcns[layer](h2, edge_index) + h
  
                      std = torch.std(h, dim=0, keepdim=False)
                      std_list.append(std.mean().data.item())
                      loss_reg.append((torch.sigmoid(h) - torch.sigmoid(h0)).square().mean().sqrt())
                      h0 = h
  
              h = F.relu(self.norms[self.num_layers - 1](h))
              h = F.dropout(h, p=self.dropout, training=self.training)
  
          elif self.block == 'res':
  
              h = F.relu(self.norms[0](self.gcns[0](h, edge_index)))
              h = F.dropout(h, p=self.dropout, training=self.training)
  
              h0 = h
              std = torch.std(h, dim=0, keepdim=False)
              std_list.append(std.mean().data.item())
              for layer in range(1, self.num_layers):
                  h1 = self.gcns[layer](h, edge_index)
                  h2 = self.norms[layer](h1)
                  h = F.relu(h2) + h
                  h = F.dropout(h, p=self.dropout, training=self.training)
  
                  std = torch.std(h, dim=0, keepdim=False)
                  std_list.append(std.mean().data.item())
                  loss_reg.append((torch.sigmoid(h) - torch.sigmoid(h0)).square().mean().sqrt())
                  h0 = h
          elif self.block == 'dense':
              raise NotImplementedError('To be implemented')
  
          elif self.block == 'plain':
  
              h = F.relu(self.norms[0](self.gcns[0](h, edge_index)))
              h = F.dropout(h, p=self.dropout, training=self.training)
              h0 = h
              std = torch.std(h, dim=0, keepdim=False)
              std_list.append(std.mean().data.item())
  
              for layer in range(1, self.num_layers):
                  h1 = self.gcns[layer](h, edge_index)
                  h2 = self.norms[layer](h1)
                  h = F.relu(h2)
                  h = F.dropout(h, p=self.dropout, training=self.training)
                  std = torch.std(h, dim=0, keepdim=False)
                  std_list.append(std.mean().data.item())
                  loss_reg.append((torch.sigmoid(h) - torch.sigmoid(h0)).square().mean().sqrt())
                  h0 = h
          else:
              raise Exception('Unknown block Type')
  
          h = self.node_pred_linear(h)
          if self.args.use_osreg:
              loss_reg = (torch.stack(loss_reg,dim=0).mean()-self.args.os_thres).square().mean()
          else:
              loss_reg = 0.
  
          return torch.log_softmax(h, dim=-1), loss_reg, np.array(std_list)
  
      def print_params(self, epoch=None, final=False):
  
          if self.learn_t:
              ts = []
              for gcn in self.gcns:
                  ts.append(gcn.t.item())
              if final:
                  print('Final t {}'.format(ts))
              else:
                  logging.info('Epoch {}, t {}'.format(epoch, ts))
          if self.learn_p:
              ps = []
              for gcn in self.gcns:
                  ps.append(gcn.p.item())
              if final:
                  print('Final p {}'.format(ps))
              else:
                  logging.info('Epoch {}, p {}'.format(epoch, ps))
          if self.msg_norm:
              ss = []
              for gcn in self.gcns:
                  ss.append(gcn.msg_norm.msg_scale.item())
              if final:
                  print('Final s {}'.format(ss))
              else:
                  logging.info('Epoch {}, s {}'.format(epoch, ss))
  
  