# Checking the version of PYTHON; we only support > 3.5
import sys
if sys.version_info < (3,5):
    raise Exception('Please use Python version 3.5 or greater.')

from qiskit import QuantumProgram
import math
#import Qconfig
#Define a QuantumProgram object 
Q_program = QuantumProgram()
#Q_program.set_api(Qconfig.APItoken, Qconfig.config['url'])
pi = math.pi


def solve_linear_sys():  

   #Q_program.set_api(Qconfig.APItoken, Qconfig.config['url'])     
        
    # create Quantum Register called "qr" with 4 qubits
    qr = Q_program.create_quantum_register("qr", 4)
    # create Quantum Register called "cr" with 4 qubits
    cr = Q_program.create_classical_register("cr", 4)
    # Creating Quantum Circuit called "qc" involving your Quantum Register "qr"
    # and your Classical Register "cr"
    qc = Q_program.create_circuit("solve_linear_sys", [qr], [cr])        
    
    # Initialize times that we get the result vector 
    n0 = 0
    n1 = 0
    
    for i in range(10):
        #Set the input|b> state"
        qc.x(qr[2])
        
        #Set the phase estimation circuit
        qc.h(qr[0])
        qc.h(qr[1]) 
        qc.u1(pi, qr[0])
        qc.u1(pi/2, qr[1])
        qc.cx(qr[1], qr[2])
    
        #The quantum inverse  Fourier transform 
        qc.h(qr[0])
        qc.cu1(-pi/2, qr[0], qr[1])
        qc.h(qr[1])
    
        #R（lamda^-1） Rotation
        qc.x(qr[1])
        qc.cu3(pi/16, 0, 0, qr[0], qr[3])
        qc.cu3(pi/8, 0, 0, qr[1], qr[3])   
    
        #Uncomputation
        qc.x(qr[1])
        qc.h(qr[1])
        qc.cu1(pi/2, qr[0], qr[1])
        qc.h(qr[0])
    
        qc.cx(qr[1], qr[2])
        qc.u1(-pi/2, qr[1])
        qc.u1(-pi, qr[0])
    
        qc.h(qr[1]) 
        qc.h(qr[0])
         
        # To measure the whole quantum register
        qc.measure(qr[0], cr[0])
        qc.measure(qr[1], cr[1])
        qc.measure(qr[2], cr[2])
        qc.measure(qr[3], cr[3])

        result = Q_program.execute("solve_linear_sys", shots=8192, backend='local_qasm_simulator')   
        
        # Get the sum og all results
        n0 = n0 + result.get_data("solve_linear_sys")['counts']['1000']
        n1 = n1 + result.get_data("solve_linear_sys")['counts']['1100']
    
        # print the result
        print(result)
        print(result.get_data("solve_linear_sys"))
        
                
        # Reset the circuit
        qc.reset(qr)
    
    # calculate the scale of the elements in result vectot and print it.
    p = n0/n1
    print(n0)
    print(n1)
    print(p)


# The test function
if __name__ == "__main__":
    solve_linear_sys()


%run "../version.ipynb"