import qiskit_alt
qiskit_alt.project.ensure_init(calljulia="pyjulia", compile=False, depot=True)

julia = qiskit_alt.project.julia
julia.Main.zeros(10)

from qiskit_nature.drivers import UnitsType, Molecule
from qiskit_nature.drivers.second_quantization import ElectronicStructureDriverType, ElectronicStructureMoleculeDriver

# Specify the geometry of the H_2 molecule
geometry = [['H', [0., 0., 0.]],
            ['H', [0., 0., 0.735]]]

basis = 'sto3g'

molecule = Molecule(geometry=geometry,
                     charge=0, multiplicity=1)
driver = ElectronicStructureMoleculeDriver(molecule, basis=basis, driver_type=ElectronicStructureDriverType.PYSCF)

from qiskit_nature.problems.second_quantization import ElectronicStructureProblem
from qiskit_nature.converters.second_quantization import QubitConverter
from qiskit_nature.mappers.second_quantization import JordanWignerMapper

es_problem = ElectronicStructureProblem(driver)
second_q_op = es_problem.second_q_ops()

fermionic_hamiltonian = second_q_op[0]

qubit_converter = QubitConverter(mapper=JordanWignerMapper())
nature_qubit_op = qubit_converter.convert(fermionic_hamiltonian)
nature_qubit_op.primitive

import qiskit_alt.electronic_structure
fermi_op = qiskit_alt.electronic_structure.fermionic_hamiltonian(geometry, basis)
pauli_op = qiskit_alt.electronic_structure.jordan_wigner(fermi_op)
pauli_op.simplify() # The Julia Pauli operators use a different sorting convention; we sort again for comparison. 

%run ../bench/jordan_wigner_nature_time.py
nature_times

%run ../bench/jordan_wigner_alt_time.py
alt_times

[t_nature / t_qk_alt for t_nature, t_qk_alt in zip(nature_times, alt_times)]

%run ../bench/fermionic_nature_time.py
nature_times

%run ../bench/fermionic_alt_time.py
alt_times

[t_nature / t_qk_alt for t_nature, t_qk_alt in zip(nature_times, alt_times)]

from qiskit_alt.pauli_operators import QuantumOps, PauliSum_to_SparsePauliOp
import numpy as np
m = np.random.rand(2**3, 2**3) # 3-qubit operator
pauli_sum = QuantumOps.PauliSum(m) # This is a wrapped Julia object
PauliSum_to_SparsePauliOp(pauli_sum) # Convert to qiskit.quantum_info.SparsePauliOp

%run ../bench/from_matrix_quantum_info.py

%run ../bench/from_matrix_alt.py

[t_pyqk / t_qk_alt for t_pyqk, t_qk_alt in zip(pyqk_times, qk_alt_times)]

%run ../bench/pauli_from_list_qinfo.py

%run ../bench/pauli_from_list_alt.py

[x / y for x,y in zip(quantum_info_times, qkalt_times)]

%load_ext julia.magic

%julia using Random: randstring
%julia pauli_strings = [randstring("IXYZ", 10) for _ in 1:1000]
None;

%julia import Pkg; Pkg.add("BenchmarkTools")
%julia using BenchmarkTools: @btime
%julia @btime QuantumOps.PauliSum($pauli_strings)
None;

%julia pauli_sum = QuantumOps.PauliSum(pauli_strings);
%julia println(length(pauli_sum))
%julia println(pauli_sum[1])

6.9 * 2.29 / .343  # Ratio of time to construct PauliSum via qiskit_alt to time in pure Julia

import qiskit.tools.jupyter
d = qiskit.__qiskit_version__._version_dict
d['qiskit_alt'] = qiskit_alt.__version__
%qiskit_version_table

