# Hamiltonian -> Sparse Matrix or expval wrt state

I see that there is a `matrix` method attached to the `qml.Hamiltonian` class, but it is not implemented. I am attempting to use a custom loss function for a VQE type computation, and I have a statevector that I’d like to use to compute exp vals wrt. But there’s no obvious way to do this.

Given a statevector `sv` and a Hamiltonian `H`, there’s no API for computing `<H>` wrt `sv`.

Also, can I use a custom loss function for autograd after using `qml.sample`?

The idea is this:

``````
def hc(mat :np.ndarray) -> np.ndarray:
return np.conj(mat.transpose())

symbols = ["H", "H"]
coordinates = np.array([0.0, 0.0, -0.6614, 0.0, 0.0, 0.6614])
h2_ham, n_qubits = qchem.molecular_hamiltonian(symbols, coordinates)
n_electrons = 2

singles, doubles = qchem.excitations(n_electrons, n_qubits)
s_wires, d_wires = qchem.excitations_to_wires(singles, doubles)
ref_state = qchem.hf_state(n_electrons, n_qubits)
ansatz = partial(UCCSD, init_state = ref_state, s_wires = s_wires, d_wires = d_wires)

dev_noisy = qml.device('default.mixed', wires = n_qubits, shots = 2)
@qml.qnode(dev_noisy)
def VQE_circuit(params, group, n_qubits):
ansatz(params, wires=range(n_qubits))
rotations = qml.grouping.diagonalize_qwc_pauli_words(group)[0]
return qml.sample(wires=range(n_qubits))

params = np.random.randn(len(s_wires) + len(d_wires))
@qml.qnode(dev_noisy)
def cost(params, H):
results = [[VQE_circuit(params, group = group, n_qubits = n_qubits)] for group in groupings]
all_statevecs = process_results(results)
psi = train(model, all_statevecs, callback_list=callbacks)
#THIS LINE DOESN'T WORK
loss = hc(psi)@H.matrix()@psi
return loss

``````

where `psi` is the result from training a tensorflow `model` on the data from `VQE_circuit`.

Hi @cuhrazatee! As of the latest version of PL (version 0.18), you can now specify `expval(H)` directly within your QNode:

``````@qml.qnode(dev_noisy)
def VQE_circuit(params, n_qubits):
ansatz(params, wires=range(n_qubits))
return qml.expval(H)
``````

As you are using finite-shots, the grouping and diagonalization will occur automatically under the hood.

Alternatively, if you would like to continue as-is but extract the Hamiltonian numeric representation, can you use the `qml.utils.sparse_hamiltonian()` function:

``````>>> coeffs = [0.2, -0.543]
>>> ops = [
...   qml.PauliX(0) @ qml.PauliZ(1),
... ]
>>> H = qml.Hamiltonian(coeffs, ops)
>>> Hmat = qml.utils.sparse_hamiltonian(H).real
>>> Hmat
<4x4 sparse matrix of type '<class 'numpy.float64'>'
with 12 stored elements in COOrdinate format>
``````

You can then use sparse matrix multiplication, or convert it into a dense array:

``````>>> Hmat.toarray()
array([[-0.38395898, -0.38395898,  0.2       ,  0.        ],
[-0.38395898,  0.38395898,  0.        , -0.2       ],
[ 0.2       ,  0.        ,  0.38395898,  0.38395898],
[ 0.        , -0.2       ,  0.38395898, -0.38395898]])
``````