from qiskit import QuantumRegister, ClassicalRegister, BasicAer
import numpy as np
import matplotlib.pyplot as plt
from qiskit import QuantumCircuit, execute,IBMQ
from qiskit.tools.monitor import job_monitor
from qiskit.circuit.library import NormalDistribution,UniformDistribution,LogNormalDistribution
from kaleidoscope import qsphere, probability_distribution

#provider = IBMQ.load_account()
#backend = provider.get_backend('ibmq_qasm_simulator')
backend = BasicAer.get_backend('qasm_simulator')

qubits = 5

q = QuantumRegister(qubits,'q')
c = ClassicalRegister(qubits,'c')

print("\n Normal Distribution")
print("-----------------")

circuit = QuantumCircuit(q,c)
normal = NormalDistribution(num_qubits = qubits, mu=0, sigma=0.1, bounds=([-1,1]))
circuit.append(normal, list(range(qubits)))
circuit.measure(q,c)

job = execute(circuit, backend, shots=8192)
job_monitor(job)
counts = job.result().get_counts()

print(counts)
sortedcounts = []
sortedkeys = sorted(counts)

for i in sortedkeys:
    for j in counts:
        if(i == j):
            sortedcounts.append(counts.get(j))

plt.suptitle('Normal Distribution')
plt.plot(sortedcounts)
plt.show()



probability_distribution(counts)

circuit.decompose().decompose().draw('mpl')

print("\n Uniform Distribution")
print("-----------------")

circuit = QuantumCircuit(q,c)
uniform = UniformDistribution(num_qubits = qubits)
circuit.append(uniform, list(range(qubits)))
circuit.measure(q,c)

job = execute(circuit, backend, shots=8192)
job_monitor(job)
counts = job.result().get_counts()

print(counts)

sortedcounts = []
sortedkeys = sorted(counts)

for i in sortedkeys:
    for j in counts:
        if(i == j):
            sortedcounts.append(counts.get(j))
            
plt.suptitle('Uniform Distribution')
plt.plot(sortedcounts)
plt.show()


probability_distribution(counts)

circuit.decompose().draw('mpl')

print("\n Log-Normal Distribution")
print("-----------------")

circuit = QuantumCircuit(q,c)
lognorm = LogNormalDistribution(num_qubits = qubits, mu=0.5, sigma=0.05, bounds=([0,4]))
circuit.append(lognorm, list(range(qubits)))
circuit.measure(q,c)

job = execute(circuit, backend, shots=8192)
job_monitor(job)
counts = job.result().get_counts()

print(counts)

sortedcounts = []
sortedkeys = sorted(counts)

for i in sortedkeys:
    for j in counts:
        if(i == j):
            sortedcounts.append(counts.get(j))

plt.suptitle('Log-Normal Distribution')
plt.plot(sortedcounts)
plt.show()

probability_distribution(counts)

from qiskit.finance.applications import GaussianConditionalIndependenceModel as GCI

print("\n Gaussian Conditional Independence Distribution")
print("-----------------")

# set problem parameters
n_z = qubits
z_max = qubits
#p_zeros = [0.15, 0.25, 0.09, 0.05, 0.01]
#rhos = [0.1, 0.05, 0.04, 0.03, 0.01]

p_zeros = [0.15, 0.25]
rhos = [0.1, 0.05]

circuit = GCI(n_z, z_max, p_zeros, rhos)

circuit.measure_all()

job = execute(circuit, backend, shots=8192)
job_monitor(job)
counts = job.result().get_counts()

print(counts)

sortedcounts = []
sortedkeys = sorted(counts)

for i in sortedkeys:
    for j in counts:
        if(i == j):
            sortedcounts.append(counts.get(j))

plt.suptitle('Log-Normal Distribution')
plt.plot(sortedcounts)
plt.show()



probability_distribution(counts)

from qiskit.aqua.algorithms import AmplitudeEstimation

estimation_qubits = 4
ae_lognormal = AmplitudeEstimation(estimation_qubits, state_preparation=lognorm)
ae_uniform = AmplitudeEstimation(estimation_qubits, state_preparation=uniform)
ae_normal = AmplitudeEstimation(estimation_qubits, state_preparation=normal)

result_lognormal = ae_lognormal.run(quantum_instance=BasicAer.get_backend('qasm_simulator'))
result_uniform = ae_uniform.run(quantum_instance=BasicAer.get_backend('qasm_simulator'))
result_normal = ae_normal.run(quantum_instance=BasicAer.get_backend('qasm_simulator'))

# plot estimated values

plt.bar(result_uniform['mapped_a_samples'], result_uniform['probabilities'], width=0.5/len(result_uniform['probabilities']))
plt.bar(result_lognormal['mapped_a_samples'], result_lognormal['probabilities'], width=0.5/len(result_lognormal['probabilities']))
#plt.bar(result_normal['mapped_a_samples'], result_normal['probabilities'], width=0.5/len(result_normal['probabilities']))
plt.xticks([0, 0.25, 0.5, 0.75, 1], size=15)
plt.yticks([0, 0.25, 0.5, 0.75, 1], size=15)
plt.title('Estimated Values', size=15)
plt.ylabel('Probability', size=15)
plt.ylim((0,1))
plt.grid()
plt.show()

print(result_lognormal)
print(result_uniform)
print(result_normal)

estimation_qubits = 7
ae_lognormal = AmplitudeEstimation(estimation_qubits, state_preparation=lognorm)
result_lognormal = ae_lognormal.run(quantum_instance=BasicAer.get_backend('qasm_simulator'))


plt.bar(result_lognormal['mapped_a_samples'], result_lognormal['probabilities'], width=0.5/len(result_lognormal['probabilities']))
plt.title('Estimated Values', size=15)
plt.ylabel('Probability', size=15)
plt.ylim((0,1))
plt.grid()

