# ProxylessNAS: Direct Neural Architecture Search on Target Task and Hardware
# Han Cai, Ligeng Zhu, Song Han
# International Conference on Learning Representations (ICLR), 2019.

import torch
import numpy as np
import torch.nn as nn
from torch.nn.parameter import Parameter
import torch.nn.functional as F

from models.SuperProxylessNAS.modules_AutoML.layers import *


def build_candidate_ops(candidate_ops, in_channels, out_channels, stride, ops_order):
    if candidate_ops is None:
        raise ValueError('please specify a candidate set')

    name2ops = {
        'Identity': lambda in_C, out_C, S: IdentityLayer(in_C, out_C, ops_order=ops_order),
    }
    # add MBConv layers
    name2ops.update({
        '3x3_MBConv1': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 3, S, 1),
        '3x3_MBConv2': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 3, S, 2),
        '3x3_MBConv3': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 3, S, 3),
        '3x3_MBConv4': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 3, S, 4),
        '3x3_MBConv5': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 3, S, 5),
        '3x3_MBConv6': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 3, S, 6),
        #######################################################################################
        '5x5_MBConv1': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 5, S, 1),
        '5x5_MBConv2': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 5, S, 2),
        '5x5_MBConv3': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 5, S, 3),
        '5x5_MBConv4': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 5, S, 4),
        '5x5_MBConv5': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 5, S, 5),
        '5x5_MBConv6': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 5, S, 6),
        #######################################################################################
        '7x7_MBConv1': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 7, S, 1),
        '7x7_MBConv2': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 7, S, 2),
        '7x7_MBConv3': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 7, S, 3),
        '7x7_MBConv4': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 7, S, 4),
        '7x7_MBConv5': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 7, S, 5),
        '7x7_MBConv6': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 7, S, 6),
    })

    return [
        name2ops[name](in_channels, out_channels, stride) for name in candidate_ops
    ]


class MixedEdge(nn.Module):
    def __init__(self, candidate_ops):
        super(MixedEdge, self).__init__()

        self.candidate_ops = nn.ModuleList(candidate_ops)

    @property
    def n_choices(self):
        return len(self.candidate_ops)

    """ """

    def forward(self, x):
#        output  = sum(op(x) for op in self.candidate_ops)
        output = 0
        for i in range(len(self.candidate_ops)):
            output = output + self.candidate_ops[i](x)
        return output

3cbd74bc12c131c33dcc38c66d8a53330c54104c
<mask token>


class MixedEdge(nn.Module):

    def __init__(self, candidate_ops):
        super(MixedEdge, self).__init__()
        self.candidate_ops = nn.ModuleList(candidate_ops)

    @property
    def n_choices(self):
        return len(self.candidate_ops)
    <mask token>

    def forward(self, x):
        output = 0
        for i in range(len(self.candidate_ops)):
            output = output + self.candidate_ops[i](x)
        return output

<mask token>


class MixedEdge(nn.Module):

    def __init__(self, candidate_ops):
        super(MixedEdge, self).__init__()
        self.candidate_ops = nn.ModuleList(candidate_ops)

    @property
    def n_choices(self):
        return len(self.candidate_ops)
    """ """

    def forward(self, x):
        output = 0
        for i in range(len(self.candidate_ops)):
            output = output + self.candidate_ops[i](x)
        return output

<mask token>


def build_candidate_ops(candidate_ops, in_channels, out_channels, stride,
    ops_order):
    if candidate_ops is None:
        raise ValueError('please specify a candidate set')
    name2ops = {'Identity': lambda in_C, out_C, S: IdentityLayer(in_C,
        out_C, ops_order=ops_order)}
    name2ops.update({'3x3_MBConv1': lambda in_C, out_C, S:
        MBInvertedConvLayer(in_C, out_C, 3, S, 1), '3x3_MBConv2': lambda
        in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 3, S, 2),
        '3x3_MBConv3': lambda in_C, out_C, S: MBInvertedConvLayer(in_C,
        out_C, 3, S, 3), '3x3_MBConv4': lambda in_C, out_C, S:
        MBInvertedConvLayer(in_C, out_C, 3, S, 4), '3x3_MBConv5': lambda
        in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 3, S, 5),
        '3x3_MBConv6': lambda in_C, out_C, S: MBInvertedConvLayer(in_C,
        out_C, 3, S, 6), '5x5_MBConv1': lambda in_C, out_C, S:
        MBInvertedConvLayer(in_C, out_C, 5, S, 1), '5x5_MBConv2': lambda
        in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 5, S, 2),
        '5x5_MBConv3': lambda in_C, out_C, S: MBInvertedConvLayer(in_C,
        out_C, 5, S, 3), '5x5_MBConv4': lambda in_C, out_C, S:
        MBInvertedConvLayer(in_C, out_C, 5, S, 4), '5x5_MBConv5': lambda
        in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 5, S, 5),
        '5x5_MBConv6': lambda in_C, out_C, S: MBInvertedConvLayer(in_C,
        out_C, 5, S, 6), '7x7_MBConv1': lambda in_C, out_C, S:
        MBInvertedConvLayer(in_C, out_C, 7, S, 1), '7x7_MBConv2': lambda
        in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 7, S, 2),
        '7x7_MBConv3': lambda in_C, out_C, S: MBInvertedConvLayer(in_C,
        out_C, 7, S, 3), '7x7_MBConv4': lambda in_C, out_C, S:
        MBInvertedConvLayer(in_C, out_C, 7, S, 4), '7x7_MBConv5': lambda
        in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 7, S, 5),
        '7x7_MBConv6': lambda in_C, out_C, S: MBInvertedConvLayer(in_C,
        out_C, 7, S, 6)})
    return [name2ops[name](in_channels, out_channels, stride) for name in
        candidate_ops]


class MixedEdge(nn.Module):

    def __init__(self, candidate_ops):
        super(MixedEdge, self).__init__()
        self.candidate_ops = nn.ModuleList(candidate_ops)

    @property
    def n_choices(self):
        return len(self.candidate_ops)
    """ """

    def forward(self, x):
        output = 0
        for i in range(len(self.candidate_ops)):
            output = output + self.candidate_ops[i](x)
        return output

import torch
import numpy as np
import torch.nn as nn
from torch.nn.parameter import Parameter
import torch.nn.functional as F
from models.SuperProxylessNAS.modules_AutoML.layers import *


def build_candidate_ops(candidate_ops, in_channels, out_channels, stride,
    ops_order):
    if candidate_ops is None:
        raise ValueError('please specify a candidate set')
    name2ops = {'Identity': lambda in_C, out_C, S: IdentityLayer(in_C,
        out_C, ops_order=ops_order)}
    name2ops.update({'3x3_MBConv1': lambda in_C, out_C, S:
        MBInvertedConvLayer(in_C, out_C, 3, S, 1), '3x3_MBConv2': lambda
        in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 3, S, 2),
        '3x3_MBConv3': lambda in_C, out_C, S: MBInvertedConvLayer(in_C,
        out_C, 3, S, 3), '3x3_MBConv4': lambda in_C, out_C, S:
        MBInvertedConvLayer(in_C, out_C, 3, S, 4), '3x3_MBConv5': lambda
        in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 3, S, 5),
        '3x3_MBConv6': lambda in_C, out_C, S: MBInvertedConvLayer(in_C,
        out_C, 3, S, 6), '5x5_MBConv1': lambda in_C, out_C, S:
        MBInvertedConvLayer(in_C, out_C, 5, S, 1), '5x5_MBConv2': lambda
        in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 5, S, 2),
        '5x5_MBConv3': lambda in_C, out_C, S: MBInvertedConvLayer(in_C,
        out_C, 5, S, 3), '5x5_MBConv4': lambda in_C, out_C, S:
        MBInvertedConvLayer(in_C, out_C, 5, S, 4), '5x5_MBConv5': lambda
        in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 5, S, 5),
        '5x5_MBConv6': lambda in_C, out_C, S: MBInvertedConvLayer(in_C,
        out_C, 5, S, 6), '7x7_MBConv1': lambda in_C, out_C, S:
        MBInvertedConvLayer(in_C, out_C, 7, S, 1), '7x7_MBConv2': lambda
        in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 7, S, 2),
        '7x7_MBConv3': lambda in_C, out_C, S: MBInvertedConvLayer(in_C,
        out_C, 7, S, 3), '7x7_MBConv4': lambda in_C, out_C, S:
        MBInvertedConvLayer(in_C, out_C, 7, S, 4), '7x7_MBConv5': lambda
        in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 7, S, 5),
        '7x7_MBConv6': lambda in_C, out_C, S: MBInvertedConvLayer(in_C,
        out_C, 7, S, 6)})
    return [name2ops[name](in_channels, out_channels, stride) for name in
        candidate_ops]


class MixedEdge(nn.Module):

    def __init__(self, candidate_ops):
        super(MixedEdge, self).__init__()
        self.candidate_ops = nn.ModuleList(candidate_ops)

    @property
    def n_choices(self):
        return len(self.candidate_ops)
    """ """

    def forward(self, x):
        output = 0
        for i in range(len(self.candidate_ops)):
            output = output + self.candidate_ops[i](x)
        return output

# ProxylessNAS: Direct Neural Architecture Search on Target Task and Hardware
# Han Cai, Ligeng Zhu, Song Han
# International Conference on Learning Representations (ICLR), 2019.

import torch
import numpy as np
import torch.nn as nn
from torch.nn.parameter import Parameter
import torch.nn.functional as F

from models.SuperProxylessNAS.modules_AutoML.layers import *


def build_candidate_ops(candidate_ops, in_channels, out_channels, stride, ops_order):
    if candidate_ops is None:
        raise ValueError('please specify a candidate set')

    name2ops = {
        'Identity': lambda in_C, out_C, S: IdentityLayer(in_C, out_C, ops_order=ops_order),
    }
    # add MBConv layers
    name2ops.update({
        '3x3_MBConv1': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 3, S, 1),
        '3x3_MBConv2': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 3, S, 2),
        '3x3_MBConv3': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 3, S, 3),
        '3x3_MBConv4': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 3, S, 4),
        '3x3_MBConv5': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 3, S, 5),
        '3x3_MBConv6': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 3, S, 6),
        #######################################################################################
        '5x5_MBConv1': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 5, S, 1),
        '5x5_MBConv2': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 5, S, 2),
        '5x5_MBConv3': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 5, S, 3),
        '5x5_MBConv4': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 5, S, 4),
        '5x5_MBConv5': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 5, S, 5),
        '5x5_MBConv6': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 5, S, 6),
        #######################################################################################
        '7x7_MBConv1': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 7, S, 1),
        '7x7_MBConv2': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 7, S, 2),
        '7x7_MBConv3': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 7, S, 3),
        '7x7_MBConv4': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 7, S, 4),
        '7x7_MBConv5': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 7, S, 5),
        '7x7_MBConv6': lambda in_C, out_C, S: MBInvertedConvLayer(in_C, out_C, 7, S, 6),
    })

    return [
        name2ops[name](in_channels, out_channels, stride) for name in candidate_ops
    ]


class MixedEdge(nn.Module):
    def __init__(self, candidate_ops):
        super(MixedEdge, self).__init__()

        self.candidate_ops = nn.ModuleList(candidate_ops)

    @property
    def n_choices(self):
        return len(self.candidate_ops)

    """ """

    def forward(self, x):
#        output  = sum(op(x) for op in self.candidate_ops)
        output = 0
        for i in range(len(self.candidate_ops)):
            output = output + self.candidate_ops[i](x)
        return output
