def get_adv_untarget(model,
                     img_t,
                     targetCode,
                     eps=1.0 / 255,
                     threshold=40,
                     loss=nn.L1Loss()):
    start = time.time()
    if not isinstance(targetCode, torch.cuda.FloatTensor):
        targetCode = Variable(torch.Tensor(targetCode).cuda())
    # BE CAUTIOUS when you do the reshape!
    X = np.array(img_t.unsqueeze(0))
    inputs = Variable(torch.Tensor(X).cuda(), requires_grad=True)
    output = model(inputs)
    targetCode = targetCode.detach()

    l1loss = loss(output, targetCode.detach())
    #l1loss.backward(retain_graph=True)
    l1loss.backward(retain_graph=True)
    tmp = inputs.grad

    tCodeValue = targetCode.cpu().data.numpy()
    oCodeValue = torch.sign(output).cpu().data.numpy()
    # Everything with 'code' in it is the one signed before
    # xxxCodeValue was signed
    #
    print('...non-targeted iterative FGSM begin....')
    print('initial distance', np.sum(np.abs(tCodeValue - oCodeValue)) / 2)
    i = 0
    while np.sum(np.abs(tCodeValue - oCodeValue)) / 2 <= threshold:
        print('epoch ', i, ' loss: ', l1loss.cpu().data.numpy())
        print('Hamming distance: ',
              np.sum(np.abs(tCodeValue - oCodeValue)) / 2)

        adv = inputs + eps * torch.sign(inputs.grad)
        #inputs.grad.data.zero_()
        tmp = adv.cpu().data.numpy()
        tmp[tmp < 0] = 0
        tmp[tmp > 1] = 1
        inputs = Variable(torch.Tensor(tmp).cuda(), requires_grad=True)

        output_adv = model(inputs)

        l1loss = loss(output_adv, targetCode.detach())
        l1loss.backward(retain_graph=True)

        #oCodeValue = torch.sign(outputCode).cpu().data.numpy()
        oCodeValue = torch.sign(output_adv).cpu().data.numpy()

        i = i + 1
        if i >= 20:
            print('Adv generation failed')
            end = time.time()
            print(end - start)
            return False

    print('Final Hamming distance : ',
          np.sum(np.abs(tCodeValue - oCodeValue)) / 2)
    return inputs
def iFGSMTargetAttackMultiTarget(model,
                                 img_t,
                                 multiTargetCode,
                                 eps=1.0 / 255,
                                 l_inf_max=32):

    multiTargetNP = multiTargetCode
    if not isinstance(multiTargetCode, torch.cuda.FloatTensor):
        multiTargetCode = Variable(torch.Tensor(multiTargetCode).cuda())

    # Calculate the weights of each target code.
    uniqueTargetNP, targetIndex, targetCounts = np.unique(multiTargetNP,
                                                          return_index=True,
                                                          return_counts=True,
                                                          axis=0)
    targetWeights = targetCounts.astype(float) / targetCounts.sum()
    multiTargetCode = multiTargetCode[targetIndex]

    from myLoss import multiTargetL1Loss as loss
    X = np.array(img_t.unsqueeze(0))
    inputs = Variable(torch.Tensor(X).cuda(), requires_grad=True)
    output = model(inputs)
    multiTargetCode = multiTargetCode.detach()

    multiL1loss = loss(output, multiTargetCode, targetWeights)
    multiL1loss.backward(retain_graph=True)
    tmp = inputs.grad

    print('...targeted iterative FGSM begin....')

    i = 0
    while i < l_inf_max:
        print('epoch ', i, ' loss: ', multiL1loss.cpu().data.numpy())

        adv = inputs - eps * torch.sign(inputs.grad)
        tmp = adv.cpu().data.numpy()
        tmp[tmp < 0] = 0
        tmp[tmp > 1] = 1
        inputs = Variable(torch.Tensor(tmp).cuda(), requires_grad=True)

        output_adv = model(inputs)

        multiL1loss = loss(output_adv, multiTargetCode, targetWeights)
        multiL1loss.backward(retain_graph=True)
        i = i + 1

    return inputs
def iFGSMTargetAttackMultiTargetDI(model,
                                   img_t,
                                   multiTargetCode,
                                   eps=1.0 / 255,
                                   l_inf_max=32,
                                   t_prob=0.5):

    multiTargetNP = multiTargetCode
    if not isinstance(multiTargetCode, torch.cuda.FloatTensor):
        multiTargetCode = Variable(torch.Tensor(multiTargetCode).cuda())

    # Calculate the weights of each target code.
    uniqueTargetNP, targetIndex, targetCounts = np.unique(multiTargetNP,
                                                          return_index=True,
                                                          return_counts=True,
                                                          axis=0)
    targetWeights = targetCounts.astype(float) / targetCounts.sum()
    multiTargetCode = multiTargetCode[targetIndex]
    multiTargetCode = multiTargetCode.detach()

    X = np.array(img_t.unsqueeze(0))

    i = 0

    adv = Variable(torch.Tensor(X).cuda(), requires_grad=True)

    from myLoss import multiTargetL1Loss as loss

    while i < l_inf_max:
        adv_np = adv.cpu().data.numpy()
        adv_np[adv_np < 0] = 0
        adv_np[adv_np > 1] = 1

        inputs = randomly_input_diversity(adv_np[0], p=t_prob)

        output_t = model(inputs)
        multiL1loss = loss(output_t, multiTargetCode, targetWeights)
        multiL1loss.backward(retain_graph=True)
        grad_var = inputs.grad

        adv = adv - eps * torch.sign(grad_var)

        i = i + 1

    adv_np = adv.cpu().data.numpy()
    adv_np[adv_np < 0] = 0
    adv_np[adv_np > 1] = 1
    adv = Variable(torch.Tensor(adv_np).cuda(), requires_grad=True)
    return adv
def targetedAttack(model,
                   img_t,
                   targetCode,
                   eps=1.0 / 255,
                   l_inf_max=32,
                   threshold_stop=2,
                   loss=nn.L1Loss(),
                   decay_factor=1.0,
                   t_prob=0.5,
                   bShowProcess=False,
                   bEarlyStop=False,
                   adv_method='iFGSM'):
    if not isinstance(targetCode, torch.cuda.FloatTensor):
        targetCode = Variable(torch.Tensor(targetCode).cuda())

    X = np.array(img_t.unsqueeze(0))
    adv = Variable(torch.Tensor(X).cuda(), requires_grad=True)
    output = model(adv)
    tCodeValue = targetCode.cpu().data.numpy()
    oCodeValue = torch.sign(output).cpu().data.numpy()

    print('...targeted %s begin....' % (adv_method))
    print('initial distance', np.sum(np.abs(tCodeValue - oCodeValue)) / 2)
    i = 0
    grad_var = 0
    while i < l_inf_max:
        adv_np = adv.cpu().data.numpy()
        adv_np[adv_np < 0] = 0
        adv_np[adv_np > 1] = 1

        # inputs_adv is used as the input of model;
        # adv is used as the adv result of iter i.
        # They are different when using Diversity Inputs method

        if adv_method == 'iFGSM' or adv_method == 'miFGSM':
            inputs_adv = Variable(torch.Tensor(adv_np).cuda(),
                                  requires_grad=True)
        elif adv_method == 'iFGSMDI' or adv_method == 'miFGSMDI':
            inputs_adv = randomly_input_diversity(adv_np[0], p=t_prob)

        output = model(inputs_adv)
        l1loss = loss(output, targetCode.detach())
        l1loss.backward(retain_graph=True)

        if adv_method == 'iFGSM':
            grad_var = inputs_adv.grad
        elif adv_method == 'miFGSM':
            grad_var = grad_var * decay_factor + inputs_adv.grad / torch.norm(
                inputs_adv.grad, p=1)
        elif adv_method == 'iFGSMDI':
            grad_var = inputs_adv.grad
        elif adv_method == 'miFGSMDI':
            grad_var = grad_var * decay_factor + inputs_adv.grad / torch.norm(
                inputs_adv.grad, p=1)
        elif adv_method == 'PGD':
            grad_var = inputs_adv.grad

        adv = adv - eps * torch.sign(grad_var)

        if bShowProcess:
            output = model(adv)
            oCodeValue = torch.sign(output).cpu().data.numpy()
            hamming_dist = np.sum(np.abs(tCodeValue - oCodeValue)) / 2
            print("epoch %d, Hamming Distance: %d" % (i, hamming_dist))
            if bEarlyStop:
                if hamming_dist <= threshold_stop:
                    break
        elif bEarlyStop:
            output = model(adv)
            oCodeValue = torch.sign(output).cpu().data.numpy()
            hamming_dist = np.sum(np.abs(tCodeValue - oCodeValue)) / 2
            if hamming_dist <= threshold_stop:
                break
        i = i + 1

    adv_np = adv.cpu().data.numpy()
    adv_np[adv_np < 0] = 0
    adv_np[adv_np > 1] = 1
    adv = Variable(torch.Tensor(adv_np).cuda(), requires_grad=True)
    output = model(adv)
    oCodeValue = torch.sign(output).cpu().data.numpy()
    print('...Final Hamming distance : ',
          np.sum(np.abs(tCodeValue - oCodeValue)) / 2)
    return adv
def iFGSMMultiTargetEnsembleRes(model_list,
                                img_t,
                                multiTargetCode_list,
                                eps=1.0 / 255,
                                l_inf_max=32):

    model_size = len(model_list)
    model_weights = np.ones([model_size]) / model_size
    #model_weights = torch.Tensor(np.ones([model_size])/model_size).cuda()
    output_list = []
    targetCodes_list = []
    codesWeights_list = []

    for j in range(model_size):
        multiTargetCode = multiTargetCode_list[j]
        multiTargetNP = multiTargetCode
        if not isinstance(multiTargetCode, torch.cuda.FloatTensor):
            multiTargetCode = Variable(torch.Tensor(multiTargetCode).cuda())

        # Calculate the weights of each target code.
        uniqueTargetNP, targetIndex, targetCounts = np.unique(
            multiTargetNP, return_index=True, return_counts=True, axis=0)
        targetWeights = targetCounts.astype(float) / targetCounts.sum()
        multiTargetCode = multiTargetCode[targetIndex]
        targetCodes_list.append(multiTargetCode)
        codesWeights_list.append(targetWeights)

    from myLoss import multiTargetL1LossEnsRes as loss

    X = np.array(img_t.unsqueeze(0))
    inputs = Variable(torch.Tensor(X).cuda(), requires_grad=True)
    for j in range(model_size):
        model_j = model_list[j]
        output_list.append(model_j(inputs))
    output_list = torch.stack(output_list[j])

    multiTargetCode = multiTargetCode.detach()
    multiL1loss = loss(output_list, model_weights, targetCodes_list,
                       codesWeights_list)
    multiL1loss.backward(retain_graph=True)
    tmp = inputs.grad

    print('...targeted iterative FGSM begin....')

    i = 0
    while i < l_inf_max:
        print('epoch ', i, ' loss: ', multiL1loss.cpu().data.numpy())

        adv = inputs - eps * torch.sign(inputs.grad)
        tmp = adv.cpu().data.numpy()
        tmp[tmp < 0] = 0
        tmp[tmp > 1] = 1
        inputs = Variable(torch.Tensor(tmp).cuda(), requires_grad=True)

        output_list = []
        for j in range(model_size):
            model_j = model_list[j]
            output_list.append(model_j(inputs))
        output_list = torch.stack(output_list[j])

        multiL1loss = loss(output_list, model_weights, targetCodes_list,
                           codesWeights_list)
        multiL1loss.backward(retain_graph=True)
        i = i + 1

    return inputs