1# This file is part of QuTiP: Quantum Toolbox in Python. 2# 3# Copyright (c) 2011 and later, Paul D. Nation and Robert J. Johansson. 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are 8# met: 9# 10# 1. Redistributions of source code must retain the above copyright notice, 11# this list of conditions and the following disclaimer. 12# 13# 2. Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in the 15# documentation and/or other materials provided with the distribution. 16# 17# 3. Neither the name of the QuTiP: Quantum Toolbox in Python nor the names 18# of its contributors may be used to endorse or promote products derived 19# from this software without specific prior written permission. 20# 21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 24# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32############################################################################### 33 34import numbers 35import numpy as np 36from numpy.testing import assert_equal, run_module_suite 37import pytest 38 39import qutip 40from qutip import (jmat, basis, destroy, create, displace, qzero, qeye, 41 num, squeeze, charge, tunneling) 42 43 44def test_jmat_12(): 45 "Spin 1/2 operators" 46 spinhalf = jmat(1 / 2.) 47 48 paulix = np.array([[0.0 + 0.j, 0.5 + 0.j], [0.5 + 0.j, 0.0 + 0.j]]) 49 pauliy = np.array([[0. + 0.j, 0. - 0.5j], [0. + 0.5j, 0. + 0.j]]) 50 pauliz = np.array([[0.5 + 0.j, 0.0 + 0.j], [0.0 + 0.j, -0.5 + 0.j]]) 51 sigmap = np.array([[0. + 0.j, 1. + 0.j], [0. + 0.j, 0. + 0.j]]) 52 sigmam = np.array([[0. + 0.j, 0. + 0.j], [1. + 0.j, 0. + 0.j]]) 53 54 assert_equal(np.allclose(spinhalf[0].full(), paulix), True) 55 assert_equal(np.allclose(spinhalf[1].full(), pauliy), True) 56 assert_equal(np.allclose(spinhalf[2].full(), pauliz), True) 57 assert_equal(np.allclose(jmat(1 / 2., '+').full(), sigmap), True) 58 assert_equal(np.allclose(jmat(1 / 2., '-').full(), sigmam), True) 59 60 61def test_jmat_32(): 62 "Spin 3/2 operators" 63 spin32 = jmat(3 / 2.) 64 65 paulix32 = np.array( 66 [[0.0000000 + 0.j, 0.8660254 + 0.j, 0.0000000 + 0.j, 0.0000000 + 0.j], 67 [0.8660254 + 0.j, 0.0000000 + 0.j, 1.0000000 + 0.j, 0.0000000 + 0.j], 68 [0.0000000 + 0.j, 1.0000000 + 0.j, 0.0000000 + 0.j, 0.8660254 + 0.j], 69 [0.0000000 + 0.j, 0.0000000 + 0.j, 0.8660254 + 0.j, 0.0000000 + 0.j]]) 70 71 pauliy32 = np.array( 72 [[0. + 0.j, 0. - 0.8660254j, 0. + 0.j, 0. + 0.j], 73 [0. + 0.8660254j, 0. + 0.j, 0. - 1.j, 0. + 0.j], 74 [0. + 0.j, 0. + 1.j, 0. + 0.j, 0. - 0.8660254j], 75 [0. + 0.j, 0. + 0.j, 0. + 0.8660254j, 0. + 0.j]]) 76 77 pauliz32 = np.array([[1.5 + 0.j, 0.0 + 0.j, 0.0 + 0.j, 0.0 + 0.j], 78 [0.0 + 0.j, 0.5 + 0.j, 0.0 + 0.j, 0.0 + 0.j], 79 [0.0 + 0.j, 0.0 + 0.j, -0.5 + 0.j, 0.0 + 0.j], 80 [0.0 + 0.j, 0.0 + 0.j, 0.0 + 0.j, -1.5 + 0.j]]) 81 82 assert_equal(np.allclose(spin32[0].full(), paulix32), True) 83 assert_equal(np.allclose(spin32[1].full(), pauliy32), True) 84 assert_equal(np.allclose(spin32[2].full(), pauliz32), True) 85 86 87def test_jmat_42(): 88 "Spin 2 operators" 89 spin42 = jmat(4 / 2., '+') 90 assert_equal(spin42.dims == [[5], [5]], True) 91 92 93def test_jmat_52(): 94 "Spin 5/2 operators" 95 spin52 = jmat(5 / 2., '+') 96 assert_equal(spin52.shape == (6, 6), True) 97 98 99def test_destroy(): 100 "Destruction operator" 101 b4 = basis(5, 4) 102 d5 = destroy(5) 103 test1 = d5 * b4 104 assert_equal(np.allclose(test1.full(), 2.0 * basis(5, 3).full()), True) 105 d3 = destroy(3) 106 matrix3 = np.array( 107 [[0.00000000 + 0.j, 1.00000000 + 0.j, 0.00000000 + 0.j], 108 [0.00000000 + 0.j, 0.00000000 + 0.j, 1.41421356 + 0.j], 109 [0.00000000 + 0.j, 0.00000000 + 0.j, 0.00000000 + 0.j]]) 110 111 assert_equal(np.allclose(matrix3, d3.full()), True) 112 113 114def test_create(): 115 "Creation operator" 116 b3 = basis(5, 3) 117 c5 = create(5) 118 test1 = c5 * b3 119 assert_equal(np.allclose(test1.full(), 2.0 * basis(5, 4).full()), True) 120 c3 = create(3) 121 matrix3 = np.array( 122 [[0.00000000 + 0.j, 0.00000000 + 0.j, 0.00000000 + 0.j], 123 [1.00000000 + 0.j, 0.00000000 + 0.j, 0.00000000 + 0.j], 124 [0.00000000 + 0.j, 1.41421356 + 0.j, 0.00000000 + 0.j]]) 125 126 assert_equal(np.allclose(matrix3, c3.full()), True) 127 128 129@pytest.mark.parametrize("to_test, expected", [ 130 (qutip.qzero, lambda x: np.zeros((x, x), dtype=complex)), 131 (qutip.qeye, lambda x: np.eye(x, dtype=complex)), 132 ]) 133@pytest.mark.parametrize("dimension", [1, 5, 100]) 134def test_simple_operator_creation(to_test, expected, dimension): 135 qobj = to_test(dimension) 136 assert np.allclose(qobj.full(), expected(dimension)) 137 138 139@pytest.mark.parametrize("to_test", [qutip.qzero, qutip.qeye, qutip.identity]) 140@pytest.mark.parametrize("dimensions", [ 141 2, 142 [2], 143 [2, 3, 4], 144 1, 145 [1], 146 [1, 1], 147 ]) 148def test_implicit_tensor_creation(to_test, dimensions): 149 implicit = to_test(dimensions) 150 if isinstance(dimensions, numbers.Integral): 151 dimensions = [dimensions] 152 assert implicit.dims == [dimensions, dimensions] 153 154 155@pytest.mark.parametrize("to_test", [qutip.qzero, qutip.qeye, qutip.identity]) 156def test_super_operator_creation(to_test): 157 size = 2 158 implicit = to_test([[size], [size]]) 159 explicit = qutip.to_super(to_test(size)) 160 assert implicit == explicit 161 162 163def test_num(): 164 "Number operator" 165 n5 = num(5) 166 assert_equal( 167 np.allclose(n5.full(), 168 np.diag([0 + 0j, 1 + 0j, 2 + 0j, 3 + 0j, 4 + 0j])), 169 True) 170 171 172def test_squeeze(): 173 "Squeezing operator" 174 sq = squeeze(4, 0.1 + 0.1j) 175 sqmatrix = np.array([[0.99500417 + 0.j, 0.00000000 + 0.j, 176 0.07059289 - 0.07059289j, 0.00000000 + 0.j], 177 [0.00000000 + 0.j, 0.98503746 + 0.j, 178 0.00000000 + 0.j, 0.12186303 - 0.12186303j], 179 [-0.07059289 - 0.07059289j, 0.00000000 + 0.j, 180 0.99500417 + 0.j, 0.00000000 + 0.j], 181 [0.00000000 + 0.j, -0.12186303 - 0.12186303j, 182 0.00000000 + 0.j, 0.98503746 + 0.j]]) 183 184 assert_equal(np.allclose(sq.full(), sqmatrix), True) 185 186 187def test_displace(): 188 "Displacement operator" 189 dp = displace(4, 0.25) 190 dpmatrix = np.array( 191 [[0.96923323 + 0.j, -0.24230859 + 0.j, 0.04282883 + 0.j, - 192 0.00626025 + 0.j], 193 [0.24230859 + 0.j, 0.90866411 + 0.j, -0.33183303 + 194 0.j, 0.07418172 + 0.j], 195 [0.04282883 + 0.j, 0.33183303 + 0.j, 0.84809499 + 196 0.j, -0.41083747 + 0.j], 197 [0.00626025 + 0.j, 0.07418172 + 0.j, 0.41083747 + 0.j, 198 0.90866411 + 0.j]]) 199 200 assert_equal(np.allclose(dp.full(), dpmatrix), True) 201 202 203def test_charge(): 204 "Charge operator" 205 N = 5 206 M = - np.random.randint(N) 207 ch = charge(N,M) 208 ch_matrix = np.diag(np.arange(M,N+1)) 209 assert_equal(np.allclose(ch.full(), ch_matrix), True) 210 211 212def test_tunneling(): 213 "Tunneling operator" 214 N = 5 215 tn = tunneling(2*N+1) 216 tn_matrix = np.diag(np.ones(2*N),k=-1) + np.diag(np.ones(2*N),k=1) 217 assert_equal(np.allclose(tn.full(), tn_matrix), True) 218 219 tn = tunneling(2*N+1,2) 220 tn_matrix = np.diag(np.ones(2*N-1),k=-2) + np.diag(np.ones(2*N-1),k=2) 221 assert_equal(np.allclose(tn.full(), tn_matrix), True) 222 223 224if __name__ == "__main__": 225 run_module_suite() 226