Skip to content

Commit bb4405a

Browse files
update timeevol tests and docs
1 parent 26f9a52 commit bb4405a

File tree

2 files changed

+151
-1
lines changed

2 files changed

+151
-1
lines changed

docs/source/advance.rst

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,151 @@ We support two modes of analog simulation, where :py:meth:`tensorcircuit.experim
149149
v, gs = hybrid_evol(b)
150150
151151
152+
Time Evolution
153+
------------------
154+
155+
TensorCircuit-NG provides several methods for simulating quantum time evolution, including exact diagonalization, Krylov subspace methods, and ODE-based approaches.
156+
These methods are essential for studying quantum dynamics, particularly in many-body systems, and all support automatic differentiation (AD) and JIT compilation for enhanced performance.
157+
158+
**Exact Diagonalization:**
159+
160+
For small systems where full diagonalization is feasible, the :py:meth:`tensorcircuit.timeevol.ed_evol` method provides exact time evolution by directly computing matrix exponentials:
161+
162+
.. code-block:: python
163+
164+
import tensorcircuit as tc
165+
166+
# Create Heisenberg Hamiltonian for a 4-site chain
167+
n = 4
168+
g = tc.templates.graphs.Line1D(n, pbc=False)
169+
h = tc.quantum.heisenberg_hamiltonian(g, hzz=1.0, hxx=1.0, hyy=1.0, sparse=False)
170+
171+
# Initial Neel state: |↑↓↑↓⟩
172+
c = tc.Circuit(n)
173+
c.x([1, 3]) # Apply X gates to qubits 1 and 3
174+
psi0 = c.state()
175+
176+
# Imaginary time evolution times
177+
times = tc.backend.convert_to_tensor([0.0, 0.5, 1.0, 2.0])
178+
179+
# Evolve and get states
180+
states = tc.timeevol.ed_evol(times, h, psi0)
181+
182+
183+
def evolve_and_measure(params):
184+
# Parametrized Hamiltonian
185+
h_param = tc.quantum.heisenberg_hamiltonian(
186+
g, hzz=params[0], hxx=params[1], hyy=params[2], sparse=False
187+
)
188+
states = tc.timeevol.hamiltonian_evol(times, h_param, psi0)
189+
# Measure observable on final state
190+
circuit = tc.Circuit(n, inputs=states[-1])
191+
return tc.backend.real(circuit.expectation_ps(z=[0]))
192+
193+
This method is particularly efficient for time-independent Hamiltonians as it uses eigendecomposition to compute the evolution.
194+
It provides exact results but is limited to small systems (typically <16 qubits) due to the exponential growth of the Hilbert space.
195+
196+
**Krylov Subspace Methods:**
197+
198+
For larger systems where exact diagonalization becomes intractable, the Krylov subspace method provides an efficient approximation.
199+
The :py:meth:`tensorcircuit.timeevol.krylov_evol` function implements this approach:
200+
201+
.. code-block:: python
202+
203+
import tensorcircuit as tc
204+
205+
# Create a Heisenberg Hamiltonian for a 1D chain
206+
n = 10
207+
g = tc.templates.graphs.Line1D(n, pbc=False)
208+
h = tc.quantum.heisenberg_hamiltonian(g, hzz=1.0, hxx=1.0, hyy=1.0, sparse=True)
209+
210+
# Initial domain wall state: |↑↑↑↑↑↓↓↓↓↓⟩
211+
c = tc.Circuit(n)
212+
c.x(range(n//2, n))
213+
psi0 = c.state()
214+
215+
# Real time evolution points
216+
times = tc.backend.convert_to_tensor([0.0, 0.5, 1.0, 2.0])
217+
218+
# Perform Krylov evolution with a 30-dimensional subspace
219+
states = tc.timeevol.krylov_evol(h, psi0, times, subspace_dimension=30)
220+
221+
# Krylov method also supports AD and JIT
222+
223+
def krylov_evolution(params):
224+
# Parametrized initial state
225+
c = tc.Circuit(n)
226+
for i in range(n):
227+
c.rx(i, theta=params[i])
228+
psi0_param = c.state()
229+
states = tc.timeevol.krylov_evol(h, psi0_param, [1.0], subspace_dimension=20)
230+
# Measure total magnetization
231+
circuit = tc.Circuit(n, inputs=states[0])
232+
mz = sum(circuit.expectation_ps(z=[i]) for i in range(n))
233+
return tc.backend.real(mz)
234+
235+
The Krylov method constructs a small subspace that captures the essential dynamics, making it possible to simulate larger systems efficiently.
236+
It supports both standard and scan-based jit-friendly implementations:
237+
238+
.. code-block:: python
239+
240+
# Standard implementation (default)
241+
states = tc.timeevol.krylov_evol(h, psi0, times, subspace_dimension=20, scan_impl=False)
242+
243+
# Scan-based implementation for better JIT performance
244+
states = tc.timeevol.krylov_evol(h, psi0, times, subspace_dimension=20, scan_impl=True)
245+
246+
**ODE-Based Evolution:**
247+
248+
For time-dependent Hamiltonians or when fine control over the evolution process is needed, TensorCircuit provides ODE-based evolution methods.
249+
These methods solve the time-dependent Schrödinger equation directly:
250+
the usage can be found at Analog circuit simulation section
251+
252+
253+
**Comparison of Time Evolution Methods:**
254+
255+
+--------------------------+----------------+------------------+------------------+------------------+
256+
| Method | System Size | Accuracy | AD Support | JIT Support |
257+
+==========================+================+==================+==================+==================+
258+
| ED Evolution | < 16 qubits | Exact |||
259+
+--------------------------+----------------+------------------+------------------+------------------+
260+
| Krylov Evolution | 16-30+ qubits | Approximate || ✅ (JAX only) |
261+
+--------------------------+----------------+------------------+------------------+------------------+
262+
| ODE Local Evolution | Any size | Solver-dependent | ✅ (JAX only) | ✅ (JAX only) |
263+
+--------------------------+----------------+------------------+------------------+------------------+
264+
| ODE Global Evolution | ~ 20 qubits | Solver-dependent | ✅ (JAX only) | ✅ (JAX only) |
265+
+--------------------------+----------------+------------------+------------------+------------------+
266+
267+
**Method Selection Guidelines:**
268+
269+
1. **Exact diagonalization Evolution**: Best for small systems where exact results are required. Most efficient for time-independent Hamiltonians.
270+
271+
2. **Krylov Evolution**: Ideal for large systems with time-independent Hamiltonians. Provides a good balance between accuracy and computational efficiency. The subspace dimension controls the trade-off between accuracy and speed.
272+
273+
3. **ODE Local Evolution**: Suitable for time-dependent Hamiltonians acting on a few qubits. Most flexible for complex control protocols or digital-analog hybrid programs.
274+
275+
4. **ODE Global Evolution**: Best for time-dependent Hamiltonians acting on the entire system.
276+
277+
**Advanced Usage:**
278+
279+
Callback functions can be used to compute observables during evolution without storing all state vectors:
280+
281+
.. code-block:: python
282+
283+
def compute_total_magnetization(state):
284+
# Compute total magnetization ⟨∑Zᵢ⟩
285+
n = int(tc.backend.log2(tc.backend.shape_tuple(state)[0]))
286+
circuit = tc.Circuit(n, inputs=state)
287+
total_mz = sum(circuit.expectation_ps(z=[i]) for i in range(n))
288+
return tc.backend.real(total_mz)
289+
290+
# Evolve with callback
291+
magnetizations = tc.timeevol.krylov_evol(
292+
h, psi0, times, subspace_dimension=20, callback=compute_total_magnetization
293+
)
294+
295+
All time evolution methods in TensorCircuit support automatic differentiation and JIT compilation, making them suitable for variational optimization and other machine learning applications in quantum physics.
296+
152297

153298
Jitted Function Save/Load
154299
-----------------------------

tests/test_timeevol.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ def test_krylov_evol_scan_impl(backend):
246246
g = tc.templates.graphs.Line1D(n, pbc=False)
247247

248248
# Generate Heisenberg Hamiltonian
249-
h = tc.quantum.heisenberg_hamiltonian(g, hzz=1.0, hxx=1.0, hyy=1.0, sparse=False)
249+
h = tc.quantum.heisenberg_hamiltonian(g, hzz=1.0, hxx=1.0, hyy=1.0, sparse=True)
250250

251251
c = tc.Circuit(n)
252252
c.x([1, 2])
@@ -260,6 +260,10 @@ def test_krylov_evol_scan_impl(backend):
260260
h, psi0, times, subspace_dimension=8, scan_impl=True
261261
)
262262

263+
states_scan_dense = tc.timeevol.krylov_evol(
264+
tc.backend.to_dense(h), psi0, times, subspace_dimension=8, scan_impl=True
265+
)
266+
263267
# Perform Krylov evolution with regular implementation
264268
states_regular = tc.timeevol.krylov_evol(
265269
h, psi0, times, subspace_dimension=8, scan_impl=False
@@ -271,6 +275,7 @@ def test_krylov_evol_scan_impl(backend):
271275

272276
# Results should be the same (up to numerical precision)
273277
np.testing.assert_allclose(states_scan, states_regular, atol=1e-5)
278+
np.testing.assert_allclose(states_scan_dense, states_regular, atol=1e-5)
274279

275280
# All states should be normalized
276281
for state in states_scan:

0 commit comments

Comments
 (0)