qml.evolve¶
- evolve(*args, **kwargs)[source]¶
This method is dispatched and its functionality depends on the type of the input
op
.Input: Operator
Returns a new operator that computes the evolution of
op
.\[e^{-i x \bm{O}}\]- Parameters
op (Operator) – operator to evolve
coeff (float) – coefficient multiplying the exponentiated operator
- Returns
evolution operator
- Return type
Examples
We can use
qml.evolve
to compute the evolution of any PennyLane operator:>>> op = qml.evolve(qml.X(0), coeff=2) >>> op Exp(-2j PauliX)
Input: ParametrizedHamiltonian
- Parameters
op (ParametrizedHamiltonian) – Hamiltonian to evolve
- Returns
time evolution \(U(t_0, t_1)\) of the Hamiltonian
- Return type
The function takes a
ParametrizedHamiltonian
and solves the time-dependent Schrodinger equation\[\frac{\partial}{\partial t} |\psi\rangle = -i H(t) |\psi\rangle\]It returns a
ParametrizedEvolution
, \(U(t_0, t_1)\), which is the solution to the time-dependent Schrodinger equation for theParametrizedHamiltonian
, such that\[|\psi(t_1)\rangle = U(t_0, t_1) |\psi(t_0)\rangle\]The
ParametrizedEvolution
class uses a numerical ordinary differential equation solver (here).Examples
When evolving a
ParametrizedHamiltonian
, aParametrizedEvolution
instance is returned:coeffs = [lambda p, t: p * t for _ in range(4)] ops = [qml.X(i) for i in range(4)] # ParametrizedHamiltonian H = qml.dot(coeffs, ops) # ParametrizedEvolution ev = qml.evolve(H)
>>> ev ParametrizedEvolution(wires=[0, 1, 2, 3])
The
ParametrizedEvolution
is anOperator
, but does not have a defined matrix unless it is evaluated at set parameters. This is done by calling theParametrizedEvolution
, which has the call signature(p, t)
:>>> qml.matrix(ev([1., 2., 3., 4.], t=[0, 4])) Array([[ 0.04930558+0.j , 0. -0.03259093j, 0. +0.1052632j , 0.06957878+0.j , 0. -0.01482305j, -0.00979751+0.j , 0.03164552+0.j , 0. -0.0209179j , 0. +0.33526757j, 0.22161038+0.j , ... ... ... 0. -0.03259093j, 0.04930566+0.j ]], dtype=complex64)
Additional options regarding how the matrix is calculated can be passed to the
ParametrizedEvolution
along with the parameters, as keyword arguments. These options are:atol (float, optional)
: Absolute error tolerancertol (float, optional)
: Relative error tolerancemxstep (int, optional)
: maximum number of steps to take for each time pointhmax (float, optional)
: maximum step size
If not specified, they will default to predetermined values.
The
ParametrizedEvolution
can be implemented in a QNode:import jax jax.config.update("jax_enable_x64", True) dev = qml.device("default.qubit") @jax.jit @qml.qnode(dev, interface="jax") def circuit(params): qml.evolve(H)(params, t=[0, 10]) return qml.expval(qml.Z(0))
>>> params = [1., 2., 3., 4.] >>> circuit(params) Array(0.86231063, dtype=float64)
>>> jax.grad(circuit)(params) [Array(50.391273, dtype=float64), Array(-9.42415807e-05, dtype=float64), Array(-0.0001049, dtype=float64), Array(-0.00010601, dtype=float64)]
Note
In the example above, the decorator
@jax.jit
is used to compile this execution just-in-time. This means the first execution will typically take a little longer with the benefit that all following executions will be significantly faster, see the jax docs on jitting. JIT-compiling is optional, and one can remove the decorator when only single executions are of interest.