Krylov subspace & Green’s functions¶
InQuanto offers built-in support for measuring the moments of an operator to calculate
quantities within a Krylov subspace, such as the Lanczos representation of a
Hamiltonian or the Green’s function. The key computable class for this is the
KrylovSubspaceComputable
, which is an example
of a composite computable from the inquanto.computables.composite
submodule.
Given an operator and a state, this computable evaluates to a
series of moments as the expectation values of the powers of the operator.
We can demonstrate this using a simple 2-site Hubbard model. First, we prepare the necessary state and operator:
from inquanto.computables.composite import KrylovSubspaceComputable
from inquanto.express import DriverHubbardDimer
from inquanto.operators import FermionOperator
from inquanto.ansatzes import FermionSpaceAnsatzChemicallyAwareUCCSD
driver = DriverHubbardDimer(t=0.3, u=2.15)
hamiltonian, space, state = driver.get_system()
qubit_hamiltonian = hamiltonian.qubit_encode()
ansatz = FermionSpaceAnsatzChemicallyAwareUCCSD(space, state)
parameters = ansatz.state_symbols.construct_random(2, 0.01, 0.1)
The computable can be instantiated as follows, where the Krylov space is expanded up to rank 4:
krylov_subspace_computable = KrylovSubspaceComputable(ansatz, qubit_hamiltonian, 4)
Once we have the computable, we can use a protocol to measure it. Since the
KrylovSubspaceComputable
calculates expectation values, we may use the PauliAveraging
protocol:
from inquanto.protocols import PauliAveraging
from pytket.partition import PauliPartitionStrat
from pytket.extensions.qiskit import AerBackend
protocol = PauliAveraging(
AerBackend(),
shots_per_circuit=10000,
pauli_partition_strategy=PauliPartitionStrat.CommutingSets,
)
protocol.build_from(parameters, krylov_subspace_computable)
protocol.compile_circuits()
protocol.run(seed=2)
<inquanto.protocols.averaging._pauli_averaging.PauliAveraging at 0x7f44017b1310>
Building the protocol from the Krylov subspace computable generates all measurement circuits,
and running the protocol submits circuits to the backend and retrieves results. We may then inspect
the protocol via dataframe helper methods, and use the evaluator to generate a
KrylovSubspace
:
print("Measurements:")
print(protocol.dataframe_measurements())
print("Circuits measured:")
print(protocol.dataframe_circuit_shot())
krylov_subspace = krylov_subspace_computable.evaluate(evaluator=protocol.get_evaluator())
Measurements:
Pauli string Mean Standard error Sample size
0 Z0 X1 X3 -0.0970 0.009953 10000
1 Z2 0.8812 0.004728 10000
2 X0 X1 Y2 Y3 -0.4608 0.008875 10000
3 Z0 X1 Z2 X3 -0.1606 0.009871 10000
4 X0 Z1 X2 Z3 0.1628 0.009867 10000
5 Z0 Z1 -0.9844 0.001760 10000
6 Z0 Z3 0.9844 0.001760 10000
7 Z0 Z1 Z2 -0.8786 0.004776 10000
8 Z0 Y1 Y3 -0.0970 0.009953 10000
9 Y0 Z1 Y2 -0.1114 0.009938 10000
10 X0 Y1 Y2 X3 0.4608 0.008875 10000
11 Y0 Z1 Y2 Z3 0.1628 0.009867 10000
12 X0 Z1 X2 -0.1114 0.009938 10000
13 Y1 Y3 0.1606 0.009871 10000
14 Y0 Y2 Z3 0.1114 0.009938 10000
15 Z0 Z1 Z2 Z3 1.0000 0.000000 10000
16 X0 X2 -0.1628 0.009867 10000
17 Z0 Z2 Z3 0.8786 0.004776 10000
18 Y0 Y2 -0.1628 0.009867 10000
19 Z0 Z1 Z3 0.8812 0.004728 10000
20 Y0 X1 X2 Y3 0.4608 0.008875 10000
21 Z0 -0.8812 0.004728 10000
22 Y1 Z2 Y3 0.0970 0.009953 10000
23 Z3 -0.8786 0.004776 10000
24 Z1 Z2 Z3 -0.8812 0.004728 10000
25 Z0 Z2 -1.0000 0.000000 10000
26 Z1 Z2 0.9844 0.001760 10000
27 X0 Y1 X2 Y3 -0.4764 0.008793 10000
28 Z1 Z3 -1.0000 0.000000 10000
29 Z0 Y1 Z2 Y3 -0.1606 0.009871 10000
30 Y0 X1 Y2 X3 -0.4764 0.008793 10000
31 Y0 Y1 Y2 Y3 -0.4764 0.008793 10000
32 X1 Z2 X3 0.0970 0.009953 10000
33 Y0 Y1 X2 X3 -0.4608 0.008875 10000
34 X0 X1 X2 X3 -0.4764 0.008793 10000
35 Z2 Z3 -0.9844 0.001760 10000
36 X1 X3 0.1606 0.009871 10000
37 X0 X2 Z3 0.1114 0.009938 10000
38 Z1 0.8786 0.004776 10000
Circuits measured:
Qubits Depth Count Depth2q Count2q DepthCX CountCX Shots
0 4 46 58 25 25 25 25 10000
1 4 54 75 32 35 32 35 10000
2 4 45 58 25 25 25 25 10000
Sum - - - - - - - 30000
krylov_subspace
is an instance of the KrylovSubspace
class that offers various methods to calculate eigenvalues, Lanczos coefficients,
Green’s functions, and more.
print("Eigenvalues of the Lanczos matrix:", krylov_subspace.eigenvalues())
exact = qubit_hamiltonian.eigenspectrum(hamming_weight=state.single_term.hamming_weight)
print("Exact diagonalization: ", exact)
Eigenvalues of the Lanczos matrix: [-0.156 0. 2.15 2.306]
Exact diagonalization: [-0.156 -0. -0. 0. 2.15 2.306]