from qiskit import QuantumRegister, ClassicalRegister
from qiskit import QuantumCircuit, execute, Aer, IBMQ
from qiskit.visualization import plot_histogram, plot_bloch_multivector

import numpy as np
import pylab as plt



def NOT(input_bit):
    
    # initialize the QC
    q = QuantumRegister(1)
    c = ClassicalRegister(1)
    qc = QuantumCircuit(q,c)
    
    # for input 1 flip the q[0] to 1
    if input_bit=='1':
        qc.x(q[0])

    # now do a NOT gate by flipping the q[0]
    qc.x(q[0])
    qc.measure( q[0], c[0] )
    # now exectue the circuit
    backend = Aer.get_backend('qasm_simulator')
    counts = execute(qc,backend,shots=1000).result().get_counts()
    
    return counts
    
NOT('1')  

def XOR(input1, input2):
    
    # initialize the QC
    q = QuantumRegister(2)
    c = ClassicalRegister(1)
    qc = QuantumCircuit(q,c)
    
    ####################################
    # 
    # DO something here... 
    # the code in the book doesn't do anything
    # so it gives 0 always irrespective of the inputs
    ####################################

    
    qc.measure( q[1], c[0] )
    # now exectue the circuit
    backend = Aer.get_backend('qasm_simulator')
    
    counts = execute(qc,backend,shots=1000, memory=True).result().get_memory()[0]
    
    return counts
    
XOR('1', '1')

def AND(input1, input2):
    
    # initialize the QC
    q = QuantumRegister(3)
    c = ClassicalRegister(1)
    qc = QuantumCircuit(q,c)
    
    ####################################    
    # 
    # DO something here... 
    # the code in the book only gives 0 always 
    ####################################
    
    qc.measure( q[2], c[0] )
    # now exectue the circuit
    backend = Aer.get_backend('qasm_simulator')
    
    counts = execute(qc,backend,shots=1000, memory=True).result().get_memory()[0]
    
    return counts
    
XOR('1', '1')

def AND(input1,input2):
    
    q = QuantumRegister(3) # two qubits in which to encode the input, and one for the output
    c = ClassicalRegister(1) # a bit to store the output
    qc = QuantumCircuit(q, c) # this is where the quantum program goes
    
    # YOUR QUANTUM PROGRAM GOES HERE
    qc.measure(q[2],c[0]) # YOU CAN CHANGE THIS IF YOU WANT TO
    
    # We'll run the program on a simulator
    backend = Aer.get_backend('qasm_simulator')
    # Since the output will be deterministic, we can use just a single shot to get it
    job = execute(qc,backend,shots=1,memory=True)
    output = job.result().get_memory()[0]
    
    return output