text: # -*- coding: utf-8 -*-
  """Label Flip.ipynb
  
  Automatically generated by Colaboratory.
  
  Original file is located at
      https://colab.research.google.com/drive/1Q8a_kEJCLh3Pp6uvK4jzTzY2d63djcgf
  """
  
  from scipy.optimize import linprog
  import numpy as np
  import pandas as pd
  import matplotlib.pyplot as plt
  from sklearn.svm import SVC
  from sklearn.model_selection import train_test_split
  
  # drive.mount('/content/drive')
  
  data = pd.read_csv('sic_data.csv')
  
  
  def make_meshgrid(x, y, h=0.2):
      x_min, x_max = x.min() - 1, x.max() + 1
      y_min, y_max = y.min() - 1, y.max() + 1
      xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                           np.arange(y_min, y_max, h))
      return xx, yy
  
  
  def SVMPlot(clf, X, y, ax):
      X = np.array(X)
      xx, yy = np.meshgrid(
          np.arange(X[:, 0].min(), X[:, 0].max(), 0.02),
          np.arange(X[:, 1].min(), X[:, 1].max(), 0.02))
      Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
      Z = Z.reshape(xx.shape)
  
      ax.contourf(xx, yy, Z, cmap=plt.cm.coolwarm, alpha=0.8)
      ax.scatter(X[:, 0], X[:, 1], c=y,
                 cmap=plt.cm.coolwarm, s=10, edgecolors='k')
  
  
  def solveLP(eps):
      X = X_train
      func_coeff = [0]*(len(U))
      gamma = 1
      C = 100
      for i in range(len(U)):
          func_coeff[i] = (eps[i]-psi[i])
  
      # constraints
      a_ub = []
      b_ub = []
      a_eq = []
      b_eq = []
  
      temp = [0]*len(U)
      for i in range(len(X), len(U)):
          temp[i] = c[i-len(X)]
  
      a_ub.append(temp)
      b_ub.append(C)
  
      for i in range(len(X)):
          temp = [0]*len(U)
          temp[i] = temp[len(X)+i] = 1
          a_eq.append(temp)
          b_eq.append(1)
  
      q_bound = (0, 1)
      Q_bound = tuple([(0, 1)]*len(U))
  
      q = linprog(func_coeff, A_ub=a_ub, b_ub=b_ub, A_eq=a_eq, b_eq=b_eq,
                  bounds=Q_bound, options={"disp": False, "maxiter": 10000}).x
      return q
  
  
  def solveQP(q):
      X = X_train
      eps = np.zeros(len(U), dtype=np.float)
      newX = []
      newY = []
      for i in range(len(U)):
          if q[i] != 0:
              newX.append([U['X1'][i], U['X2'][i]])
              newY.append(U['Y'][i])
  
      newX = np.array(newX)
      newY = np.array(newY, dtype=int)
      new_classifier = SVC(gamma='auto')
      new_classifier.fit(newX, newY)
      for i in range(len(U)):
          xi = np.zeros(2)
          xi[0], xi[1], yi = U.iloc[i]
          new_predicted = new_classifier.predict(xi.reshape(1, -1))
          eps[i] = max(0, 1 - yi*new_predicted)
      return newX, newY, new_classifier, eps
  
  
  X = [0]*len(data)
  for i in range(len(data)):
      X[i] = [data['X1'][i], data['X2'][i]]
  normal_classifier = SVC(gamma='auto')
  y = data['Y']
  X_train, X_test, y_train, y_test = train_test_split(
      X, y, test_size=0.8, random_state=42)
  normal_classifier.fit(X_train, y_train)
  data = pd.DataFrame(data=X_train, columns=['X1', 'X2'])
  data['Y'] = y_train.values
  
  temp_data = data.copy()
  temp_data['Y'] *= -1
  U = pd.DataFrame(np.vstack((data, temp_data)), columns=['X1', 'X2', 'Y'])
  psi = [0]*len(U)
  eps = [0]*len(U)
  c = [1]*len(U)
  q = [0]*len(U)
  for i in range(len(U)):
      xi = np.zeros(2)
      xi[0], xi[1], yi = U.iloc[i]
      normal_predicted = normal_classifier.predict(xi.reshape(1, -1))  # fs(xi)
      psi[i] = max(0, 1 - yi*normal_predicted)
  maxIter = 10
  curIter = 1
  while curIter <= maxIter:
      q = solveLP(eps)
      new_X_train, new_y_train, new_classifier, eps = solveQP(q)
      curIter += 1
  
  fig, axs = plt.subplots(1, 2, sharex=True, sharey=True, figsize=(12, 6))
  SVMPlot(normal_classifier, X_train, y_train, axs[0])
  SVMPlot(new_classifier, new_X_train, new_y_train, axs[1])
  plt.savefig('results.png')
  
  print('Normal classifier : ', normal_classifier.score(X_test, y_test))
  print('New classifier    : ', new_classifier.score(X_test, y_test))
  