In [1]:
from cutiepy import *
import numpy as np
cutiepy.codegen.DEBUG = True

$|k\rangle \rightarrow \hat{a}^\dagger|k\rangle$


In [2]:
op = create(5)
y_anon = Ket.anon(5)
cf = generate_cython(evalf(op*y_anon),         
                     func=NDArrayFunction(),            
                     argument_order = [y_anon])

In [3]:
ccf = cf.compiled()


#cython: boundscheck=False, wraparound=False, initializedcheck=False, cdivision=True
cimport numpy as np
import numpy as np
from libc.math cimport sin, cos, exp, sinh, cosh, tan, tanh, log
from scipy.linalg.cython_blas cimport zgemv, zgemm

cdef int iONE=1, iZERO=0
cdef double complex zONE=1, zZERO=0, zNHALF=-0.5

# Declaration of global variables for
# - intermediate results
# - predefined constants

cdef double complex [:, :] A # initialized in setup

# The generated cython code
cdef generated_function(
    # input arguments
    double complex [:, :] B,
    # output argument
    double complex [:, :] C
    ):
    # indices and intermediate values for various matrix operations
    cdef int i, j, k, ii, jj, kk
    cdef double complex c
    # intermediate results
    # no intermediate results globals
    # predefined constants
    global A
    # evaluating the function
    # C = A.B
    ii = A.shape[0]
    jj = A.shape[1]
    kk = B.shape[1]
    zgemm('N', 'N', &kk, &ii, &jj, &zONE, &B[0,0], &kk, &A[0,0], &jj, &zZERO, &C[0,0], &kk)

# Function to deliver the constants from python to cython
cpdef setup_generated_function(
    double complex [:, :] _A
    ):
    global A
    A = _A

cpdef np.ndarray[np.complex_t, ndim=2] pythoncall(_0):
    cdef np.ndarray[np.complex_t, ndim=2] result = np.empty((5, 1), complex)
    generated_function(_0, result)
    return result

In [4]:
b = basis(5,1)
ccf.pythoncall(numerical(b))


Out[4]:
array([[ 0.00000000+0.j],
       [ 0.00000000+0.j],
       [ 1.41421356+0.j],
       [ 0.00000000+0.j],
       [ 0.00000000+0.j]])

$\rho \rightarrow \left[ \sigma_x, \rho \right]$


In [5]:
op = sigmax()
y_anon = Operator.anon(2)
cf = generate_cython(evalf(Commutator(op, y_anon)),         
                     func=NDArrayFunction(),            
                     argument_order = [y_anon])

In [6]:
ccf = cf.compiled()


#cython: boundscheck=False, wraparound=False, initializedcheck=False, cdivision=True
cimport numpy as np
import numpy as np
from libc.math cimport sin, cos, exp, sinh, cosh, tan, tanh, log
from scipy.linalg.cython_blas cimport zgemv, zgemm

cdef int iONE=1, iZERO=0
cdef double complex zONE=1, zZERO=0, zNHALF=-0.5

# Declaration of global variables for
# - intermediate results
# - predefined constants
cdef double complex [:, :] C = np.empty((2, 2), dtype=np.complex)
cdef double complex [:, :] E = np.empty((2, 2), dtype=np.complex)
cdef double complex [:, :] F = np.empty((2, 2), dtype=np.complex)
cdef double complex [:, :] D # initialized in setup
cdef double complex [:, :] A # initialized in setup

# The generated cython code
cdef generated_function(
    # input arguments
    double complex [:, :] B,
    # output argument
    double complex [:, :] G
    ):
    # indices and intermediate values for various matrix operations
    cdef int i, j, k, ii, jj, kk
    cdef double complex c
    # intermediate results
    global C, E, F
    # predefined constants
    global D, A
    # evaluating the function
    # C = A.B
    ii = A.shape[0]
    jj = A.shape[1]
    kk = B.shape[1]
    zgemm('N', 'N', &kk, &ii, &jj, &zONE, &B[0,0], &kk, &A[0,0], &jj, &zZERO, &C[0,0], &kk)
    # E = B.D
    ii = B.shape[0]
    jj = B.shape[1]
    kk = D.shape[1]
    zgemm('N', 'N', &kk, &ii, &jj, &zONE, &D[0,0], &kk, &B[0,0], &jj, &zZERO, &E[0,0], &kk)
    # F = -1*E
    ii = E.shape[0]
    jj = E.shape[1]
    for i in range(ii):
        for j in range(jj):
            F[i,j] = -1*E[i,j]
    # G = C+F
    ii = C.shape[0]
    jj = C.shape[1]
    for i in range(ii):
        for j in range(jj):
            G[i,j] = C[i,j]+F[i,j]

# Function to deliver the constants from python to cython
cpdef setup_generated_function(
    double complex [:, :] _D,
    double complex [:, :] _A
    ):
    global D, A
    D = _D
    A = _A

cpdef np.ndarray[np.complex_t, ndim=2] pythoncall(_0):
    cdef np.ndarray[np.complex_t, ndim=2] result = np.empty((2, 2), complex)
    generated_function(_0, result)
    return result

In [7]:
ccf.pythoncall(numerical(op))


Out[7]:
array([[ 0.+0.j,  0.+0.j],
       [ 0.+0.j,  0.+0.j]])

In [8]:
ccf.pythoncall(numerical(sigmay()))


Out[8]:
array([[ 0.+2.j,  0.+0.j],
       [ 0.+0.j,  0.-2.j]])

$\rho \rightarrow -i \left[ \sigma_x, \rho \right]$


In [9]:
op = sigmax()
y_anon = Operator.anon(2)
cf = generate_cython(evalf(-1j*Commutator(op, y_anon)),         
                     func=NDArrayFunction(),            
                     argument_order = [y_anon])

In [10]:
ccf = cf.compiled()


#cython: boundscheck=False, wraparound=False, initializedcheck=False, cdivision=True
cimport numpy as np
import numpy as np
from libc.math cimport sin, cos, exp, sinh, cosh, tan, tanh, log
from scipy.linalg.cython_blas cimport zgemv, zgemm

cdef int iONE=1, iZERO=0
cdef double complex zONE=1, zZERO=0, zNHALF=-0.5

# Declaration of global variables for
# - intermediate results
# - predefined constants
cdef double complex [:, :] C = np.empty((2, 2), dtype=np.complex)
cdef double complex [:, :] E = np.empty((2, 2), dtype=np.complex)
cdef double complex [:, :] F = np.empty((2, 2), dtype=np.complex)
cdef double complex [:, :] G = np.empty((2, 2), dtype=np.complex)
cdef double complex [:, :] D # initialized in setup
cdef double complex [:, :] A # initialized in setup

# The generated cython code
cdef generated_function(
    # input arguments
    double complex [:, :] B,
    # output argument
    double complex [:, :] H
    ):
    # indices and intermediate values for various matrix operations
    cdef int i, j, k, ii, jj, kk
    cdef double complex c
    # intermediate results
    global C, E, F, G
    # predefined constants
    global D, A
    # evaluating the function
    # C = A.B
    ii = A.shape[0]
    jj = A.shape[1]
    kk = B.shape[1]
    zgemm('N', 'N', &kk, &ii, &jj, &zONE, &B[0,0], &kk, &A[0,0], &jj, &zZERO, &C[0,0], &kk)
    # E = B.D
    ii = B.shape[0]
    jj = B.shape[1]
    kk = D.shape[1]
    zgemm('N', 'N', &kk, &ii, &jj, &zONE, &D[0,0], &kk, &B[0,0], &jj, &zZERO, &E[0,0], &kk)
    # F = -1*E
    ii = E.shape[0]
    jj = E.shape[1]
    for i in range(ii):
        for j in range(jj):
            F[i,j] = -1*E[i,j]
    # G = C+F
    ii = C.shape[0]
    jj = C.shape[1]
    for i in range(ii):
        for j in range(jj):
            G[i,j] = C[i,j]+F[i,j]
    # H = -1j*G
    ii = G.shape[0]
    jj = G.shape[1]
    for i in range(ii):
        for j in range(jj):
            H[i,j] = -1j*G[i,j]

# Function to deliver the constants from python to cython
cpdef setup_generated_function(
    double complex [:, :] _D,
    double complex [:, :] _A
    ):
    global D, A
    D = _D
    A = _A

cpdef np.ndarray[np.complex_t, ndim=2] pythoncall(_0):
    cdef np.ndarray[np.complex_t, ndim=2] result = np.empty((2, 2), complex)
    generated_function(_0, result)
    return result

In [11]:
ccf.pythoncall(numerical(sigmay()))


Out[11]:
array([[ 2.-0.j,  0.-0.j],
       [ 0.-0.j, -2.+0.j]])