@@ -537,22 +537,63 @@ def test_unitary_kraus_qutrit_single(backend):
537537 c = tc .QuditCircuit (1 , dim = d )
538538 idx = c .unitary_kraus ([I , X ], 0 , prob = [0.0 , 1.0 ])
539539 assert idx == 1
540-
541- a0 = c .amplitude ("0" )
542- a1 = c .amplitude ("1" )
543- a2 = c .amplitude ("2" )
544- np .testing .assert_allclose (a1 , 1.0 + 0j , atol = 1e-6 )
545- np .testing .assert_allclose (a0 , 0.0 + 0j , atol = 1e-6 )
546- np .testing .assert_allclose (a2 , 0.0 + 0j , atol = 1e-6 )
540+ np .testing .assert_allclose (c .amplitude ("0" ), 0.0 + 0j , atol = 1e-6 )
541+ np .testing .assert_allclose (c .amplitude ("1" ), 1.0 + 0j , atol = 1e-6 )
542+ np .testing .assert_allclose (c .amplitude ("2" ), 0.0 + 0j , atol = 1e-6 )
547543
548544 # Case B: choose I branch deterministically
549545 c2 = tc .QuditCircuit (1 , dim = d )
550546 idx2 = c2 .unitary_kraus ([I , X ], 0 , prob = [1.0 , 0.0 ])
551547 assert idx2 == 0
548+ np .testing .assert_allclose (c2 .amplitude ("0" ), 1.0 + 0j , atol = 1e-6 )
549+ np .testing .assert_allclose (c2 .amplitude ("1" ), 0.0 + 0j , atol = 1e-6 )
550+ np .testing .assert_allclose (c2 .amplitude ("2" ), 0.0 + 0j , atol = 1e-6 )
551+
552+
553+ @pytest .mark .parametrize ("backend" , [lf ("npb" ), lf ("tfb" ), lf ("jaxb" )])
554+ def test_general_kraus_qutrit_single (backend ):
555+ r"""
556+ Qutrit (d=3) tests for general_kraus on a single site (Part B only).
557+
558+ True general Kraus with normalization and `with_prob=True`:
559+ K0 = sqrt(p) * I, K1 = sqrt(1-p) * X
560+ (K0^\dagger K0 + K1^\dagger K1 = I)
561+ `status` controls which branch is sampled.
562+ """
563+ d = 3
564+
565+ # Identity and qutrit shift X (|k> -> |k+1 mod 3)
566+ I = tc .quditgates .i_matrix_func (d )
567+ X = tc .quditgates .x_matrix_func (d )
568+
569+ p = 0.7
570+ K0 = np .sqrt (p ) * I
571+ K1 = np .sqrt (1.0 - p ) * X
572+
573+ # ---- completeness check in numpy space (works for all backends) ----
574+ np .testing .assert_allclose (
575+ tc .backend .transpose (tc .backend .conj (K0 )) @ K0
576+ + tc .backend .transpose (tc .backend .conj (K1 )) @ K1 ,
577+ I ,
578+ atol = 1e-6 ,
579+ )
552580
553- b0 = c2 .amplitude ("0" )
554- b1 = c2 .amplitude ("1" )
555- b2 = c2 .amplitude ("2" )
556- np .testing .assert_allclose (b0 , 1.0 + 0j , atol = 1e-6 )
557- np .testing .assert_allclose (b1 , 0.0 + 0j , atol = 1e-6 )
558- np .testing .assert_allclose (b2 , 0.0 + 0j , atol = 1e-6 )
581+ # ---- Case B1: status small -> pick K0 with prob ~ p; state remains |0\rangle ----
582+ c3 = tc .QuditCircuit (1 , dim = d )
583+ idx3 , prob3 = c3 .general_kraus ([K0 , K1 ], 0 , status = 0.2 , with_prob = True )
584+ assert idx3 == 0
585+ np .testing .assert_allclose (np .array (prob3 ), np .array ([p , 1 - p ]), atol = 1e-6 )
586+ np .testing .assert_allclose (np .array (prob3 )[idx3 ], p , atol = 1e-6 )
587+ np .testing .assert_allclose (c3 .amplitude ("0" ), 1.0 + 0j , atol = 1e-6 )
588+ np .testing .assert_allclose (c3 .amplitude ("1" ), 0.0 + 0j , atol = 1e-6 )
589+ np .testing .assert_allclose (c3 .amplitude ("2" ), 0.0 + 0j , atol = 1e-6 )
590+
591+ # ---- Case B2: status large -> pick K1 with prob ~ (1-p); state becomes |1\rangle ----
592+ c4 = tc .QuditCircuit (1 , dim = d )
593+ idx4 , prob4 = c4 .general_kraus ([K0 , K1 ], 0 , status = 0.95 , with_prob = True )
594+ assert idx4 == 1
595+ np .testing .assert_allclose (np .array (prob4 ), np .array ([p , 1 - p ]), atol = 1e-6 )
596+ np .testing .assert_allclose (np .array (prob4 )[idx4 ], 1.0 - p , atol = 1e-6 )
597+ np .testing .assert_allclose (c4 .amplitude ("0" ), 0.0 + 0j , atol = 1e-6 )
598+ np .testing .assert_allclose (c4 .amplitude ("1" ), 1.0 + 0j , atol = 1e-6 )
599+ np .testing .assert_allclose (c4 .amplitude ("2" ), 0.0 + 0j , atol = 1e-6 )
0 commit comments