from qiskit.algorithms import VQE
from qiskit.algorithms.optimizers import COBYLA
from qiskit.opflow import X, Y, Z, I, PauliSumOp
from qiskit.circuit.library import TwoLocal

from qiskit import Aer

import numpy as np

import qiskit_alt, qiskit_alt.electronic_structure
from qiskit_alt.pauli_operators import PauliSum_to_SparsePauliOp
from qiskit.opflow import PauliSumOp

# Describe the Hydrogen molecule by fixing the location of each nucleus
geometry = [['H', [0., 0., 0.]], ['H', [0., 0., 0.739]]]
basis = 'sto3g'

# Compute the Fermionic operator of the molecule 
fermi_op = qiskit_alt.electronic_structure.fermionic_hamiltonian(geometry, basis)

# Convert the Fermionic operator to a Pauli operator using the Jordan-Wigner transform
pauli_op = qiskit_alt.electronic_structure.jordan_wigner(fermi_op);

# Convert the Pauli operator into a sum of Pauli operators
# input to the VQE algorithm to compute the minimum eigenvalue
pauli_sum_op = PauliSumOp(pauli_op)
print(pauli_sum_op)

# Set up the ansatz of type TwoLOcal
ansatz = TwoLocal(num_qubits=4, 
                  rotation_blocks=['ry'], 
                  entanglement_blocks='cx', 
                  reps=1,
                  entanglement='linear', 
                  skip_final_rotation_layer= False)

# Initialize the COBYLA optimizer
optimizer = COBYLA(maxiter=500)

# Select the backend for the quantum_instance
backend = Aer.get_backend('aer_simulator_statevector')

# Run VQE algorithm
vqe = VQE(ansatz = ansatz, 
          optimizer = optimizer,
          quantum_instance = backend)

# Compute the ground-state energy of the molecule
result = vqe.compute_minimum_eigenvalue(operator=pauli_sum_op)
print("The ground-state energy of the Hydrogen molecule is {} Hatree".format(round(result.eigenvalue.real,3)))