QobjEvo usage example

Made by Eric Giguere


In [1]:
from qutip import *
import time
import numpy as np

Definition of time-dependant Qobj

QobjEvo represent a Qobj that depend on time. It is used in main solvers (sesolve, mesolve, mcsolve, stochastic solvers).

QobjEvo are definied from nested list of Qobj:
[Qobj0, [Qobj1, coeff1], [Qobj2, coeff2]]
coeff can be one of:

  • function
  • string
  • np.array

In [2]:
# Definition of base Qobj and coeff
N = 4
t = 1.0
a = destroy(N)
ad = create(N)
n = create(N)*destroy(N)
I = qeye(N)

Contant QobjEvo


In [3]:
cte_QobjEvo = QobjEvo(a)

#The Qobj at t is obtain by obj(t)
cte_QobjEvo(0.)


Out[3]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = False\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 1.0 & 0.0 & 0.0\\0.0 & 0.0 & 1.414 & 0.0\\0.0 & 0.0 & 0.0 & 1.732\\0.0 & 0.0 & 0.0 & 0.0\\\end{array}\right)\end{equation*}

In [4]:
cte_QobjEvo(1.)


Out[4]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = False\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 1.0 & 0.0 & 0.0\\0.0 & 0.0 & 1.414 & 0.0\\0.0 & 0.0 & 0.0 & 1.732\\0.0 & 0.0 & 0.0 & 0.0\\\end{array}\right)\end{equation*}

Coefficient as function

Function based coefficient:

def coeff(t, args={})


In [5]:
def sin_t(t, args):
    return np.sin(t)

def cos_t(t, args):
    return np.cos(t)

In [6]:
# QobjEvo with function based coeff
func_QobjEvo = QobjEvo([n,[a+ad,cos_t]])
func_QobjEvo(0.)


Out[6]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 1.0 & 0.0 & 0.0\\1.0 & 1.0 & 1.414 & 0.0\\0.0 & 1.414 & 2.0 & 1.732\\0.0 & 0.0 & 1.732 & 3.000\\\end{array}\right)\end{equation*}

In [7]:
func_QobjEvo(3.1416)


Out[7]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.0 & -1.000 & 0.0 & 0.0\\-1.000 & 1.0 & -1.414 & 0.0\\0.0 & -1.414 & 2.0 & -1.732\\0.0 & 0.0 & -1.732 & 3.000\\\end{array}\right)\end{equation*}

Coeficient as string

Valid 1 line of code returning a complex number:

"cos(t)"

availiable functions and object:

sin cos tan asin acos atan pi  
sinh cosh tanh asinh acosh atanh  
exp log log10 erf zerf sqrt  
real imag conj abs norm arg proj  
numpy as np  
scipy.special as spe

In [8]:
# QobjEvo with function based coeff
str_QobjEvo = QobjEvo([n,[a+ad,"cos(t)"]])
str_QobjEvo(0.)


Out[8]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 1.0 & 0.0 & 0.0\\1.0 & 1.0 & 1.414 & 0.0\\0.0 & 1.414 & 2.0 & 1.732\\0.0 & 0.0 & 1.732 & 3.000\\\end{array}\right)\end{equation*}

In [9]:
str_QobjEvo(3.1416)


Out[9]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.0 & -1.000 & 0.0 & 0.0\\-1.000 & 1.0 & -1.414 & 0.0\\0.0 & -1.414 & 2.0 & -1.732\\0.0 & 0.0 & -1.732 & 3.000\\\end{array}\right)\end{equation*}

Coefficient as array

Array of values at t's.

The t's are passed as a tlist. A cubic spline interpolation is used between provided values.


In [10]:
tlist = np.linspace(0,10,101)
array_QobjEvo = QobjEvo([n, [a+ad,np.cos(tlist)]],tlist=tlist)
array_QobjEvo(0.)


Out[10]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 1.0 & 0.0 & 0.0\\1.0 & 1.0 & 1.414 & 0.0\\0.0 & 1.414 & 2.0 & 1.732\\0.0 & 0.0 & 1.732 & 3.000\\\end{array}\right)\end{equation*}

In [11]:
array_QobjEvo(3.1416)


Out[11]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.0 & -1.000 & 0.0 & 0.0\\-1.000 & 1.0 & -1.414 & 0.0\\0.0 & -1.414 & 2.0 & -1.732\\0.0 & 0.0 & -1.732 & 3.000\\\end{array}\right)\end{equation*}
time step do not have to be equality distributed

In [12]:
tlistlog = np.logspace(-3,1,1001)
Log_array_QobjEvo = QobjEvo([n, [a+ad,np.cos(tlistlog)]],tlist=tlistlog)
Log_array_QobjEvo(0.)


Out[12]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 1.000 & 0.0 & 0.0\\1.000 & 1.0 & 1.414 & 0.0\\0.0 & 1.414 & 2.0 & 1.732\\0.0 & 0.0 & 1.732 & 3.000\\\end{array}\right)\end{equation*}

In [13]:
Log_array_QobjEvo(3.1416)


Out[13]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.0 & -1.000 & 0.0 & 0.0\\-1.000 & 1.0 & -1.414 & 0.0\\0.0 & -1.414 & 2.0 & -1.732\\0.0 & 0.0 & -1.732 & 3.000\\\end{array}\right)\end{equation*}

Arguments

Data can be passed to the coeff function or string in a "args" dictionary.

args = {"name1":value, "name2":value}  

names must be valid variable names not beginning with "_"

value can be of any type, but for string coefficient, scalar and np.array are prefered.


In [14]:
def coeff_with_args(t, args):
    return t + args['w']

td_args = QobjEvo([I, coeff_with_args], args={'w':1.}) 
td_args(0)


Out[14]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}1.0 & 0.0 & 0.0 & 0.0\\0.0 & 1.0 & 0.0 & 0.0\\0.0 & 0.0 & 1.0 & 0.0\\0.0 & 0.0 & 0.0 & 1.0\\\end{array}\right)\end{equation*}

In [15]:
td_args(1)


Out[15]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}2.0 & 0.0 & 0.0 & 0.0\\0.0 & 2.0 & 0.0 & 0.0\\0.0 & 0.0 & 2.0 & 0.0\\0.0 & 0.0 & 0.0 & 2.0\\\end{array}\right)\end{equation*}

In [16]:
td_args(0, args={"w":10})


Out[16]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}10.0 & 0.0 & 0.0 & 0.0\\0.0 & 10.0 & 0.0 & 0.0\\0.0 & 0.0 & 10.0 & 0.0\\0.0 & 0.0 & 0.0 & 10.0\\\end{array}\right)\end{equation*}

In [17]:
td_args_str = QobjEvo([I, "t+w"], args={'w':1.}) 
td_args_str(0)


Out[17]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}1.0 & 0.0 & 0.0 & 0.0\\0.0 & 1.0 & 0.0 & 0.0\\0.0 & 0.0 & 1.0 & 0.0\\0.0 & 0.0 & 0.0 & 1.0\\\end{array}\right)\end{equation*}

In [18]:
td_args_str(1)


Out[18]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}2.0 & 0.0 & 0.0 & 0.0\\0.0 & 2.0 & 0.0 & 0.0\\0.0 & 0.0 & 2.0 & 0.0\\0.0 & 0.0 & 0.0 & 2.0\\\end{array}\right)\end{equation*}

In [19]:
td_args_str(0, args={"w":10})


Out[19]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}10.0 & 0.0 & 0.0 & 0.0\\0.0 & 10.0 & 0.0 & 0.0\\0.0 & 0.0 & 10.0 & 0.0\\0.0 & 0.0 & 0.0 & 10.0\\\end{array}\right)\end{equation*}

Advanced example


In [20]:
# Example of object as value
td_args_str = QobjEvo([I, "w(t)"], args={'w':np.cos}) 
td_args_str.compile()

In [21]:
td_args_str(0.)


Out[21]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}1.0 & 0.0 & 0.0 & 0.0\\0.0 & 1.0 & 0.0 & 0.0\\0.0 & 0.0 & 1.0 & 0.0\\0.0 & 0.0 & 0.0 & 1.0\\\end{array}\right)\end{equation*}

In [22]:
td_args_str(3.1416)


Out[22]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}-1.000 & 0.0 & 0.0 & 0.0\\0.0 & -1.000 & 0.0 & 0.0\\0.0 & 0.0 & -1.000 & 0.0\\0.0 & 0.0 & 0.0 & -1.000\\\end{array}\right)\end{equation*}

State in argument

The state of the solver can be accessed in arguments.

  • "name=vec":Qobj0 : args[name] = state as 1d np.array
  • "name=mat":Qobj0 : args[name] = state as 2d np.array
  • "name=Qobj":Qobj0 : args[name] = state as Qobj
  • "name=expect":Qobj/QobjEvo : args[name] = expect(Qobj/QobjEvo(t), state)
  • "name=collapse"=[] : args[name] = list of collapse. mcsolve only.

The initial value is taken from Qobj0 or 0 for expect.
Later call will use the last available value.
Main solvers ([se/me/mc]solve) update at each call.


In [23]:
args={"state_as_vec" + "=vec":basis(4,3),
      "state_as_mat" + "=mat":basis(4,3),
      "state_as_Qobj" + "=Qobj":basis(4,3),
      "e1" + "=expect":n}

def print_args(t, args):
    for key in args:
        print(args[key])
    return t

td_args = QobjEvo([I, print_args], args=args) 
td_args(0)


[0.+0.j 0.+0.j 0.+0.j 1.+0.j]
[[0.+0.j]
 [0.+0.j]
 [0.+0.j]
 [1.+0.j]]
Quantum object: dims = [[4], [1]], shape = (4, 1), type = ket
Qobj data =
[[0.]
 [0.]
 [0.]
 [1.]]
0.0
Out[23]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0\\\end{array}\right)\end{equation*}

In [24]:
td_args(0, state=basis(4,2))


[0.+0.j 0.+0.j 1.+0.j 0.+0.j]
[[0.+0.j]
 [0.+0.j]
 [1.+0.j]
 [0.+0.j]]
Quantum object: dims = [[4], [1]], shape = (4, 1), type = ket
Qobj data =
[[0.]
 [0.]
 [1.]
 [0.]]
(2.0000000000000004+0j)
Out[24]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0\\\end{array}\right)\end{equation*}

coefficient with memory

Function coefficient can be class method, allowing for internal states.


In [25]:
class coeff:
    def __init__(self):
        self.ts = []
        
    def call(self, t, args):
        self.ts.append((t,args["e1"]))
        return np.sin(t)

my_coeff = coeff()

H = QobjEvo([I+(a+ad), my_coeff.call], args={"e1=expect":n}) 
sesolve(H, basis(4,2), [0, 0.01])
my_coeff.ts


Out[25]:
[(0.0, (2.0000000000000004+0j)),
 (0.0, (2.0000000000000004+0j)),
 (4.712160915387242e-10, (2.0000000000000004+0j)),
 (0.0001337474054398383, (2.0000000000000004+0j)),
 (6.687370281960761e-05, (2.0000000000000004+0j)),
 (6.687370281960761e-05, (2.0000000000000004+0j)),
 (0.00013374740563921523, (2.000000000000001+0j)),
 (0.00013374740563921523, (2.000000000000001+0j)),
 (0.0008024844338352913, (2.0000000000001057+0j)),
 (0.0008024844338352913, (2.000000000000706+0j)),
 (0.0003211302409302149, (2.0000000000000084+0j)),
 (0.0003211302409302149, (2.0000000000000067+1.88079096131566e-37j)),
 (0.0005085130762212145, (2.0000000000000684+0j)),
 (0.0023823414291312107, (2.0000000000904707+8.470329472543003e-22j)),
 (0.016171623770340246, (2.0000002117361637+0j)),
 (0.016171623770340246, (1.9999998710986275+0j))]

In [26]:
td_args(1, state=basis(4,2))


[0.+0.j 0.+0.j 1.+0.j 0.+0.j]
[[0.+0.j]
 [0.+0.j]
 [1.+0.j]
 [0.+0.j]]
Quantum object: dims = [[4], [1]], shape = (4, 1), type = ket
Qobj data =
[[0.]
 [0.]
 [1.]
 [0.]]
(2.0000000000000004+0j)
Out[26]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}1.0 & 0.0 & 0.0 & 0.0\\0.0 & 1.0 & 0.0 & 0.0\\0.0 & 0.0 & 1.0 & 0.0\\0.0 & 0.0 & 0.0 & 1.0\\\end{array}\right)\end{equation*}

Some solver may call the system at previous time step.
t=1. then t=0.5 then t=1.5 etc.

Mathematic

QobjEvo support basis mathematic operation:

  • addition (QobjEvo, Qobj)
  • substraction (QobjEvo, Qobj)
  • product (QobjEvo, Qobj, scalar)
  • division (scalar)

and unitary transformation:

  • conj
  • dag
  • trans

In [27]:
(array_QobjEvo * 2)(0)


Out[27]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 2.0 & 0.0 & 0.0\\2.0 & 2.0 & 2.828 & 0.0\\0.0 & 2.828 & 4.0 & 3.464\\0.0 & 0.0 & 3.464 & 6.000\\\end{array}\right)\end{equation*}

In [28]:
(array_QobjEvo + 1 + a)(0)


Out[28]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = False\begin{equation*}\left(\begin{array}{*{11}c}1.0 & 2.0 & 0.0 & 0.0\\1.0 & 2.0 & 2.828 & 0.0\\0.0 & 1.414 & 3.0 & 3.464\\0.0 & 0.0 & 1.732 & 4.000\\\end{array}\right)\end{equation*}

Liouvillian and lindblad dissipator, to use in solver

Functions in qutip.superoperator can be used for QobjEvo.


In [29]:
liouv = liouvillian(array_QobjEvo, c_ops=[cte_QobjEvo])
liouv(0)


Out[29]:
Quantum object: dims = [[[4], [4]], [[4], [4]]], shape = (16, 16), type = super, isherm = False\begin{equation*}\left(\begin{array}{*{11}c}0.0 & -1.0j & 0.0 & 0.0 & 1.0j & \cdots & 0.0 & 0.0 & 0.0 & 0.0 & 0.0\\-1.0j & (-0.500-1.0j) & -1.414j & 0.0 & 0.0 & \cdots & 0.0 & 0.0 & 0.0 & 0.0 & 0.0\\0.0 & -1.414j & (-1.0-2.0j) & -1.732j & 0.0 & \cdots & 0.0 & 0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & -1.732j & (-1.500-3.000j) & 0.0 & \cdots & 0.0 & 0.0 & 0.0 & 0.0 & 0.0\\1.0j & 0.0 & 0.0 & 0.0 & (-0.500+1.0j) & \cdots & 0.0 & 0.0 & 0.0 & 0.0 & 0.0\\\vdots & \vdots & \vdots & \vdots & \vdots & \ddots & \vdots & \vdots & \vdots & \vdots & \vdots\\0.0 & 0.0 & 0.0 & 0.0 & 0.0 & \cdots & (-2.500-1.000j) & 0.0 & 0.0 & 0.0 & 1.732j\\0.0 & 0.0 & 0.0 & 0.0 & 0.0 & \cdots & 0.0 & (-1.500+3.000j) & -1.0j & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0 & 0.0 & \cdots & 0.0 & -1.0j & (-2.000+2.000j) & -1.414j & 0.0\\0.0 & 0.0 & 0.0 & 0.0 & 0.0 & \cdots & 0.0 & 0.0 & -1.414j & (-2.500+1.000j) & -1.732j\\0.0 & 0.0 & 0.0 & 0.0 & 0.0 & \cdots & 1.732j & 0.0 & 0.0 & -1.732j & -3.000\\\end{array}\right)\end{equation*}