import torch
import torch.nn as nn
import torch.nn.functional as F

class EIO_ResNet(nn.Module):
    def __init__(self):
        super(EIO_ResNet, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm1 = nn.BatchNorm2d(16)
        self.relu1 = nn.ReLU(inplace=True)
        self.conv2 = nn.Conv2d(16, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm2 = nn.BatchNorm2d(16)
        self.relu2 = nn.ReLU(inplace=True)
        self.conv3 = nn.Conv2d(16, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm3 = nn.BatchNorm2d(16)
        self.relu3 = nn.ReLU(inplace=True)
        self.conv4 = nn.Conv2d(16, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm4 = nn.BatchNorm2d(16)
        self.relu4 = nn.ReLU(inplace=True)
        self.conv5 = nn.Conv2d(16, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm5 = nn.BatchNorm2d(16)
        self.relu5 = nn.ReLU(inplace=True)
        self.conv6 = nn.Conv2d(16, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm6 = nn.BatchNorm2d(16)
        self.relu6 = nn.ReLU(inplace=True)
        self.conv7 = nn.Conv2d(16, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm7 = nn.BatchNorm2d(16)
        self.relu7 = nn.ReLU(inplace=True)
        self.conv8 = nn.Conv2d(16, 32, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm8 = nn.BatchNorm2d(32)
        self.relu8 = nn.ReLU(inplace=True)
        self.conv9 = nn.Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm9 = nn.BatchNorm2d(32)
        self.conv10 = nn.Conv2d(16, 32, kernel_size=(1, 1), stride=(2, 2), padding=(0, 0), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm10 = nn.BatchNorm2d(32)
        self.relu9 = nn.ReLU(inplace=True)
        self.conv11 = nn.Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm11 = nn.BatchNorm2d(32)
        self.relu10 = nn.ReLU(inplace=True)
        self.conv12 = nn.Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm12 = nn.BatchNorm2d(32)
        self.relu11 = nn.ReLU(inplace=True)
        self.conv13 = nn.Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm13 = nn.BatchNorm2d(32)
        self.relu12 = nn.ReLU(inplace=True)
        self.conv14 = nn.Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm14 = nn.BatchNorm2d(32)
        self.relu13 = nn.ReLU(inplace=True)
        self.conv15 = nn.Conv2d(32, 64, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm15 = nn.BatchNorm2d(64)
        self.relu14 = nn.ReLU(inplace=True)
        self.conv16 = nn.Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm16 = nn.BatchNorm2d(64)
        self.conv17 = nn.Conv2d(32, 64, kernel_size=(1, 1), stride=(2, 2), padding=(0, 0), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm17 = nn.BatchNorm2d(64)
        self.relu15 = nn.ReLU(inplace=True)
        self.conv18 = nn.Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm18 = nn.BatchNorm2d(64)
        self.relu16 = nn.ReLU(inplace=True)
        self.conv19 = nn.Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm19 = nn.BatchNorm2d(64)
        self.relu17 = nn.ReLU(inplace=True)
        self.conv20 = nn.Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm20 = nn.BatchNorm2d(64)
        self.relu18 = nn.ReLU(inplace=True)
        self.conv21 = nn.Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), dilation=(1, 1), bias=0, groups=1)
        self.batchnorm21 = nn.BatchNorm2d(64)
        self.relu19 = nn.ReLU(inplace=True)
        self.avgpool_pool1 = nn.AvgPool2d(8, stride=8, padding=0)
        self.fc1 = nn.Linear(64, 10, bias=1)
    def forward(self, blob1):
        conv_blob1 = self.conv1(blob1)
        batch_norm_blob1 = self.batchnorm1(conv_blob1)
        relu_blob1 = self.relu1(batch_norm_blob1)
        conv_blob2 = self.conv2(relu_blob1)
        batch_norm_blob2 = self.batchnorm2(conv_blob2)
        relu_blob2 = self.relu2(batch_norm_blob2)
        conv_blob3 = self.conv3(relu_blob2)
        batch_norm_blob3 = self.batchnorm3(conv_blob3)
        add_blob1 = batch_norm_blob3 + relu_blob1
        relu_blob3 = self.relu3(add_blob1)
        conv_blob4 = self.conv4(relu_blob3)
        batch_norm_blob4 = self.batchnorm4(conv_blob4)
        relu_blob4 = self.relu4(batch_norm_blob4)
        conv_blob5 = self.conv5(relu_blob4)
        batch_norm_blob5 = self.batchnorm5(conv_blob5)
        add_blob2 = batch_norm_blob5 + relu_blob3
        relu_blob5 = self.relu5(add_blob2)
        conv_blob6 = self.conv6(relu_blob5)
        batch_norm_blob6 = self.batchnorm6(conv_blob6)
        relu_blob6 = self.relu6(batch_norm_blob6)
        conv_blob7 = self.conv7(relu_blob6)
        batch_norm_blob7 = self.batchnorm7(conv_blob7)
        add_blob3 = batch_norm_blob7 + relu_blob5
        relu_blob7 = self.relu7(add_blob3)
        conv_blob8 = self.conv8(relu_blob7)
        batch_norm_blob8 = self.batchnorm8(conv_blob8)
        relu_blob8 = self.relu8(batch_norm_blob8)
        conv_blob9 = self.conv9(relu_blob8)
        batch_norm_blob9 = self.batchnorm9(conv_blob9)
        conv_blob10 = self.conv10(relu_blob7)
        batch_norm_blob10 = self.batchnorm10(conv_blob10)
        add_blob4 = batch_norm_blob9 + batch_norm_blob10
        relu_blob9 = self.relu9(add_blob4)
        conv_blob11 = self.conv11(relu_blob9)
        batch_norm_blob11 = self.batchnorm11(conv_blob11)
        relu_blob10 = self.relu10(batch_norm_blob11)
        conv_blob12 = self.conv12(relu_blob10)
        batch_norm_blob12 = self.batchnorm12(conv_blob12)
        add_blob5 = batch_norm_blob12 + relu_blob9
        relu_blob11 = self.relu11(add_blob5)
        conv_blob13 = self.conv13(relu_blob11)
        batch_norm_blob13 = self.batchnorm13(conv_blob13)
        relu_blob12 = self.relu12(batch_norm_blob13)
        conv_blob14 = self.conv14(relu_blob12)
        batch_norm_blob14 = self.batchnorm14(conv_blob14)
        add_blob6 = batch_norm_blob14 + relu_blob11
        relu_blob13 = self.relu13(add_blob6)
        conv_blob15 = self.conv15(relu_blob13)
        batch_norm_blob15 = self.batchnorm15(conv_blob15)
        relu_blob14 = self.relu14(batch_norm_blob15)
        conv_blob16 = self.conv16(relu_blob14)
        batch_norm_blob16 = self.batchnorm16(conv_blob16)
        conv_blob17 = self.conv17(relu_blob13)
        batch_norm_blob17 = self.batchnorm17(conv_blob17)
        add_blob7 = batch_norm_blob16 + batch_norm_blob17
        relu_blob15 = self.relu15(add_blob7)
        conv_blob18 = self.conv18(relu_blob15)
        batch_norm_blob18 = self.batchnorm18(conv_blob18)
        relu_blob16 = self.relu16(batch_norm_blob18)
        conv_blob19 = self.conv19(relu_blob16)
        batch_norm_blob19 = self.batchnorm19(conv_blob19)
        add_blob8 = batch_norm_blob19 + relu_blob15
        relu_blob17 = self.relu17(add_blob8)
        conv_blob20 = self.conv20(relu_blob17)
        batch_norm_blob20 = self.batchnorm20(conv_blob20)
        relu_blob18 = self.relu18(batch_norm_blob20)
        conv_blob21 = self.conv21(relu_blob18)
        batch_norm_blob21 = self.batchnorm21(conv_blob21)
        add_blob9 = batch_norm_blob21 + relu_blob17
        relu_blob19 = self.relu19(add_blob9)
        avgpool_pool_blob1 = self.avgpool_pool1(relu_blob19)
        view_blob1 = avgpool_pool_blob1.view(avgpool_pool_blob1.shape[0], -1)
        fc_blob1 = self.fc1(view_blob1)
        return fc_blob1
