<jupyter_start><jupyter_text><jupyter_code>import pennylane as qml
from pennylane import numpy as np
from pennylane.templates import RandomLayers
import matplotlib.pyplot as plt
from qiskit import *
import torch
from torch.autograd import Variable
from torchvision import datasets, transforms
import torch.optim as optim
import torch.nn.functional as F
import pandas as pd
use_cuda = torch.cuda.is_available()
print(use_cuda)
from google.colab import drive
drive.mount('/content/drive')
cd drive/MyDrive/Quantum\ Computer/qcnn/Qlassifier
n_epochs = 30   # Number of optimization epochs
n_layers = 1    # Number of random layers
n_train = 128    # Size of the train dataset
n_test = 32     # Size of the test dataset

SAVE_PATH = "./quanvolution_pqc/" # Data saving folder
PROCESS = True           # If False, skip quantum processing and load data from SAVE_PATH
BATCH_SIZE = 16
from torch.utils.data import SubsetRandomSampler
train_dataset = datasets.MNIST(root = "./data",
                               train = True,
                               download = True,
                               transform = transforms.transforms.Compose([
                                 transforms.Resize(size=14),
                                 transforms.ToTensor() 
                             ]))
                            

test_dataset = datasets.MNIST(root = "./data",
                              train = False,
                              download = False,
                              transform = transforms.transforms.Compose([
                                 transforms.Resize(size=14),
                                 transforms.ToTensor() 
                             ]))

train_sampler = SubsetRandomSampler(range(n_train))
test_sampler = SubsetRandomSampler(range(n_test))

train_loader = torch.utils.data.DataLoader(dataset = train_dataset,
                                           batch_size = BATCH_SIZE,
                                           shuffle = False,
                                           sampler = train_sampler)

test_loader = torch.utils.data.DataLoader(dataset = test_dataset,
                                          batch_size = BATCH_SIZE,
                                          shuffle = False,
                                          sampler = test_sampler)
for (x,y) in train_loader:
    print(torch.max(x[0],dim=2))
    break
token1 = '2b740fada862fb6d9683487f84455ff8fccb2caaa3988e4f406d321ef67ce0644eb679211a1b6a377ec5ee9b3839d34434255304ab535a9ed11ce60703f07446'
token2 = '<KEY>'

# from qiskit import IBMQ
# IBMQ.save_account(token2)
# provider = IBMQ.enable_account(token1)
dev = qml.device("default.qubit", wires=9)
# dev = qml.device('qiskit.ibmq', wires=9, backend='ibmq_qasm_simulator',provider=provider)
# IBMQ.get_provider(hub='ibm-q', group='open', project='main')
# dev = qml.device('qiskit.ibmq', wires=9, backend='ibmq_qasm_simulator',
                #  ibmqx_token=token1, hub='ibm-q', group='open', project='main')
# print(dev.capabilities()['backend'])
# import pennylane as qml
# from pennylane_ionq import ops

# dev = qml.device("ionq.qpu", wires=9)

# Random circuit parameters

@qml.qnode(dev, interface='torch')
def pqc(data,params,circno=9):
  print(data.device())
  print(params[0].device())
  n_qubits = 9
  for j in range(n_qubits):
      qml.RY(np.pi * data[j], wires=j)
  
  if circno == 2:     # len(params) == 18
      # PQC
      for i in range(n_qubits):
          qml.RX(params[i], wires=i)
      for i in range(n_qubits):
          qml.RX(params[i+n_qubits], wires=i)
      for i in range(n_qubits-1,0,-1):
          qml.CNOT(wires=[i,i-1])    
  elif circno == 3:   # len(params) == 26
      # PQC
      for i in range(n_qubits):
          qml.RX(params[i], wires=i)
      for i in range(n_qubits):
          qml.RX(params[i+n_qubits], wires=i)
      for k,i in enumerate(range(n_qubits-1,0,-1)):
          qml.CRZ(params[k+2*n_qubits], wires=[i,i-1])
  elif circno == 9:   # len(params) == 9
      # PQC
      for i in range(n_qubits):
          qml.Hadamard(wires=i)
      for i in range(n_qubits-1,0,-1):
          qml.CZ(wires=[i,i-1])
      for i in range(n_qubits):
          qml.RX(params[i],wires=i)
  elif circno == 10:  # len(params) == 18
      for i in range(n_qubits):
          qml.RY(params[i],wires=i)
      for i in range(n_qubits-1,0,-1):
          qml.CZ(wires=[i,i-1])
      qml.CZ(wires=[0,n_qubits-1])
      for i in range(n_qubits):
          qml.RY(params[i+n_qubits],wires=i)
  else:
      pass
  # Measurement producing 9 classical output values
  return qml.expval(qml.PauliZ(0))
print(pqc([1,0,2,1,2,3,1,2,0],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],circno=10))
class QuanvNet(torch.nn.Module):
    def __init__(self,qc=True,opt=True,circno=9):
        super().__init__()
        self.qc = qc
        self.opt = opt
        self.n_qubits = 9
        self.filters = 1
        self.conv_opt = torch.nn.Conv2d(in_channels=self.filters,out_channels=self.filters,kernel_size=3)
        self.conv1 = torch.nn.Conv2d(in_channels=self.filters,out_channels=8,kernel_size=3,padding='same')
        self.pre_pool = torch.nn.AvgPool2d(2)
        self.pool = torch.nn.MaxPool2d(2)
        self.conv2 = torch.nn.Conv2d(in_channels=8,out_channels=8,kernel_size=3)
        self.fc1 = torch.nn.Linear(32,16)
        self.fc2 = torch.nn.Linear(16,10)
        self.dropout = torch.nn.Dropout(0.4)
        if circno == 2:
          self.num_q_params = 2*self.n_qubits
        elif circno == 3:
          self.num_q_params = 3*self.n_qubits - 1
        elif circno == 9:
          self.num_q_params = self.n_qubits
        elif circno == 10:
          self.num_q_params = 2*self.n_qubits
        self.q_params = torch.nn.Parameter(2*np.pi*torch.rand(self.filters,self.num_q_params).cuda()).to('cuda')
        self.q_params.requires_grad = True
        if self.qc:
          self.circno = circno
        else:
          self.circno = 0

    def forward(self, inputs):
        if self.qc == True:
          out = torch.zeros((BATCH_SIZE,self.filters,12,12)).cuda()
          for bat, image in enumerate(inputs):
              image = image.cuda()
              for j in range(1, 13, 1):
                  for k in range(1, 13, 1):
                      for i in range(self.filters):
                          q_results = pqc(
                          [
                              image[0, j - 1, k - 1].item(),
                              image[0, j - 1, k].item(),
                              image[0, j - 1, k + 1].item(),
                              image[0, j, k - 1].item(),
                              image[0, j, k].item(),
                              image[0, j, k + 1].item(),
                              image[0, j + 1, k - 1].item(),
                              image[0, j + 1, k].item(),
                              image[0, j + 1, k + 1].item()
                          ],
                              self.q_params[i],
                              circno=self.circno
                          )
                          out[bat,i,j - 1, k - 1] = q_results.cuda()
        else:
          out = torch.zeros((BATCH_SIZE,self.filters,14,14))
          out = inputs
        # print(out.size())
        if self.opt==True:
          out = self.conv_opt(inputs)
        # print("out", out.type)
        x = self.pool(F.relu(self.conv1(out)))
        # print("x", x.type)
        # print(x.size())
        x = self.pool(F.relu(self.conv2(x)))
        x = torch.flatten(x,1)
        # print(x.size())
        x = F.relu(self.fc1(x))
        x = self.dropout(x)
        x = F.softmax(self.fc2(x))
        return x.cuda()


# !pip3 install --upgrade torch
from torchsummary import summary
criterion = torch.nn.CrossEntropyLoss()
model = QuanvNet(qc=True,opt=False)
if use_cuda:
    model.cuda()
opt = optim.Adam(model.parameters(),lr=0.01)
summary(model,(1,14,14))
for p in model.parameters():
    print(p.shape)
def save_data_file(file_name,qc=True,opt=False,circno=9, **kwargs):
  criterion = torch.nn.CrossEntropyLoss()
  if use_cuda:
    model = QuanvNet(qc=qc,opt=opt,circno=circno).cuda()
  else:
    model = QuanvNet(qc=qc,opt=opt,circno=circno)
  opt = optim.Adam(model.parameters(),lr=0.01)
  losses = []
  train_accs = []
  test_accs = []
  for epoch in range(1000):
    train_loss = 0
    train_acc = 0
    for (x_train, y_train) in train_loader:
      # print(y_train)
      opt.zero_grad()
      outputs = model(x_train.cuda() if use_cuda else x_train)
      _, preds = torch.max(outputs,1)
      train_acc += (preds==(y_train.cuda() if use_cuda else y_train)).sum().item()
      loss = criterion(outputs,(y_train.cuda() if use_cuda else y_train))
      loss.backward()
      opt.step()
      train_loss += loss
      del loss
    train_acc /= n_train
    train_loss /= (n_train/BATCH_SIZE)
    if epoch%10 == 9:
      train_accs.append(train_acc)
      if epoch%100 == 99:
        print(epoch+1,train_loss,train_acc)
      losses.append(train_loss.item())
    if epoch%10 == 9:
      test_acc = 0
      for (x_test, y_test) in test_loader:
        outputs = model(x_test.cuda() if use_cuda else x_test)
        _, preds = torch.max(outputs,1)
        test_acc += (preds==(y_test.cuda() if use_cuda else y_test)).sum().item()
      test_acc /= n_test
      test_accs.append(test_acc)
      if epoch%100 == 99:
        print("test_acc: ", test_acc)
  file = pd.DataFrame(data = {'train_loss': losses,
                              'train_acc': train_accs,
                              'test_acc': test_accs})
  file.to_pickle(SAVE_PATH+file_name)

save_data_file('qnn_circ2_1000_epoch.pkl',qc=True,opt=False,circno=2)
cnn_data = pd.read_pickle(SAVE_PATH+'qnn_circ2_1000_epoch.pkl')
from matplotlib.pyplot import plot
data_file = cnn_data
x = np.arange(0,1000,10)
plot(x,data_file['train_loss'])
plot(x,data_file['train_acc'])
plot(x,data_file['test_acc'])
x = np.arange(0,10000,10)
plot(x,accs)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12870193755647025, 'fraction_numerical': 0.03242646320650537, 'mean_word_length': 2.068062827225131, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '628347', 'license': 'MIT', 'n_tokens_mistral': 3638, 'n_tokens_neox': 3434, 'n_words': 635, 'path': 'QNN_PQC.ipynb', 'repo_name': 'JadeKim/2021QuantumHackatonKorea', 'size': '10084'}