<jupyter_start><jupyter_text>Get non-contextual H<jupyter_code>nonH_guesses = c.greedy_dfs(ham, 10, criterion='weight')

nonH = max(nonH_guesses, key=lambda x:len(x)) # largest nonCon part found by dfs alg<jupyter_output><empty_output><jupyter_text>Split into:$$H = H_{c} + H_{nc}$$<jupyter_code>nonCon_H = {}
Con_H = {}

for P in ham:
    if P in nonH:
        nonCon_H[P]=ham[P]
    else:
        Con_H[P]=ham[P]<jupyter_output><empty_output><jupyter_text>Testing contextuality<jupyter_code>print('Is NONcontextual correct:', not c.contextualQ_ham(nonCon_H))
print('Is contextual correct:',c.contextualQ_ham(Con_H))<jupyter_output>Is NONcontextual correct: True
Is contextual correct: True<jupyter_text>Classical part of problem! Take $H_{nc}$ and split into:- $Z$ = operators that completely comute with all operators in $S$- $T$ = remaining operators in $S$    - where $S = Z \cup T$  and $S$ is set of Pauli operators in $H_{nc}$        - We then split the set $T$ into cliques $C_{1}, C_{2}, ... , C_{|T|}$    - all ops in a clique commute    - ops between cliques anti-commute!<jupyter_code>bool_flag, Z_list, T_list = c.contextualQ(list(nonCon_H.keys()), verbose=True)
Z_list
T_list<jupyter_output><empty_output><jupyter_text>Get quasi modelFirst we define- $C_{i1}$ = first Pauli in each $C_{i}$ set- $A_{ij} = C_{ij}C_{1i}$- $G^{prime} = \{1 P_{i} \;| \; i=1,2,...,|Z| \}$    - aka all the completely commuting terms with coefficients set to +1!- We define G to be an independent set of $G^{prime}$    - where $G \subseteq G^{prime}$<jupyter_code>G_list, Ci1_list, all_mappings = c.quasi_model(nonCon_H)
print('non-independent Z list:', Z_list)
print('G (independent) Z list:', G_list)
print('all Ci1 terms:', Ci1_list)<jupyter_output>all Ci1 terms: ['IIZ', 'XXX']<jupyter_text>$$R = G \cup \{ C_{i1} \;| \; i=1,2,...,N \}$$<jupyter_code># Assemble all the mappings from terms in the Hamiltonian to their products in R:
all_mappings<jupyter_output><empty_output><jupyter_text>Overall $R$ is basically reduced non-contextual set- where everything in original non-contextual set can be found by **inference!**  Function form$$R = G \cup \{ C_{i1} \;| \; i=1,2,...,N \}$$- note q to do with $G$- note r to do with $C_{i1}$<jupyter_code>model = [G_list, Ci1_list, all_mappings]

fn_form = c.energy_function_form(nonCon_H, model)

# returns [
#            denstion of q,
#            dimension of r,
#            [coeff, indices of q's, indices of r's, term in Hamiltonian]
#         ]

fn_form
Energy_function = c.energy_function(fn_form)
import random

### now for the q terms we only have +1 or -1 assignment!
q_variables = [random.choice([1,-1]) for _ in range(fn_form[0])]


### r variables is anything that makes up unit vector!
r_variables = c.angular(np.arange(0,2*np.pi, fn_form[1]))
r_variables
 Energy_function(*q_variables,*r_variables)<jupyter_output><empty_output><jupyter_text>find_gs_nonconfunction optimizes above steps by:1. brute forcing all choices of ```q_variables```    - ```itertools.product([1,-1],repeat=fn_form[0])```2. optimizing over ```r_variables``` (in code ```x```)    - using SciPy optimizer!<jupyter_code>model = [G_list, Ci1_list, all_mappings]

lowest_eigenvalue, ground_state_params, model_copy, fn_form_copy,  = c.find_gs_noncon(nonCon_H,
               method = 'differential_evolution',
               model=model,
               fn_form=fn_form) # returns:  best + [model, fn_form]

print(lowest_eigenvalue)
print(ground_state_params)
## check
Energy_function(*ground_state_params[0],*ground_state_params[1]) == lowest_eigenvalue<jupyter_output><empty_output><jupyter_text>Now need to rotate Hamiltonian! We now have non contextual ground state: $(\vec{q}, \vec{r})$<jupyter_code>ground_state_params<jupyter_output><empty_output><jupyter_text>We can use this result - ground state of $H_{nc}$ -  as a classical estiamte of our ground state of the full Hamiltonian ($H = H_{c} + H_{nc}$)However we can also obtain a quantum correction using $H_{c}$By minimizing theenergy of the remaining terms in the Hamiltonian over the quantum states that are **consistent with the noncon-textual ground state**. To do this we first rotate each $G_{j}$ and $\mathcal{A} = \sum_{i=1}^{N} r_{i}A_{i}$:<jupyter_code>model = [G_list, Ci1_list, all_mappings]

print(G_list) # G_j terms!
print(Ci1_list) # mathcal(A)<jupyter_output>['ZIZ', 'IZZ']
['IIZ', 'XXX']<jupyter_text>to SINGLE QUBIT pauli Z operators!- to map the operators in $G$ to single qubit Pauli operators, we use $\frac{\pi}{2}$ rotations!- note $\mathcal{A}$ is an anti-commuting set... therefore we can use $N-1$ rotations as in unitary partitioning's sequence of rotations to do this!    - $R^{\dagger}\mathcal{A} R = \text{single Pauli op}$  Rotate full Hamiltonian to basis with diagonal noncontextual generators! function ```diagonalize_epistemic```:1. first if else statement:    - if cliques present:        - first maps A to single Pauli operator (if cliques present)        - then rotates to diagonlize G union with single Pauli opator of A (hence GuA name!)    - else if NO cliques present:        - gets rotations to diagonlize G             - these rotations make up GuA term in code!2. NEXT code loops over terms in GuA (denoted as g in code)    - if g is not a single qubit $Z$:        - code generates code to rotate operator to make g diagonal (rotations)        - then constructs map of g to single Z (J rotation)    - Note R is applied to GuA        - Note rotations are given in Appendix A of https://arxiv.org/pdf/2011.10027.pdf    - First code checks if g op in GuA is diagonal        - if so then needs to apply "K" rotation (involving $Y$ and $I$ operators (see pg 11 top) to make it NOT diagononal    - now operator will be diagnoal!    - next generate "J" rotation        - turns non-diagonal operator into a single qubit $Z$ operator!<jupyter_code># Get sequence of rotations requried to diagonalize the generators for the noncontextual ground state!

Rotations_list, diagonalized_generators_GuA, eigen_vals_nonC_ground_state_GuA_ops = c.diagonalize_epistemic(model,
                                                                                                            fn_form,
                                                                                                            ground_state_params)
# rotations to map A to single Pauli operator!
Rotations_list
# rotations to diagonlize G
diagonalized_generators_GuA
eigen_vals_nonC_ground_state_GuA_ops
# for rotation in Rotations_list:
#     for p in ham:
#         if not c.commute(rotation[1],p):
#             print(rotation)
#     print()
model = [G_list, Ci1_list, all_mappings]
ham_noncon = hamiltonians[mol_key][3]

lowest_eigenvalue, ground_state_params, model_copy, fn_form_copy,  = c.find_gs_noncon(
               ham_noncon,#nonCon_H,
               method = 'differential_evolution',
               model=model,
               fn_form=fn_form) # returns:  best + [model, fn_form]<jupyter_output><empty_output><jupyter_text>Will's method<jupyter_code>ham_noncon = hamiltonians[mol_key][3]
n_qubits = hamiltonians[mol_key][1]
true_gs= hamiltonians[mol_key][4]

true_gs, approxs_out, errors_out, order_out = c.csvqe_approximations_heuristic(ham,
                                                                                   ham_noncon,
                                                                                   n_qubits, 
                                                                                   true_gs)
order_out
errors_out
### old way
# order = list(range(hamiltonians[mol_key][1]))
order = order_out
red_H = c.get_reduced_hamiltonians(ham,
                           model,
                           fn_form,
                           ground_state_params,
                           order)
len(red_H)
list(range(hamiltonians[mol_key][1]))
red_H[2]
approxs_out<jupyter_output><empty_output><jupyter_text>MY way  - SeqRot<jupyter_code>import cs_vqe_with_SeqRot as c_SeqRot
ham_noncon = hamiltonians[mol_key][3]
n_qubits = hamiltonians[mol_key][1]
true_gs= hamiltonians[mol_key][4]

true_gs, approxs_out, errors_out, order_out = c_SeqRot.csvqe_approximations_heuristic_SeqRot(ham,
                                                                                   ham_noncon,
                                                                                   n_qubits, 
                                                                                   true_gs)

from copy import deepcopy 
updated_order = deepcopy(order_out)
updated_order
errors_out

red_H_SeqRot = c_SeqRot.get_reduced_hamiltonians_SeqRot(ham,
                           model,
                           fn_form,
                           ground_state_params,
                           updated_order,
                          check_reduction=True)#order)
len(red_H_SeqRot)
red_H_SeqRot[2]
red_H[2]<jupyter_output><empty_output><jupyter_text>Check energies<jupyter_code>hamilt_ind = 0
# red_H[hamilt_ind]
import conversion_scripts as conv_scr

H = conv_scr.Get_Openfermion_Hamiltonian(red_H[hamilt_ind])
sparseH = qubit_operator_sparse(H, n_qubits=hamiltonians[mol_key][1])
# sp.sparse.linalg.eigsh(sparseH, which='SA', k=1)[0][0]
min(np.linalg.eigvalsh(sparseH.todense()))
H = conv_scr.Get_Openfermion_Hamiltonian(red_H_SeqRot[hamilt_ind])
sparseH = qubit_operator_sparse(H, n_qubits=hamiltonians[mol_key][1])
# sp.sparse.linalg.eigsh(sparseH, which='SA', k=1)[0][0]
min(np.linalg.eigvalsh(sparseH.todense()))
H = conv_scr.Get_Openfermion_Hamiltonian(ham)
sparseH = qubit_operator_sparse(H, n_qubits=hamiltonians[mol_key][1])
# sp.sparse.linalg.eigsh(sparseH, which='SA', k=1)[0][0]
min(np.linalg.eigvalsh(sparseH.todense()))<jupyter_output><empty_output><jupyter_text>MY way  - LCU<jupyter_code>import cs_vqe_with_LCU as c_LCU
ham_noncon = hamiltonians[mol_key][3]
n_qubits = hamiltonians[mol_key][1]
true_gs= hamiltonians[mol_key][4]
N_index=0
gs_true, approxs_out, errors_out, order_out = c_LCU.csvqe_approximations_heuristic_LCU(ham, 
                                                                                       ham_noncon, 
                                                                                       n_qubits,
                                                                                       true_gs,
                                                                                       check_reduction=True)

from copy import deepcopy 
updated_order = deepcopy(order_out)
updated_order
approxs_out
nonCon_H == hamiltonians[mol_key][3] # something odd here!
model = [G_list, Ci1_list, all_mappings]

lowest_eigenvalue, ground_state_params, model_copy, fn_form_copy,  = c.find_gs_noncon(nonCon_H,
               method = 'differential_evolution',
               model=model,
               fn_form=fn_form) # returns:  best + [model, fn_form]

print(lowest_eigenvalue)
print(ground_state_params)

red_H_LCU = c_LCU.get_reduced_hamiltonians_LCU(ham,
                           model,
                           fn_form,
                           ground_state_params,
                           updated_order,
                          check_reduction=True)#order)
len(red_H_LCU)
H = conv_scr.Get_Openfermion_Hamiltonian(red_H_LCU[1])
sparseH = qubit_operator_sparse(H, n_qubits=hamiltonians[mol_key][1])
# sp.sparse.linalg.eigsh(sparseH, which='SA', k=1)[0][0]
min(np.linalg.eigvalsh(sparseH.todense()))<jupyter_output><empty_output><jupyter_text>check H of different methods<jupyter_code>red_H_LCU[-2]
red_H_SeqRot[-2]
red_H[-2] # Will's way<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10459601621108908, 'fraction_numerical': 0.008364232128998879, 'mean_word_length': 2.8340495867768594, 'pattern_counts': {'":': 0, '<': 62, '<?xml version=': 0, '>': 62, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 44, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '16', 'dir': 'jupyter-structured-clean-dedup', 'id': '221005', 'license': 'MIT', 'n_tokens_mistral': 3892, 'n_tokens_neox': 3737, 'n_words': 880, 'path': 'Projects/CS_VQE/jupyter_notebooks/CS-VQE My SeqRot.ipynb', 'repo_name': 'AlexisRalli/VQE-code', 'size': '11597'}