<jupyter_start><jupyter_text>CS-VQE usageHere we run through a simple example of CS-VQE to simulate a small test molucule for varying quantum resource expenditure.<jupyter_code>import cs_vqe_classes.cs_vqe_circuit as cs_circ
import utils.cs_vqe_tools as cs_tools
import utils.plotting_tools as plot
from utils.molecule_tools import get_molecule
from matplotlib import pyplot as plt<jupyter_output>/home/tim/anaconda3/lib/python3.7/site-packages/qiskit/aqua/components/optimizers/optimizer.py:50: DeprecationWarning: The package qiskit.aqua.components.optimizers is deprecated. It was moved/refactored to qiskit.algorithms.optimizers (pip install qiskit-terra). For more information see <https://github.com/Qiskit/qiskit-aqua/blob/master/README.md#migration-guide>
  'qiskit.algorithms.optimizers', 'qiskit-terra')<jupyter_text>First we construct the calculated molecule, obtaining the corresponding Hamiltonian and UCCSD Ansatz operator:<jupyter_code>speciesname = "C_STO-3G_SINGLET"
molecule    = get_molecule(speciesname)
num_qubits  = molecule['num_qubits']
ham         = molecule['hamiltonian']
uccsd       = molecule['uccsdansatz']

print('Num qubits:',   num_qubits)
print('Hamiltonian:',  ham)
print('UCCSD Ansatz:', uccsd)<jupyter_output>Num qubits: 10
Hamiltonian: {'IIIIIIIIII': (-24.43336166259357+0j), 'ZIIIIIIIII': (6.323494958088604+0j), 'YZYIIIIIII': (0.08374130177201292+0j), 'XZXIIIIIII': (0.08374130177201292+0j), 'IZIIIIIIII': (6.323494958088606+0j), 'IYZYIIIIII': (0.08374130177201289+0j), 'IXZXIIIIII': (0.08374130177201289+0j), 'IIZIIIIIII': (0.587253863444877+0j), 'IIIZIIIIII': (0.5872538634448765+0j), 'IIIIZIIIII': (0.39026732133668585+0j), 'IIIIIZIIII': (0.39026732133668635+0j), 'IIIIIIZIII': (0.3902673213366863+0j), 'IIIIIIIZII': (0.390267321336686+0j), 'IIIIIIIIZI': (0.3902673213366862+0j), 'IIIIIIIIIZ': (0.39026732133668607+0j), 'ZZIIIIIIII': (0.8780153541704965+0j), 'YIYIIIIIII': (0.09224795199275918+0j), 'XIXIIIIIII': (0.09224795199275918+0j), 'ZYZYIIIIII': (0.09224795199275918+0j), 'ZXZXIIIIII': (0.09224795199275918+0j), 'YXXYIIIIII': (0.015242871172763375+0j), 'YYXXIIIIII': (-0.015242871172763375+0j), 'XXYYIIIIII': (-0.015242871172763375+0j), 'XYYXIIIIII': (0.015242871172763375+0j), 'YXIIXYIIII': (0.0[...]<jupyter_text>Create a CS-VQE circuit instanceOur CS-VQE circuit class requires an input Hamiltonian, a noncontextual subset of terms therein, along with the number of qubits and electrons in the full system. The latter is necessary for determining the Hartree-Fock state to be used as the UCCSD reference. Optionally, we may specify the qubit inclusion order (by default the optimal ordering will be determined) and choose which rotations to perform (i.e. just those diagonalising G or the additional unitary partitioning A rotations).<jupyter_code>print('Hamiltonian is contextual?', cs_tools.contextualQ_ham(ham))
#terms_noncon = cs_tools.greedy_dfs(ham, 300, criterion='weight')[-1]
terms_noncon=['IIIIIIIIII', 'IZIIIIIIII', 'ZIIIIIIIII', 'ZZIIIIIIII', 'IIZIIIIIII', 'IIIZIIIIII', 'IIIIIZIIII', 'IIIIIIZIII', 'IIIIIIIIZI', 'IIIIIIIIIZ', 'IIIIIIIZII', 'IIIIZIIIII', 'ZIIZIIIIII', 'IZZIIIIIII', 'ZIIIIZIIII', 'ZIIIIIIZII', 'ZIIIIIIIIZ', 'IZIIZIIIII', 'IZIIIIZIII', 'IZIIIIIIZI', 'ZIIIZIIIII', 'ZIIIIIZIII', 'ZIIIIIIIZI', 'IZIIIZIIII', 'IZIIIIIZII', 'IZIIIIIIIZ', 'ZIZIIIIIII', 'IZIZIIIIII', 'IIIIZZIIII', 'IIIIIIZZII', 'IIIIIIIIZZ', 'IIZIIZIIII', 'IIZIIIIZII', 'IIZIIIIIIZ', 'IIIZZIIIII', 'IIIZIIZIII', 'IIIZIIIIZI', 'IIZZIIIIII', 'IIIIZIIZII', 'IIIIZIIIIZ', 'IIIIIZZIII', 'IIIIIZIIZI', 'IIIIIIZIIZ', 'IIIIIIIZZI', 'IIIIZIZIII', 'IIIIZIIIZI', 'IIIIIZIZII', 'IIIIIZIIIZ', 'IIIIIIZIZI', 'IIIIIIIZIZ', 'IIZIZIIIII', 'IIZIIIZIII', 'IIZIIIIIZI', 'IIIZIZIIII', 'IIIZIIIZII', 'IIIZIIIIIZ', 'YIYIIIIIII', 'XIXIIIIIII', 'YZYIIIIIII', 'XZXIIIIIII', 'YZYIZIIIII', 'XZXIZIIIII', 'YZYIIIZIII', 'XZXIIIZIII', 'YZYIIIIIZI', 'XZXIIIIIZI', 'YZYZIIIIII', 'XZXZIIIIII', 'YZYIIZIIII', 'XZXIIZIIII', 'YZYIIIIZII', 'XZXIIIIZII', 'YZYIIIIIIZ', 'XZXIIIIIIZ']
print(terms_noncon)
#H2 terms_noncon = ['IIIIIIII', 'IIIIIIZI', 'IIIIIIIZ', 'IIIIZIII', 'IIIIIZII', 'IIZIIIII', 'IIIZIIII', 'ZIIIIIII', 'IZIIIIII', 'IIIIIIZZ', 'ZIIIIIIZ', 'IZIIIIZI', 'ZZIIIIII', 'IIIIZIIZ', 'IIIIIZZI', 'ZIIIIZII', 'IZIIZIII', 'ZIIIIIZI', 'IZIIIIIZ', 'IIIIZZII', 'IIZIIIIZ', 'IIIZIIZI', 'ZIIZIIII', 'IZZIIIII', 'ZIIIZIII', 'IZIIIZII', 'IIIIZIZI', 'IIIIIZIZ', 'IIZZIIII', 'IIZIIZII', 'IIIZZIII', 'IIZIIIZI', 'IIIZIIIZ', 'IIZIZIII', 'IIIZIZII', 'YZZZYIII', 'XZZZXIII', 'ZIZIIIII', 'IZIZIIII', 'YZZZYIIZ', 'XZZZXIIZ', 'YIZZYIII', 'XIZZXIII', 'YZZZYZII', 'XZZZXZII', 'YZZZYIZI', 'XZZZXIZI', 'YZIZYIII', 'XZIZXIII', 'YZZIYIII', 'XZZIXIII']
#H3 terms_noncon = ['IIIIII', 'ZIIIII', 'IZIIII', 'IIIIZZ', 'IIZZII', 'ZZIIII', 'ZIIIIZ', 'IZIIZI', 'ZIIZII', 'IZZIII', 'IIZIIZ', 'IIIZZI', 'IIIIZI', 'IIIIIZ', 'IIIZII', 'IIZIII', 'IIZIZI', 'IIIZIZ', 'ZIIIZI', 'IZIIIZ', 'ZIZIII', 'IZIZII', 'YXIIXY', 'YYIIXX', 'XXIIYY', 'XYIIYX'] 
#BeH+ terms_noncon = ['IIIIIIIIIIII', 'ZIIIIIIIIIII', 'IZIIIIIIIIII', 'IIZIIIIIIIII', 'IIIZIIIIIIII', 'IIIIIIZIIIII', 'IIIIIIIZIIII', 'IIIIIIIIZIII', 'IIIIIIIIIZII', 'IIIIZIIIIIII', 'IIIIIZIIIIII', 'ZZIIIIIIIIII', 'IIIIIIIIIIZI', 'IIIIIIIIIIIZ', 'ZIIIIIIIIZII', 'IZIIIIIIZIII', 'ZIIIIIIZIIII', 'IZIIIIZIIIII', 'ZIIIIIIIZIII', 'IZIIIIIIIZII', 'ZIIIIIZIIIII', 'IZIIIIIZIIII', 'ZIIZIIIIIIII', 'IZZIIIIIIIII', 'ZIZIIIIIIIII', 'IZIZIIIIIIII', 'ZIIIIZIIIIII', 'IZIIZIIIIIII', 'ZIIIZIIIIIII', 'IZIIIZIIIIII', 'IIIIYZZZZZYI', 'IIIIXZZZZZXI', 'IIIIIIIIZZII', 'IIIIIIZZIIII', 'IIIIIIZIIZII', 'IIIIIIIZZIII', 'IIZIIIIIIZII', 'IIIZIIIIZIII', 'IIZIIIIZIIII', 'IIIZIIZIIIII', 'IIZZIIIIIIII', 'IIIIZZIIIIII', 'IIIIIIZIZIII', 'IIIIIIIZIZII', 'IIIIZIIIIZII', 'IIIIIZIIZIII', 'IIIIZIIZIIII', 'IIIIIZZIIIII', 'IIZIIZIIIIII', 'IIIZZIIIIIII', 'ZIIIIIIIIIIZ', 'IZIIIIIIIIZI', 'IIIIIIIIIIZZ', 'ZIIIIIIIIIZI', 'IZIIIIIIIIIZ', 'IIIIZIIIZIII', 'IIIIIZIIIZII', 'IIIIZIZIIIII', 'IIIIIZIZIIII', 'IIZIIIIIZIII', 'IIIZIIIIIZII', 'IIZIIIZIIIII', 'IIIZIIIZIIII', 'IIZIIIIIIIIZ', 'IIIZIIIIIIZI', 'IIIIZIIIIIIZ', 'IIIIIZIIIIZI', 'IIZIZIIIIIII', 'IIIZIZIIIIII', 'IIIIIIIIZIIZ', 'IIIIIIIIIZZI', 'IIIIIIZIIIIZ', 'IIIIIIIZIIZI', 'IIIIIIIIZIZI', 'IIIIIIIIIZIZ', 'IIIIIIZIIIZI', 'IIIIIIIZIIIZ', 'IIZIIIIIIIZI', 'IIIZIIIIIIIZ', 'IIIIZIIIIIZI', 'IIIIIZIIIIIZ', 'IZIIYZZZZZYI', 'IZIIXZZZZZXI', 'ZIIIYZZZZZYI', 'ZIIIXZZZZZXI', 'IIIIYZZZZIYI', 'IIIIXZZZZIXI', 'IIIIYZZIZZYI', 'IIIIXZZIZZXI', 'IIIIYZZZIZYI', 'IIIIXZZZIZXI', 'IIIIYZIZZZYI', 'IIIIXZIZZZXI', 'IIIIYIZZZZYI', 'IIIIXIZZZZXI', 'IIIZYZZZZZYI', 'IIIZXZZZZZXI', 'IIZIYZZZZZYI', 'IIZIXZZZZZXI', 'IIIIYZZZZZYZ', 'IIIIXZZZZZXZ']
mol_circ = cs_circ.cs_vqe_circuit(hamiltonian=ham,
                                  terms_noncon=terms_noncon,
                                  num_qubits=num_qubits)

print('Noncontextual ground state:', mol_circ.reference_state())<jupyter_output>Hamiltonian is contextual? True
['IIIIIIIIII', 'IZIIIIIIII', 'ZIIIIIIIII', 'ZZIIIIIIII', 'IIZIIIIIII', 'IIIZIIIIII', 'IIIIIZIIII', 'IIIIIIZIII', 'IIIIIIIIZI', 'IIIIIIIIIZ', 'IIIIIIIZII', 'IIIIZIIIII', 'ZIIZIIIIII', 'IZZIIIIIII', 'ZIIIIZIIII', 'ZIIIIIIZII', 'ZIIIIIIIIZ', 'IZIIZIIIII', 'IZIIIIZIII', 'IZIIIIIIZI', 'ZIIIZIIIII', 'ZIIIIIZIII', 'ZIIIIIIIZI', 'IZIIIZIIII', 'IZIIIIIZII', 'IZIIIIIIIZ', 'ZIZIIIIIII', 'IZIZIIIIII', 'IIIIZZIIII', 'IIIIIIZZII', 'IIIIIIIIZZ', 'IIZIIZIIII', 'IIZIIIIZII', 'IIZIIIIIIZ', 'IIIZZIIIII', 'IIIZIIZIII', 'IIIZIIIIZI', 'IIZZIIIIII', 'IIIIZIIZII', 'IIIIZIIIIZ', 'IIIIIZZIII', 'IIIIIZIIZI', 'IIIIIIZIIZ', 'IIIIIIIZZI', 'IIIIZIZIII', 'IIIIZIIIZI', 'IIIIIZIZII', 'IIIIIZIIIZ', 'IIIIIIZIZI', 'IIIIIIIZIZ', 'IIZIZIIIII', 'IIZIIIZIII', 'IIZIIIIIZI', 'IIIZIZIIII', 'IIIZIIIZII', 'IIIZIIIIIZ', 'YIYIIIIIII', 'XIXIIIIIII', 'YZYIIIIIII', 'XZXIIIIIII', 'YZYIZIIIII', 'XZXIZIIIII', 'YZYIIIZIII', 'XZXIIIZIII', 'YZYIIIIIZI', 'XZXIIIIIZI', 'YZYZIIIIII', 'XZXZIIIIII', 'YZYIIZIIII', '[...]<jupyter_text>Given the number of qubits we wish to simulate, our circ_vqe_circuit instance includes functionality for computing various parameters necessary for constructing a corresponding quantum circuit for our CS-VQE routine:<jupyter_code>num_sim_q = 2

print('Qubits Included in Simulation:', mol_circ.sim_qubits(num_sim_q)[0])
print('Mapping onto available qubits:', mol_circ.qubit_map(num_sim_q), '\n')
print('%i-qubit reduced Hamiltonian:'%num_sim_q, mol_circ.ham_reduced[num_sim_q], '\n')
print('%i-qubit reduced Ansatz:'%num_sim_q, mol_circ.project_anz_terms(uccsd, num_sim_q))<jupyter_output>Qubits Included in Simulation: (9, 8)
Mapping onto available qubits: {9: 1, 8: 0} 

2-qubit reduced Hamiltonian: {'II': (-31.286042760254222+0j), 'IZ': (5.678969362324752+0j), 'ZZ': (0.21314889573394402+0j), 'ZI': (0.44652933688658286+0j)} 

II
2-qubit reduced Ansatz: ({}, 'II')<jupyter_text>Constructing the CS-VQE circuitThe main feature of the cs_vqe_circuit class is its ability to construct a CS-VQE circuit (within Qiskit) given a specified Ansatz and the number of qubits to simulate. The method has been designed with modularity in mind, with the quantum circuit being defined in separate 'blocks' that can be selected at will. The current blocks that have been implemented are as follows:- **ref_state_block** initialises the circuit in the refernce state, typically HF_config though for smaller example one may wish to select the most significant basis state in the Hamiltonian spectrum- **anz_block** gets the reduced Ansatz (as above) and converts it into series of gates using functionality from utils.circuit_tools; by default it will be Trotterized with n_T=2.- **swap_entgl_block** requires an ancilla qubit and will fix a specified qubit to the single-qubit basis state |0> (typically this will be the 'X index' of the observable A, or if using unitary partitioning it will be the qubit position of the single Pauli Z therein). It does this at the expense of entangling the ancilla with the other qubits.- **rot_ham_block** implements the noncontextual generator rotations in the quantum circuit- **rot_A_block** implemetns only the unitary partitioning A rotations in the quantum circuit- **A_eig_block** uses functionality from utils.eigenstate and forces the quantum state into the +1-eigenspace of A - **parity_cascade_block** takes a list of qubits and stores their parity in an ancilla bit, then inserts an input circuit block before reversing the parity computation. It will also compensate for the 'lost parity' as a consequnce of reducing the simulation dimension by introducing an X gate on the ancilla conditional on the parity of qubits not included in the simulation (fixed by the noncontextual ground state).All of these blocks are compiled in the build_circuit method - let's see this in action...<jupyter_code>mol_circ.build_circuit(uccsd, 2).draw(output='mpl')
#fig.savefig("plots/usage_circuit.png", dpi=300)<jupyter_output><empty_output><jupyter_text>Executing the reduced CS-VQE circuitsFinally, we are able to execute our CS-VQE routine with the CS_VQE method, taking as input an Ansatz and the number of qubits to simulate. This returns a python dict with the simulation results:<jupyter_code>cs_vqe_results = mol_circ.CS_VQE(uccsd, num_sim_q)
plt.title('CS-VQE convergence'), plt.xlabel('Optimisation count'), plt.ylabel('Energy (Ha)')
X, Y = cs_vqe_results['counts'], cs_vqe_results['values']
plt.plot(X, Y)
plt.hlines(cs_vqe_results['target'], 0, X[-1], color='green')<jupyter_output>II
II
*   Performing 2-qubit CS-VQE over qubit positions 9, 8 ...<jupyter_text>Furthermore, if we wish to compare the CS-VQE results across different numbers of simulation qubits we can use run_cs_vqe, specifying the maximum number of qubits (and optionally the minumum number) to be included. The resulting data can be plotted with utils.plotting_tools.plot_cs_vqe_convergence.<jupyter_code>mol_circ.run_cs_vqe(uccsd, max_sim_q=num_qubits)
cs_vqe_results = mol_circ.cs_vqe_results
title = 'CS-VQE Convergence Test %s' % speciesname
fig = plot.plot_cs_vqe_convergence_alt(data=cs_vqe_results, title=title)
#fig.savefig("plots/FH-CS-VQE-uccsd_ansatz.png", dpi=300)
import json 

data={}
for k in cs_vqe_results.keys():
    data[str(k)] = cs_vqe_results[k]
     
with open("data/final/"+speciesname+"_UCCSD_CS-VQE_convergence_projected_ansatz.json", "w") as outfile: 
    json.dump(data, outfile)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.142717417882468, 'fraction_numerical': 0.045643491727117125, 'mean_word_length': 7.7831066571224055, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 26, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 96, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '345721', 'license': 'Apache-2.0', 'n_tokens_mistral': 5487, 'n_tokens_neox': 5035, 'n_words': 1083, 'path': 'misc/legacy/ipynb for development/usage-Copy2.ipynb', 'repo_name': 'wmkirby1/CS-VQE', 'size': '12269'}