
    bii                   L   d dl mZ d dlmZ d dlmZ d dlZd dlZd dl	m
Z d dlmZ d dlmZmZmZmZmZ e G d d             Zd Z G d	 d
      Zej0                  ej2                  gZ G d d      Z G d d      Z G d d      Z G d d      Z G d d      Z G d d      Z y)    )annotations)	dataclass)CallableN)CanonBackendNumPyCanonBackendPythonCanonBackendSciPyCanonBackendTensorRepresentationc                  J    e Zd ZU dZdZded<   dZded<   dZded<   dZd	ed
<   y)linOpHelperzv
    Helper class that allows to access properties of linOps without
    needing to create a full linOps instance
    NzNone | tuple[int, ...]shapez
None | strtypez%None | int | np.ndarray | list[slice]datazNone | list[linOpHelper]args)	__name__
__module____qualname____doc__r   __annotations__r   r   r        [/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/cvxpy/tests/test_python_backends.pyr   r      s4    
 %)E!(D*26D
/6%)D
")r   r   c            
     L   t        t        j                  dg      t        j                  dg      t        j                  dg      t        j                  dg      d      } t        t        j                  dg      t        j                  dg      t        j                  dg      t        j                  dg      d      }t        j                  | |g      }t        j                  |j
                  t        j                  ddg      k(        sJ t        j                  |j                  t        j                  ddg      k(        sJ t        j                  |j                  t        j                  ddg      k(        sJ t        j                  |j                  t        j                  ddg      k(        sJ |j                  dk(  sJ |j                  d      }t        j                  |j                         t        j                  ddgddgddgddgg      k(        sJ y )N
   r         r   r      r   )r
   nparraycombineallr   rowcolparameter_offsetr   flatten_tensortoarray)ABcombined	flatteneds       r   test_tensor_representationr-   !   s   
"!rxx}bhhsm6	A 	
"!rxx}bhhsm6	A $++QF3H66(--288RH#5566666(,,"((Aq6"2233366(,,"((Aq6"2233366(++rxxA/??@@@>>V###''*I66)##%Aq6Aq6B7QPRG2T)UUVVVr   c                      e Zd Zd Zy)TestBackendInstancec                   dddddddddddf}t        j                  t        j                  g| }t	        |t
              sJ t        j                  t        j                  g| }t	        |t              sJ t        j                  t              5  t        j                  d       d d d        y # 1 sw Y   y xY w)	Nr   r   r   r   r      r4   r3      notabackend)r   get_backendsSCIPY_CANON_BACKEND
isinstancer	   NUMPY_CANON_BACKENDr   pytestraisesKeyError)selfr   backends      r   test_get_backendz$TestBackendInstance.test_get_backend3   s    !1m]AqA**1+@+@H4H'#4555**1+@+@H4H'#4555]]8$ 	4$$]3	4 	4 	4s   B55B>N)r   r   r   rB   r   r   r   r/   r/   2   s    
4r   r/   c                  x   e Zd Ze ej
                  e      d               Zd Zd Z	d Z
d Zd Zd Zd	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zej0                  j3                  ddg dfdg dfd e ed            fd e ed            fg      d        Zd Zd Zd Zd Z d  Z!d! Z"d" Z#d# Z$d$ Z%d% Z&y)&TestBackendsparamsc                    dddddddddddd}t        j                  | j                  fi |}t        |t              sJ |S 	Nr   r   r1   r   r2   r5   r6   	id_to_colparam_to_sizeparam_to_colparam_size_plus_one
var_lengthr   r8   paramr;   r   requestkwargsrA   s      r   rA   zTestBackends.backendD   W     1"#] !qM#$
 **7==CFC'#5666r   c                    |j                  d      }t        |t              sJ t        j                  t
              5  |j                  d       d d d        y # 1 sw Y   y xY w)Nsumnotafunc)get_funcr;   r   r=   r>   r?   )r@   rA   funcs      r   test_mappingzTestBackends.test_mappingU   sQ    &$)))]]8$ 	)Z(	) 	) 	)s   AA!c                   |j                         }t        ddd      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t               }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d       k(        sJ |j                  dd      |j                  dd      k(  sJ y	)
a  
        define x = Variable((2,2)) with
        [[x11, x12],
         [x21, x22]]

        x is represented as eye(4) in the A matrix (in column-major order), i.e.,

         x11 x21 x12 x22
        [[1   0   0   0],
         [0   1   0   0],
         [0   0   1   0],
         [0   0   0   1]]

        neg(x) means we now have
         [[-x11, -x21],
          [-x12, -x22]],

         i.e.,

         x11 x21 x12 x22
        [[-1  0   0   0],
         [0  -1   0   0],
         [0   0  -1   0],
         [0   0   0  -1]]
        r   variabler   r   r   r   r6   r6   r6   r   N)get_empty_viewr   process_constraintget_tensor_representationsp
coo_matrixr   r$   r%   r(   r    r#   eyeneg)	r@   rA   
empty_viewvariable_lin_opviewview_A
neg_lin_opout_viewr)   s	            r   test_negzTestBackends.test_neg[   s9   4 ++-
%f:AF))/:F //15fjj&**-EFfU]]_vvfq	)*** ]
;;z40..q!4 MM166AEE155>2&AIIKvvaBFF1I:o&&& 11!Q74;Y;YZ[]^;____r   c                &   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        dd	g|g
      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  g dg dg dg dg      }t        j                  ||k(        sJ |j                  dd      |j                  dd      k(  sJ y	)a}  
        define x = Variable((2,2)) with
        [[x11, x12],
         [x21, x22]]

        x is represented as eye(4) in the A matrix (in column-major order), i.e.,

         x11 x21 x12 x22
        [[1   0   0   0],
         [0   1   0   0],
         [0   0   1   0],
         [0   0   0   1]]

        transpose(x) means we now have
         [[x11, x21],
          [x12, x22]]

        which, when using the same columns as before, now maps to

         x11 x21 x12 x22
        [[1   0   0   0],
         [0   0   1   0],
         [0   1   0   0],
         [0   0   0   1]]

        -> It reduces to reordering the rows of A.
        r   r\   r   r]   r   r6   r^   r   Nr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   	transposer!   )	r@   rA   rg   rh   ri   transpose_lin_oprk   r)   expecteds	            r   test_transposezTestBackends.test_transpose   sQ   : &f:AF))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***&vTF/ARS$$%5t<..q!4 MM166AEE155>2&AIIK88\<|TUvva8m$$$ 11!Q74;Y;YZ[]^;____r   c                    t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        t        d      g	      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd
      j                         }t        j                  g dg      }t        j                  ||k(        sJ |j                  dd      |j                  dd      k(  sJ y)a>  
        define x = Variable((2,2)) with
        [[x11, x12],
         [x21, x22]]

        x is represented as eye(4) in the A matrix (in column-major order), i.e.,

         x11 x21 x12 x22
        [[1   0   0   0],
         [0   1   0   0],
         [0   0   1   0],
         [0   0   0   1]]

        upper_tri(x) means we select only x12 (the diagonal itself is not considered).

        which, when using the same columns as before, now maps to

         x11 x21 x12 x22
        [[0   0   0   1]]

        -> It reduces to selecting a subset of the rows of A.
        r   r\   r   r]   r   r6   r^   r   r   r   r6   rp   N)r   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   	upper_trir!   )	r@   rA   rg   rh   ri   upper_tri_lin_oprk   r)   ru   s	            r   test_upper_trizTestBackends.test_upper_tri   sI   0 &f:AF))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***&[-@,AB$$%5t<..q!4 MM166AEE155>2&AIIK88\N+vva8m$$$ 11!Q74;Y;YZ[]^;____r   c                   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        t        dd	d      t        ddd      g|g
      }|j                  ||      }|j                  dd	      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  g dg dg      }t        j                  ||k(        sJ t        t        ddd      g|g
      }	|j                  |	|      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  g dg      }t        j                  ||k(        sJ |j                  dd      |j                  dd      k(  sJ y)a  
        define x = Variable((2,2)) with
        [[x11, x12],
         [x21, x22]]

        x is represented as eye(4) in the A matrix (in column-major order), i.e.,

         x11 x21 x12 x22
        [[1   0   0   0],
         [0   1   0   0],
         [0   0   1   0],
         [0   0   0   1]]

        index() returns the subset of rows corresponding to the slicing of variables.

        e.g. x[0:2,0] yields
         x11 x21 x12 x22
        [[1   0   0   0],
         [0   1   0   0]]

         Passing a single slice only returns the corresponding row of A.
         Note: Passing a single slice does not happen when slicing e.g. x[0], which is expanded to
         the 2d case.

         -> It reduces to selecting a subset of the rows of A.
        r   r\   r   r]   r   r6   r^   r   r   rn   r   r6   ro   rq   ry   Nr   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   sliceindexr!   
r@   rA   rg   rh   ri   index_2d_lin_oprk   r)   ru   index_1d_lin_ops
             r   
test_indexzTestBackends.test_index   s   8 &f:AF))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***%E!QNE!QN+KSbRcd==$7..q!4 MM166AEE155>2&AIIK88\<89vva8m$$$%E!QN+;?BST==$7..q!4 MM166AEE155>2&AIIK88\N+vva8m$$$ 11!Q74;Y;YZ[]^;____r   c                   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        dd	      }|j                  ||      }|j                  dd
      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  g dg dg      }t        j                  ||k(        sJ |j                  dd      |j                  dd      k(  sJ y)aK  
        define x = Variable((2,2)) with
        [[x11, x12],
         [x21, x22]]

        x is represented as eye(4) in the A matrix (in column-major order), i.e.,

         x11 x21 x12 x22
        [[1   0   0   0],
         [0   1   0   0],
         [0   0   1   0],
         [0   0   0   1]]

        diag_mat(x) means we select only the diagonal, i.e., x11 and x22.

        which, when using the same columns as before, now maps to

         x11 x21 x12 x22
        [[1   0   0   0],
         [0   0   0   1]]

        -> It reduces to selecting a subset of the rows of A.
        r   r\   r   r]   r   r6   r^   r   r   r   r   r~   ro   rr   Nr   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   diag_matr!   )	r@   rA   rg   rh   ri   diag_mat_lin_oprk   r)   ru   s	            r   test_diag_matzTestBackends.test_diag_mat  sD   2 &f:AF))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***%F;##OT:..q!4 MM166AEE155>2&AIIK88\<89vva8m$$$ 11!Q74;Y;YZ[]^;____r   c                   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ d}t        d	|
      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  g dg      }	t        j                  ||	k(        sJ |j                  dd      |j                  dd      k(  sJ y)a7  
        define x = Variable((2,2)) with
        [[x11, x12],
         [x21, x22]]

        x is represented as eye(4) in the A matrix (in column-major order), i.e.,

         x11 x21 x12 x22
        [[1   0   0   0],
         [0   1   0   0],
         [0   0   1   0],
         [0   0   0   1]]

        diag_mat(x, k=1) means we select only the 1-(super)diagonal, i.e., x12.

        which, when using the same columns as before, now maps to

         x11 x21 x12 x22
        [[0   0   1   0]]

        -> It reduces to selecting a subset of the rows of A.
        r   r\   r   r]   r   r6   r^   r   r   r   r   ry   rp   Nr   )
r@   rA   rg   rh   ri   kr   rk   r)   ru   s
             r   test_diag_mat_with_offsetz&TestBackends.test_diag_mat_with_offsetL  sF   0 &f:AF))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***%F;##OT:..q!4 MM166AEE155>2&AIIK88\N+vva8m$$$ 11!Q74;Y;YZ[]^;____r   c                    t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        dd	      }|j                  ||      }|j                  dd
      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  ddgddgddgddgg      }t        j                  ||k(        sJ |j                  dd
      |j                  dd
      k(  sJ y)a  
        define x = Variable((2,)) with
        [x1, x2]

        x is represented as eye(2) in the A matrix, i.e.,

         x1  x2
        [[1  0],
         [0  1]]

        diag_vec(x) means we introduce zero rows as if the vector was the diagonal
        of an n x n matrix, with n the length of x.

        Thus, when using the same columns as before, we now have

         x1  x2
        [[1  0],
         [0  0],
         [0  0],
         [0  1]]
        r   r\   r   r]   r   r   r   r   r   r6   )r6   r   Nr   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   diag_vecr!   )	r@   rA   rg   rh   ri   diag_vec_lin_oprk   r)   ru   s	            r   test_diag_veczTestBackends.test_diag_vecy  sX   . &d!D))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***%F;##OT:..q!4 MM166AEE155>2&AIIK88aVaVaVaV<=vva8m$$$ 11!Q74;Y;YZ[]^;____r   c                B   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ d}t        d	|
      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  ddgddgddgddgddgddgddgddgddgg	      }	t        j                  ||	k(        sJ |j                  dd      |j                  dd      k(  sJ y)a  
        define x = Variable((2,)) with
        [x1, x2]

        x is represented as eye(2) in the A matrix, i.e.,

         x1  x2
        [[1  0],
         [0  1]]

        diag_vec(x, k) means we introduce zero rows as if the vector was the k-diagonal
        of an n+|k| x n+|k| matrix, with n the length of x.

        Thus, for k=1 and using the same columns as before, want to represent
        [[0  x1 0],
        [ 0  0  x2],
        [[0  0  0]]
        i.e., unrolled in column-major order:

         x1  x2
        [[0  0],
        [0  0],
        [0  0],
        [1  0],
        [0  0],
        [0  0],
        [0  0],
        [0  1],
        [0  0]]
        r   r\   r   r]   r   r   r   r   r4   r4   r   	   )r   r   Nr   )
r@   rA   rg   rh   ri   r   r   rk   r)   ru   s
             r   test_diag_vec_with_offsetz&TestBackends.test_diag_vec_with_offset  s   @ &d!D))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***%F;##OT:..q!4 MM166AEE155>2&AIIK88VaVaVaVaVaVaVaVaQRVT
 vva8m$$$ 11!Q74;Y;YZ[]^;____r   c                   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        dd	d
g|g      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  ddgg      }t        j                  ||k(        sJ |j                  dd      |j                  dd      k(  sJ y	)aw  
        define x = Variable((2,)) with
        [x1, x2]

        x is represented as eye(2) in the A matrix, i.e.,

         x1  x2
        [[1  0],
         [0  1]]

        sum_entries(x) means we consider the entries in all rows, i.e., we sum along the row axis.

        Thus, when using the same columns as before, we now have

         x1  x2
        [[1  1]]
        r   r\   r   r]   r   r   r   r   NTr   r   r   r1   r   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   sum_entriesr!   )	r@   rA   rg   rh   ri   sum_entries_lin_oprk   r)   ru   s	            r   test_sum_entrieszTestBackends.test_sum_entries  sQ   & &d!D))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***(tTlRaQbc&&'94@..q!4 MM166AEE155>2&AIIK88aVH%vva8m$$$ 11!Q74;Y;YZ[]^;____r   c                   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        d      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd	      j                         }t        j                  dgdgdgg      }t        j                  ||k(        sJ |j                  dd      |j                  dd      k(  sJ y
)a|  
        define x = Variable((1,)) with
        [x1,]

        x is represented as eye(1) in the A matrix, i.e.,

         x1
        [[1]]

        promote(x) means we repeat the row to match the required dimensionality of n rows.

        Thus, when using the same columns as before and assuming n = 3, we now have

         x1
        [[1],
         [1],
         [1]]
        r   r\   r   r]   r   r   r   r4   r4   r   N)r   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   promoter!   )	r@   rA   rg   rh   ri   promote_lin_oprk   r)   ru   s	            r   test_promotezTestBackends.test_promote  sG   ( &d!D))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***$T*??>48..q!4 MM166AEE155>2&AIIK88aS1#sO,vva8m$$$ 11!Q74;Y;YZ[]^;____r   c           	     0   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        d	d	|g
      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  g dg dg dg dg dg dg      }t        j                  ||k(        sJ |j                  dd      |j                  dd      k(  sJ y)a  
        define x = Variable(3) with
        [x1, x2, x3]

        x is represented as eye(3) in the A matrix, i.e.,
         x1 x2 x3
        [[1  0  0],
         [0  1  0],
         [0  0  1]]
        
        broadcast_to(x, (2, 3)) means we repeat every variable twice along the row axis.

        Thus we expect the following A matrix:
        
         x1 x2 x3
        [[1  0  0],
         [1  0  0],
         [0  1  0],
         [0  1  0]
         [0  0  1],
         [0  0  1]]
        r   r\   r   r]   r   r4   r   r   r   r4   rn   )   r4   )r   r   r   )r   r   r   )r   r   r   Nr   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   broadcast_tor!   	r@   rA   rg   rh   ri   broadcast_lin_oprk   r)   ru   s	            r   test_broadcast_to_rowsz#TestBackends.test_broadcast_to_rows*  s^   . &d!D))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***&u5?PQ''(8$?..q!4 MM166AEE155>2&AIIK88Y&&&&&( ) vva8m$$$ 11!Q74;Y;YZ[]^;____r   c           	     0   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        d	d	|g
      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  ddgddgddgddgddgddgg      }t        j                  ||k(        sJ |j                  dd      |j                  dd      k(  sJ y)a  
        define x = Variable((2,1)) with
        [[x1], 
         [x2]]

        x is represented as eye(2) in the A matrix, i.e.,
         x1 x2
        [[1  0],
         [0  1]]
        
        broadcast_to(x, (2, 3)) means we tile the variables three times along the rows

        Thus we expect the following A matrix:
        
         x1 x2
        [[1  0],
         [0  1],
         [1  0],
         [0  1]
         [1  0],
         [0  1]]
        r   r   r\   r   r]   r   r   r   r   r   rn   r4   )r   r   Nr   r   s	            r   test_broadcast_to_colsz#TestBackends.test_broadcast_to_colsZ  sv   . &e*1E))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***&u5?PQ''(8$?..q!4 MM166AEE155>2&AIIK88aVVVVVV% & vva8m$$$ 11!Q74;Y;YZ[]^;____r   c                   t        ddd      }t        ddd      }t        ||g      }ddd|_        |j                  ||j                               }|j	                  dd      }t        j                  |j                  |j                  |j                  ffd	
      j                         }t        j                  d      }t        j                  ||k(        sJ y)z
        define x,y = Variable((1,)), Variable((1,))

        hstack([x, y]) means the expression should be represented in the A matrix as if it
        was a Variable of shape (2,), i.e.,

          x  y
        [[1  0],
         [0  1]]
        r   r\   r   r]   r   rx   r   r1   r   r   N)r   rJ   hstackr_   ra   rb   rc   r   r$   r%   r(   r    rd   r#   )r@   rA   lin_op_xlin_op_yhstack_lin_oprk   r)   ru   s           r   test_hstackzTestBackends.test_hstack  s     t*1=t*1=#(H)=> !aL>>-1G1G1IJ..q!4 MM166AEE155>2&AIIK66!9vva8m$$$r   c                   t        ddd      }t        ddd      }t        ||g      }ddd|_        |j                  ||j                               }|j	                  dd      }t        j                  |j                  |j                  |j                  ffd	
      j                         }t        j                  g dg dg dg dg      }t        j                  ||k(        sJ y)aU  
        define x,y = Variable((1,2)), Variable((1,2)) with
        [[x1, x2]]
        and
        [[y1, y2]]

        vstack([x, y]) yields

        [[x1, x2],
         [y1, y2]]

        which maps to

         x1   x2  y1  y2
        [[1   0   0   0],
         [0   0   1   0],
         [0   1   0   0],
         [0   0   0   1]]
        r1   r\   r   r]   r   rx   r   r6   r^   r   ro   rp   rq   rr   N)r   rJ   vstackr_   ra   rb   rc   r   r$   r%   r(   r    r!   r#   )r@   rA   r   r   vstack_lin_oprk   r)   ru   s           r   test_vstackzTestBackends.test_vstack  s    * vJQ?vJQ?#(H)=> !aL>>-1G1G1IJ..q!4 MM166AEE155>2&AIIK88\<|TUvva8m$$$r   c                \   ddd|_         t        ddd      }t        ddd      }t        ||gdg      }ddd|_         |j                  ||j                               }|j	                  dd      }t        j                  |j                  |j                  |j                  ffd	
      j                         }t        j                  d      }t        j                  ||k(        sJ t        ||gdg      }|j                  ||j                               }|j	                  dd      }t        j                  |j                  |j                  |j                  ffd	
      j                         }t        j                  g dg dg dg dg      }t        j                  ||k(        sJ y)a  
        Define x,y = Variable((1,2)), Variable((1,2)) with
        [[x1, x2]]
        and
        [[y1, y2]]

        concatenate([x, y], axis = 0) yields

        [[x1, x2],
         [y1, y2]]

        which maps to

         x1   x2  y1  y2
        [[1   0   0   0],
         [0   0   1   0],
         [0   1   0   0],
         [0   0   0   1]]

        Note that in this case concatenate is equivalent to vstack

        Applying concatenate([x, y], axis=1) yields:

        [[x1, x2, y1, y2]]

        Which is equivalent to hstack([x, y]) in this context.

        The mapping to the matrix A would be:

          x1  x2  y1  y2
         [[1   0   0  0],
          [0   1   0  0],
          [0   0   1  0],
          [0   0   0  1]]

        r   r   r1   r\   r   r]   r   r   r6   r^   r   ro   rp   rq   rr   N)rJ   r   concatenater_   ra   rb   rc   r   r$   r%   r(   r    rd   r#   r!   )r@   rA   r   r   concatenate_lin_oprk   r)   ru   s           r   test_concatenatezTestBackends.test_concatenate  sq   L !"aL vJQ?vJQ?(x.BA3O !aL&&'97;Q;Q;ST..q!4 MM166AEE155>2&AIIK66!9vva8m$$$ )x.BA3O&&'97;Q;Q;ST..q!4 MM166AEE155>2&AIIK88\<|TUvva8m$$$r   zaxis, variable_indicesr   )r   r      r   r   r4   r      r6            r            r   )r   r   r   r4   r   r   r   r   r6   r   r   r   r   r   r   r   r      Nc                   d }ddd|_         t        ddd      }t        ddd	      }t        ||g|g
      }|j                  ||j                               }|j	                  dd      }	t        j                  |	j                  |	j                  |	j                  ffd      j                         }	 ||      }
t        j                  |	|
k(        sJ y)aN  
        Test the concatenate operation with variables of shape (2, 2, 2)
        along different axes

        Define variables x and y, each of shape (2, 2, 2):

        x = [
            [[x000, x001],
            [x010, x011]],
            [[x100, x101],
            [x110, x111]]
            ]

        y = [
            [[y000, y001],
            [y010, y011]],
            [[y100, y101],
            [y110, y111]]
            ]

        The variables are assigned indices as follows:

        Indices for x:
            x000: 0, x001: 1, x010: 2, x011: 3,
            x100: 4, x101: 5, x110: 6, x111: 7

        Indices for y:
            y000: 8, y001: 9, y010: 10, y011: 11,
            y100: 12, y101: 13, y110: 14, y111: 15

        How we chose the list of variable_indices:

        - For each axis, we perform the concatenation of x and y along that axis.
        - We assign indices to the variables in x and y as per their positions.
        - For each argument, we generate an array of indices from 0 to the number of
        elements minus one, reshaped to the argument's shape with 'F' order
        (column-major order), and offset by the cumulative
        number of elements from previous arguments.

        - We concatenate these indices along the specified axis.
        - We flatten the concatenated indices with 'F' order to obtain the variable_indices,
        which represent the order of variables in the flattened concatenated tensor.

        The expected variable_indices are:

        For axis=0:
            [0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15]

        For axis=1:
            [0, 1, 2, 3, 8, 9, 10, 11, 4, 5, 6, 7, 12, 13, 14, 15]

        For axis=2:
            [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

        For axis=None:
            [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

        axis=None follows NumPy; arrays are flattened in 'C' order before concatenating,
        so the resulting array is [x000, x001, x010, x011, x100, x101, x110, x111,
                                y000, y001, y010, y011, y100, y101, y110, y111]
        c                    t        j                  dt              }t        j                  d      }t	        ||       D ]  \  }}d|||f<    |S )Nr   r   )dtyper   r   )r    zerosintarangezip)variable_indicesr)   	positionsposvar_idxs        r   get_expected_matrixz=TestBackends.test_concatenate_nd.<locals>.get_expected_matrixN  sL    -A		"I #I/? @ $W"##w,$Hr   r   r   r1   r   r   r   r\   r   r]   r   r   r   r   r   N)rJ   r   r   r_   ra   rb   rc   r   r$   r%   r(   r    r#   )r@   rA   axisr   r   r   r   r   rk   r)   
expected_As              r   test_concatenate_ndz TestBackends.test_concatenate_nd  s    P	 !"aL yzByzB )x.BD6R&&'97;Q;Q;ST..q"5MM166AEE155>2(CKKM()9:
vva:o&&&r   c           	     p   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        dd	t        j                  dd
gddgg            }t        ||g      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  g dg dg dg dg      }	t        j                  ||	k(        sJ |j                  dd      |j                  dd      k(  sJ y)a  
        define x = Variable((2,2)) with
        [[x11, x12],
         [x21, x22]]

         Multiplying with the constant from the left
        [[1, 2],
         [3, 4]],

         we expect the output to be
        [[  x11 + 2 x21,   x12 + 2 x22],
         [3 x11 + 4 x21, 3 x12 + 4 x22]]

        i.e., when represented in the A matrix (again using column-major order):
         x11 x21 x12 x22
        [[1   2   0   0],
         [3   4   0   0],
         [0   0   1   2],
         [0   0   3   4]]
        r   r\   r   r]   r   r6   r^   r   dense_constr   r4   rn   )r   r   r   r   )r4   r6   r   r   )r   r   r   r   )r   r   r4   r6   N)r   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   r!   mul)
r@   rA   rg   rh   ri   lhs
mul_lin_oprk   r)   ru   s
             r   test_mulzTestBackends.test_mule  sn   , &f:AF))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***&}288aVaQRVDT;UV c0AB
;;z40..q!4 MM166AEE155>2&AIIK88\<|TUvva8m$$$ 11!Q74;Y;YZ[]^;____r   c                \   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        d	d
t        j                  ddg            }t        ||g      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  g dg dg      }	t        j                  ||	k(        sJ |j                  dd      |j                  dd      k(  sJ y)a  
        define x = Variable((2,2)) with
        [[x11, x12],
         [x21, x22]]

         Multiplying with the constant from the right
         (intentionally using 1D vector to cover edge case)
        [1, 2]

         we expect the output to be
         [[x11 + 2 x12],
          [x21 + 2 x22]]

        i.e., when represented in the A matrix:
         x11 x21 x12 x22
        [[1   0   2   0],
         [0   1   0   2]]
        r   r\   r   r]   r   r6   r^   r   r   r   r   rn   r~   )r   r   r   r   )r   r   r   r   N)r   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   r!   rmul)
r@   rA   rg   rh   ri   rhsrmul_lin_oprk   r)   ru   s
             r   	test_rmulzTestBackends.test_rmul  s`   ( &f:AF))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***$]1a&9IJ!s/1BC<<T2..q!4 MM166AEE155>2&AIIK88\<89vva8m$$$ 11!Q74;Y;YZ[]^;____r   c                X   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        dd	t        j                  dd
g            }t        |      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  ddgdd
gg      }	t        j                  ||	k(        sJ |j                  dd      |j                  dd      k(  sJ y)ai  
        define x = Variable((2,)) with
        [x1, x2]

        x is represented as eye(2) in the A matrix, i.e.,

         x1  x2
        [[1  0],
         [0  1]]

         mul_elementwise(x, a) means 'a' is reshaped into a column vector and multiplied by A.
         E.g. for a = (2,3), we obtain

         x1  x2
        [[2  0],
         [0  3]]
        r   r\   r   r]   r   r   r   r   r   r4   r   N)r   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   r!   mul_elem)
r@   rA   rg   rh   ri   r   mul_elementwise_lin_oprk   r)   ru   s
             r   test_mul_elementwisez!TestBackends.test_mul_elementwise  sg   & &d!D))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***$]1a&9IJ!,#!6##$:DA..q!4 MM166AEE155>2&AIIK88aVaV,-vva8m$$$ 11!Q74;Y;YZ[]^;____r   c           	     l   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        dd	t        j                  dd
gddgg            }t        |      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  g dg dg dg dg      }	t        j                  ||	k(        sJ |j                  dd      |j                  dd      k(  sJ y)a9  
        define x = Variable((2,2)) with
        [[x11, x12],
         [x21, x22]]

         Dividing elementwise with
        [[1, 2],
         [3, 4]],

        we obtain:
         x11 x21 x12 x22
        [[1   0   0   0],
         [0   1/3 0   0],
         [0   0   1/2 0],
         [0   0   0   1/4]]
        r   r\   r   r]   r   r6   r^   r   r   r   r4   r   ro   )r   UUUUUU?r   r   )r   r         ?r   )r   r   r         ?N)r   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   r!   div)
r@   rA   rg   rh   ri   r   
div_lin_oprk   r)   ru   s
             r   test_divzTestBackends.test_div  sl   $ &f:AF))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***&}288aVaQRVDT;UV c*
;;z40..q!4 MM166AEE155>2&AIIK88\+;=MO_`avva8m$$$ 11!Q74;Y;YZ[]^;____r   c                   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        |g	      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd
      j                         }t        j                  g dg      }t        j                  ||k(        sJ |j                  dd      |j                  dd      k(  sJ y)a  
        define x = Variable((2,2)) with
        [[x11, x12],
         [x21, x22]]

        x is represented as eye(4) in the A matrix (in column-major order), i.e.,

         x11 x21 x12 x22
        [[1   0   0   0],
         [0   1   0   0],
         [0   0   1   0],
         [0   0   0   1]]

        trace(x) means we sum the diagonal entries of x, i.e.

         x11 x21 x12 x22
        [[1   0   0   1]]
        r   r\   r   r]   r   r6   r^   r   rx   ry   )r   r   r   r   N)r   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   tracer!   )	r@   rA   rg   rh   ri   trace_lin_oprk   r)   ru   s	            r   
test_tracezTestBackends.test_trace  s@   ( &f:AF))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***"(9:==t4..q!4 MM166AEE155>2&AIIK88\N+vva8m$$$ 11!Q74;Y;YZ[]^;____r   c                p   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        dd	t        j                  g d
            }t        |d|g      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  g dg dg dg dg dg      }	t        j                  ||	k(        sJ |j                  dd      |j                  dd      k(  sJ y)ai  
        define x = Variable((3,)) with
        [x1, x2, x3]

        having f = [1,2,3], conv(f, x) means we repeat the column vector of f for each column in
        the A matrix, shifting it down by one after each repetition, i.e.,
          x1 x2 x3
        [[1  0  0],
         [2  1  0],
         [3  2  1],
         [0  3  2],
         [0  0  3]]
        r   r\   r   r]   r   r4   r   r   r   )r   r   r4   )r   r   )r   r   r   r   )r   r4   )      ?        r   )       @r   r   )      @r   r   )r   r   r   )r   r   r   N)r   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   r!   conv)
r@   rA   rg   rh   ri   fconv_lin_oprk   r)   ru   s
             r   	test_convzTestBackends.test_conv4  sj    &d!D))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***=rxx	7JK!qo=NO<<T2..q!4 MM166AEE155>2&AIIK88oQ`a
 vva8m$$$ 11!Q74;Y;YZ[]^;____r   c                   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        d	d
t        j                  dgdgg            }t        ||g      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  g dg dg dg dg dg dg dg dg      }	t        j                  ||	k(        sJ |j                  dd      |j                  dd      k(  sJ y)a  
        define x = Variable((2,2)) with
        [[x11, x12],
         [x21, x22]]

        and
        a = [[1],
             [2]],

        kron(a, x) means we have
        [[x11, x12],
         [x21, x22],
         [2x11, 2x12],
         [2x21, 2x22]]

        i.e. as represented in the A matrix (again in column-major order)

         x11 x21 x12 x22
        [[1   0   0   0],
         [0   1   0   0],
         [2   0   0   0],
         [0   2   0   0],
         [0   0   1   0],
         [0   0   0   1],
         [0   0   2   0],
         [0   0   0   2]]

        However computing kron(a, x) (where x is represented as eye(4))
        directly gives us:
        [[1   0   0   0],
         [2   0   0   0],
         [0   1   0   0],
         [0   2   0   0],
         [0   0   1   0],
         [0   0   2   0],
         [0   0   0   1],
         [0   0   0   2]]
        So we must swap the row indices of the resulting matrix.
        r   r\   r   r]   r   r6   r^   r   r   r   r   rn   r   r   r6   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   N)r   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   r!   kron_r)
r@   rA   rg   rh   ri   akron_r_lin_oprk   r)   ru   s
             r   test_kron_rzTestBackends.test_kron_r[  s   R &f:AF))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***]A3*9MN#/1BC>>-6..q!4 MM166AEE155>2&AIIK88$$$$$$$$	
 vva8m$$$ 11!Q74;Y;YZ[]^;____r   c                   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        d	d
t        j                  ddgg            }t        ||g      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  g dg dg dg dg dg dg dg dg      }	t        j                  ||	k(        sJ |j                  dd      |j                  dd      k(  sJ y)a  
        define x = Variable((2,2)) with
        [[x11, x12],
         [x21, x22]]

        and
        a = [[1, 2]],

        kron(x, a) means we have
        [[x11, 2x11, x12, 2x12],
         [x21, 2x21, x22, 2x22]]

        i.e. as represented in the A matrix (again in column-major order)

         x11 x21 x12 x22
        [[1   0   0   0],
         [0   1   0   0],
         [2   0   0   0],
         [0   2   0   0],
         [0   0   1   0],
         [0   0   0   1],
         [0   0   2   0],
         [0   0   0   2]]

         However computing kron(x, a) (where a is reshaped into a column vector
         and x is represented as eye(4)) directly gives us:
        [[1   0   0   0],
         [2   0   0   0],
         [0   1   0   0],
         [0   2   0   0],
         [0   0   1   0],
         [0   0   2   0],
         [0   0   0   1],
         [0   0   0   2]]
        So we must swap the row indices of the resulting matrix.
        r   r\   r   r]   r   r6   r^   r   r1   r   r   rn   r   r   r  r  r  r  r  r  r  r  N)r   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   r!   kron_l)
r@   rA   rg   rh   ri   r
  kron_l_lin_oprk   r)   ru   s
             r   test_kron_lzTestBackends.test_kron_l  s}   L &f:AF))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***]Aq6(9KL#/1BC>>-6..q!4 MM166AEE155>2&AIIK88$$$$$$$$	
 vva8m$$$ 11!Q74;Y;YZ[]^;____r   c                   |j                  dd      }t        j                  |t        j                  d      k(        sJ 	 |j                  dd      }t        j                  |g dk(        sJ |j                  dd      }t        j                  |t        j                  d      k(        sJ |j                  dd      }t        j                  |g dk(        sJ |j                  dd      }g d	}t        j                  ||k(        sJ y
)ax  
        kron(l,r)
        with
        l = [[x1, x3],  r = [[a],
             [x2, x4]]       [b]]

        yields
        [[ax1, ax3],
         [bx1, bx3],
         [ax2, ax4],
         [bx2, bx4]]

        Which is what we get when we compute kron(l,r) directly,
        as l is represented as eye(4) and r is reshaped into a column vector.

        So we have:
        kron(l,r) =
        [[a, 0, 0, 0],
         [b, 0, 0, 0],
         [0, a, 0, 0],
         [0, b, 0, 0],
         [0, 0, a, 0],
         [0, 0, b, 0],
         [0, 0, 0, a],
         [0, 0, 0, b]].

        Thus, this function should return arange(8).
        r   r   r   )r   r   r6   r   r   r4   r   r   r1   r4   r   r   )r   r   r6   r   r4   r   r   r   r   r   r   r   )r   r   r6   r   r   r4   r   r   r   r   r   r   r   r   r   r   N)_get_kron_row_indicesr    r#   r   )r@   rA   indicesru   s       r   test_get_kron_row_indicesz&TestBackends.test_get_kron_row_indices  s    : //?vvg1-...	< //?vvg!99::://?vvg2./////?vvg!GGHHH//?Ivvg)***r   c                
   |j                         }|j                  d d       J ddgi}ddgi}|j                  |d       |k(  sJ |j                  d |      |k(  sJ |j                  ||      |j                  ||      k(  sJ y )Nr
  r   br   )r_   combine_potentially_none	add_dicts)r@   rA   rh   r
  r  s        r   )test_tensor_view_combine_potentially_nonez6TestBackends.test_tensor_view_combine_potentially_none7  s    %%',,T48@@@1#J1#J,,Q5:::,,T15:::,,Q2dnnQ6JJJJr   )'r   r   r   staticmethodr=   fixturebackendsrA   rZ   rl   rv   r|   r   r   r   r   r   r   r   r   r   r   r   r   markparametrizelistranger   r   r   r   r   r   r   r  r  r  r  r   r   r   rD   rD   C   s8   V^^8$ % ),`\/`b*`X7`r+`Z+`Z)`V5`n%`N&`P.``.``%2 %D>%B [[5	
BC	
BC	
DrO	tE"I	8 	S'	S'j*`X(`T'`R&`P&`P%`NH`TE`NI+VKr   rD   c                      e Zd Ze ej
                  e      d               Zd Zd Z	d Z
d Zd Zd Zd	 Zd
 Zd Zd Zy)TestParametrizedBackendsrE   c                    ddiddddddddd}t        j                  | j                  fi |}t        |t              sJ |S Nr   r   r   r3   r   r   r3   r4   rI   rO   rQ   s      r   param_backendz&TestParametrizedBackends.param_backendB  W     Q"#] !qM#$
 **7==CFC'#5666r   c                   t        ddd      }ddd|_        t        ddd	      }|j                  ||j                               }t        |
      }|j	                  ||      }t        dd      }|j                  ||      }|j                  dd      }	|	j                  d      j                         ddddf   }
t        j                  ddgddgddgddgg      }t        j                  |
|k(        sJ |	j                  d	      j                         ddddf   }t        j                  ddgddgddgddgg      }t        j                  ||k(        sJ |j                  dd      |j                  dd      k(  sJ y)a  
        Starting with a parametrized expression
        x1  x2
        [[[1  0],
         [0  0]],

         [[0  0],
         [0  1]]]

        diag_vec(x) means we introduce zero rows as if the vector was the diagonal
        of an n x n matrix, with n the length of x.

        Thus, when using the same columns as before, we now have

         x1  x2
        [[[1  0],
          [0  0],
          [0  0],
          [0  0]]

         [[0  0],
          [0  0],
          [0  0],
          [0  1]]]
        r   rP   r   r]   r   r4   r'  r\   r   r   r   r   r6   Nr3   r   r   r   rL   r`   r_   r   r   ra   get_param_slicer(   r    r!   r#   )r@   r(  param_lin_oprg   var_viewmul_elem_lin_opparam_var_viewr   rk   out_reprslice_idx_zeroexpected_idx_zeroslice_idx_oneexpected_idx_ones                 r   test_parametrized_diag_vecz3TestParametrizedBackends.test_parametrized_diag_vecQ  s   6 #4gA>)*]"%d!D 33O]EaEaEcd%<8&//J%F; ))/>J55a;!11!4<<>q#2#vFHHsCj3*sCj3PS*%UVvvn(99::: 003;;=a"fE88c3Z#sc3Z#s$TUvvm'77888 11!Q7>;c;cq<
 
 	
 
r   c                H   t        ddd      }ddd|_        t        ddd	      }|j                  ||j                               }t        |
      }|j	                  ||      }d	}t        d|      }|j                  ||      }	|	j                  dd      }
|
j                  d      j                         ddddf   }t        j                  ddgddgddgddgddgddgddgddgddgg	      }t        j                  ||k(        sJ |
j                  d	      j                         ddddf   }t        j                  ddgddgddgddgddgddgddgddgddgg	      }t        j                  ||k(        sJ |	j                  dd      |j                  dd      k(  sJ y)al  
        Starting with a parametrized expression
        x1  x2
        [[[1  0],
          [0  0]],

         [[0  0],
          [0  1]]]

        diag_vec(x, k) means we introduce zero rows as if the vector was the k-diagonal
        of an n+|k| x n+|k| matrix, with n the length of x.

        Thus, for k=1 and using the same columns as before, want to represent
        [[0  x1 0],
         [0  0  x2],
         [0  0  0]]
        parametrized across two slices, i.e., unrolled in column-major order:

        slice 0         slice 1
         x1  x2          x1  x2
        [[0  0],        [[0  0],
         [0  0],         [0  0],
         [0  0],         [0  0],
         [1  0],         [0  0],
         [0  0],         [0  0],
         [0  0],         [0  0],
         [0  0],         [0  0],
         [0  0],         [0  1],
         [0  0]]         [0  0]]
        r   rP   r   r]   r   r4   r'  r\   r   r   r   r   r   Nr3   r   r   r+  )r@   r(  r-  rg   r.  r/  r0  r   r   rk   r1  r2  r3  r4  r5  s                  r   &test_parametrized_diag_vec_with_offsetz?TestParametrizedBackends.test_parametrized_diag_vec_with_offset  s   @ #4gA>)*]"%d!D 33O]EaEaEcd%<8&//J%F; ))/>J55a;!11!4<<>q#2#vFHHc
c
c
c
c
c
c
c
c


 vvn(99::: 003;;=a"fE88c
c
c
c
c
c
c
c
c


 vvm'77888 11!Q7>;c;cq<
 
 	
 
r   c                   t        ddd      }ddd|_        t        ddd	      }|j                  ||j                               }t        |
      }|j	                  ||      }t        dddg|g      }|j                  ||      }|j                  dd	      }	|	j                  d      j                         ddddf   }
t        j                  ddgg      }t        j                  |
|k(        sJ |	j                  d	      j                         ddddf   }t        j                  ddgg      }t        j                  ||k(        sJ |j                  dd	      |j                  dd	      k(  sJ y)ao  
        starting with a parametrized expression
        x1  x2
        [[[1  0],
         [0  0]],

         [[0  0],
         [0  1]]]

        sum_entries(x) means we consider the entries in all rows, i.e., we sum along the row axis.

        Thus, when using the same columns as before, we now have

         x1  x2
        [[[1  0]],

         [[0  1]]]
        r   rP   r   r]   r   r4   r'  r\   r   r   NTr   r3   r   r   )r   rL   r`   r_   r   r   ra   r,  r(   r    r!   r#   )r@   r(  r-  rg   r.  r/  r0  r   rk   r1  r2  r3  r4  r5  s                 r   test_parametrized_sum_entriesz6TestParametrizedBackends.test_parametrized_sum_entries  sw   & #4gA>)*]"%d!D 33O]EaEaEcd%<8&//J(t4,oM^_ ,,-?P55a;!11!4<<>q#2#vFHHsCj\2vvn(99::: 003;;=a"fE88c3ZL1vvm'77888 11!Q7>;c;cq<
 
 	
 
r   c                   t        ddd      }ddd|_        ddd|_        d	|_        d|_        |j                  ||j                               }|j                  dd      }t        j                  |j                  |j                  |j                  ffd
      j                         }t        j                  |t        j                   d      k(        sJ t        ddd      }t        ||g      }|j#                  ||      }|j                  dd      }|j%                  d      j                         ddddf   }	t        j&                  g dg dg dg dg      }
t        j                  |	|
k(        sJ |j%                  d      j                         ddddf   }t        j&                  g dg dg dg dg      }t        j                  ||k(        sJ |j%                  d      j                         ddddf   }t        j&                  g dg dg dg dg      }t        j                  ||k(        sJ |j%                  d      j                         ddddf   }t        j&                  g dg dg dg dg      }t        j                  ||k(        sJ |j                  dd      |j                  dd      k(  sJ y)aD  
        Continuing from the non-parametrized example when the lhs is a parameter,
        instead of multiplying with known values, the matrix is split up into four slices,
        each representing an element of the parameter, i.e. instead of
         x11 x21 x12 x22
        [[1   2   0   0],
         [3   4   0   0],
         [0   0   1   2],
         [0   0   3   4]]

         we obtain the list of length four, where we have ones at the entries where previously
         we had the 1, 3, 2, and 4 (again flattened in column-major order):

            x11  x21  x12  x22
        [
            [[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]],

            [[0   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]]
        ]
        r   r\   r   r]   r6   r&  r   r'  r   r^   r   rP   r   rn   Nr3   r  r   r   r   r   r  r  r  r4   )r   rK   rL   rM   rN   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   r   r,  r!   )r@   r(  rg   rh   ri   lhs_parameterr   rk   r1  r2  r3  r4  r5  slice_idx_twoexpected_idx_twoslice_idx_threeexpected_idx_threes                    r   test_parametrized_mulz.TestParametrizedBackends.test_parametrized_mul   s   J &f:AF+,m#)*]",-)#$ //A]A]A_` //15fjj&**-EFfU]]_vvfq	)***#FqA m?:KL
 $$Z655a; "11!4<<>q#2#vFHH!#79MOcd
 vvn(99::: !003;;=a"fE88!#79MOcd
 vvm'77888 !003;;=a"fE88!#79MOcd
 vvm'77888 #2215==?3B3GXX!#79MOcd
 vvo);;<<< 11!Q74;Y;YZ[]^;____r   c           	        t        ddd      }ddd|_        ddd	|_        d|_        t        dd
d      }|j	                  ||j                               }t        |      }|j                  ||      }t        ddt        j                  ddgddgg            }t        ||g      }|j                  ||      }	|	j                  dd      }
|
j                  d      j                         ddddf   }t        j                  g dg dg dg dg      }t        j                  ||k(        sJ |
j                  d      j                         ddddf   }t        j                  g dg dg dg dg      }t        j                  ||k(        sJ |
j                  d      j                         ddddf   }t        j                  g dg dg dg dg      }t        j                  ||k(        sJ |
j                  d      j                         ddddf   }t        j                  g dg dg dg dg      }t        j                  ||k(        sJ |	j                  dd      |j                  dd      k(  sJ y)a  
        Continuing from the non-parametrized example when the expression
        that is multiplied by is parametrized. For a variable that
        was multiplied elementwise by a parameter, instead of
         x11 x21 x12 x22
        [[1   2   0   0],
         [3   4   0   0],
         [0   0   1   2],
         [0   0   3   4]]

         we obtain the list of length four, where we have the same entries as before
         but each variable maps to a different parameter slice:

            x11  x21  x12  x22
        [
            [[1   0   0   0],
             [3   0   0   0],
             [0   0   0   0],
             [0   0   0   0]],

            [[0   2   0   0],
             [0   4   0   0],
             [0   0   0   0],
             [0   0   0   0]],

            [[0   0   0   0],
             [0   0   0   0],
             [0   0   1   0],
             [0   0   3   0]],

            [[0   0   0   0],
             [0   0   0   0],
             [0   0   0   2],
             [0   0   0   4]]
        ]
        r   rP   r   r]   r   r6   r'  r   r&  r\   r   r   r4   rn   Nr3   r  )r   r   r   r   r<  r  )r         @r   r   r  r   r   r   r   r  r   r   r   rD  )r   rL   rK   rN   r`   r_   r   r    r!   r   ra   r,  r(   r#   )r@   r(  r-  rg   r.  r/  r0  r   r   rk   r1  r2  r3  r4  r5  r>  r?  r@  rA  s                      r   test_parametrized_rhs_mulz2TestParametrizedBackends.test_parametrized_rhs_mulV  s{   J #6a@)*]"+,m##$ %f:AF 33O]EaEaEcd%<8&//J&}288aVaQRVDT;UV c0AB
 $$Z@55a;!11!4<<>q#2#vFHH!#79MOcd
 vvn(99::: 003;;=a"fE88!#79MOcd
 vvm'77888 003;;=a"fE88!#79MOcd
 vvm'77888"2215==?3B3GXX!#79MOcd
 vvo);;<<< 11!Q7>;c;cq<
 
 	
 
r   c                   t        ddd      }d|_        |j                  ||j                               }|j	                  dd      }t        j                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        d	d
d      }t        ||g      }|j                  ||      }|j	                  dd      }|j                  d      j                         ddddf   }	t        j                   g dg dg      }
t        j                  |	|
k(        sJ |j                  d      j                         ddddf   }t        j                   g dg dg      }t        j                  ||k(        sJ |j	                  dd      |j	                  dd      k(  sJ y)ac  
        Continuing from the non-parametrized example when the rhs is a parameter,
        instead of multiplying with known values, the matrix is split up into two slices,
        each representing an element of the parameter, i.e. instead of
         x11 x21 x12 x22
        [[1   0   2   0],
         [0   1   0   2]]

         we obtain the list of length two, where we have ones at the entries where previously
         we had the 1 and 2:

         x11  x21  x12  x22
        [
         [[1   0   0   0],
          [0   1   0   0]]

         [[0   0   1   0],
          [0   0   0   1]]
        ]
        r   r\   r   r]   r6   r   r^   r   r   rP   r   rn   Nr3   ro   rq   rp   rr   )r   rN   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   r   r,  r!   )r@   r(  rg   rh   ri   rhs_parameterr   rk   r1  r2  r3  r4  r5  s                r   test_parametrized_rmulz/TestParametrizedBackends.test_parametrized_rmul  s   , &f:AF#$ //A]A]A_` //15fjj&**-EFfU]]_vvfq	)***#DwQ?!}O;LM %%k4855a; "11!4<<>q#2#vFHHlL%ABvvn(99::: !003;;=a"fE88\<$@Avvm'77888 11!Q74;Y;YZ[]^;____r   c           	        t        ddd      }ddd|_        ddd	|_        d|_        t        dd
d      }|j	                  ||j                               }t        |      }|j                  ||      }t        ddt        j                  ddgddgg            }t        ||g      }|j                  ||      }	|	j                  dd      }
|
j                  d      j                         ddddf   }t        j                  g dg dg dg dg      }t        j                  ||k(        sJ |
j                  d      j                         ddddf   }t        j                  g dg dg dg dg      }t        j                  ||k(        sJ |
j                  d      j                         ddddf   }t        j                  g dg dg dg dg      }t        j                  ||k(        sJ |
j                  d      j                         ddddf   }t        j                  g dg dg dg dg      }t        j                  ||k(        sJ |	j                  dd      |j                  dd      k(  sJ y)a  
        Continuing from the non-parametrized example when the expression
        that is multiplied by is parametrized. For a variable that
        was multiplied elementwise by a parameter, instead of

         x11 x21 x12 x22
        [[1   0   3   0],
         [0   1   0   3],
         [2   0   4   0],
         [0   2   0   4]]

         we obtain the list of length four, where we have the same entries as before
         but each variable maps to a different parameter slice:

         x11  x21  x12  x22
        [
         [[1   0   0   0],
          [0   0   0   0],
          [2   0   0   0],
          [0   0   0   0]]

         [[0   0   0   0],
          [0   1   0   0],
          [0   0   0   0],
          [0   2   0   0]]

         [[0   0   3   0],
          [0   0   0   0],
          [0   0   4   0],
          [0   0   0   0]]

         [[0   0   0   0],
          [0   0   0   3],
          [0   0   0   0],
          [0   0   0   4]]
        ]
        r   rP   r   r]   r   r6   r'  r   r&  r\   r   r   r4   rn   Nr3   r  r<  r  r  r  rE  )r   r   rD  r   )r   r   r   r   rF  )r   rL   rK   rN   r`   r_   r   r    r!   r   ra   r,  r(   r#   )r@   r(  r-  rg   r.  r/  r0  r   r   rk   r1  r2  r3  r4  r5  r>  r?  r@  rA  s                      r   test_parametrized_rhs_rmulz3TestParametrizedBackends.test_parametrized_rhs_rmul  s{   L #6a@)*]"+,m##$ %f:AF 33O]EaEaEcd%<8&//J&}288aVaQRVDT;UV!s/1BC %%k>B55a;!11!4<<>q#2#vFHH!#79MOcd
 vvn(99::: 003;;=a"fE88!#79MOcd
 vvm'77888 003;;=a"fE88!#79MOcd
 vvm'77888"2215==?3B3GXX!#79MOcd
 vvo);;<<< 11!Q7>;c;cq<
 
 	
 
r   c                   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        dd	d      }t        |
      }|j                  ||      }|j                  dd      }|j                  d      j                         ddddf   }	t        j                  ddgddgg      }
t        j                  |	|
k(        sJ |j                  d      j                         ddddf   }t        j                  ddgddgg      }t        j                  ||k(        sJ |j                  dd      |j                  dd      k(  sJ y)a  
        Continuing the non-parametrized example when 'a' is a parameter, instead of multiplying
        with known values, the matrix is split up into two slices, each representing an element
        of the parameter, i.e. instead of
         x1  x2
        [[2  0],
         [0  3]]

         we obtain the list of length two:

          x1  x2
        [
         [[1  0],
          [0  0]],

         [[0  0],
          [0  1]]
        ]
        r   r\   r   r]   r   r   r   r   rP   r   Nr3   )r   r`   r_   ra   rb   rc   r   r$   r%   r(   r    r#   rd   r   r,  r!   )r@   r(  rg   rh   ri   r=  r   rk   r1  r2  r3  r4  r5  s                r   !test_mul_elementwise_parametrizedz:TestParametrizedBackends.test_mul_elementwise_parametrized+  s   * &d!D//A]A]A_` //15fjj&**-EFfU]]_vvfq	)***#DwQ?!,-!@ ))*@$G55a; "11!4<<>q#2#vFHHq!fq!f%56vvn(99::: !003;;=a"fE88aVaV$45vvm'77888 11!Q74;Y;YZ[]^;____r   c           	        t        ddd      }ddd|_        ddd	|_        d|_        t        dd
d      }|j	                  ||j                               }t        |      }|j                  ||      }t        ddt        j                  ddgddgg            }t        |      }|j                  ||      }	|	j                  dd      }
|
j                  d      j                         ddddf   }t        j                  g dg dg dg dg      }t        j                  ||k(        sJ |
j                  d      j                         ddddf   }t        j                  g dg dg dg dg      }t        j                  ||k(        sJ |
j                  d      j                         ddddf   }t        j                  g dg dg dg dg      }t        j                  ||k(        sJ |
j                  d      j                         ddddf   }t        j                  g dg dg dg dg      }t        j                  ||k(        sJ |	j                  dd      |j                  dd      k(  sJ y)a  
        Continuing from the non-parametrized example when the expression
        that is divided by is parametrized. For a variable that
        was multiplied elementwise by a parameter, instead of
         x11 x21 x12 x22
        [[1   0   0   0],
         [0   1/3 0   0],
         [0   0   1/2 0],
         [0   0   0   1/4]]

         we obtain the list of length four, where we have the quotients at the same entries
         but each variable maps to a different parameter slice:

            x11  x21  x12  x22
        [
            [[1   0   0   0],
             [0   0   0   0],
             [0   0   0   0],
             [0   0   0   0]],

            [[0   0   0   0],
             [0   1/3 0   0],
             [0   0   0   0],
             [0   0   0   0]],

            [[0   0   0   0],
             [0   0   0   0],
             [0   0   1/2 0],
             [0   0   0   0]],

            [[0   0   0   0],
             [0   0   0   0],
             [0   0   0   0],
             [0   0   0   1/4]]
        ]
        r   rP   r   r]   r   r6   r'  r   r&  r\   r   r   r4   Nr3   r  r<  )r   r   r   r   )r   r   r   r   )r   r   r   r   )r   rL   rK   rN   r`   r_   r   r    r!   r   ra   r,  r(   r#   )r@   r(  r-  rg   r.  r/  r0  r   r   rk   r1  r2  r3  r4  r5  r>  r?  r@  rA  s                      r   test_parametrized_divz.TestParametrizedBackends.test_parametrized_div[  sz   J #6a@)*]"+,m##$ %f:AF 33O]EaEaEcd%<8&//J&}288aVaQRVDT;UV c*
 $$Z@55a;!11!4<<>q#2#vFHH!#79MOcd
 vvn(99::: 003;;=a"fE88$&$$	
 vvm'77888 003;;=a"fE88$$&$	
 vvm'77888"2215==?3B3GXX$$$&	
 vvo);;<<<11!Q7>;c;cq<
 
 	
 
r   c                n   t        ddd      }ddd|_        ddd	|_        d|_        t        dd
d      }|j	                  ||j                               }t        |      }|j                  ||      }t        |g      }|j                  ||      }|j                  dd      }	|	j                  d      j                         ddddf   }
t        j                  g dg      }t        j                  |
|k(        sJ |	j                  d      j                         ddddf   }t        j                  g dg      }t        j                  ||k(        sJ |	j                  d      j                         ddddf   }t        j                  g dg      }t        j                  ||k(        sJ |	j                  d      j                         ddddf   }t        j                  g dg      }t        j                  ||k(        sJ |j                  dd      |j                  dd      k(  sJ y)a  
        Continuing from the non-parametrized example, instead of a pure variable
        input, we take a variable that has been multiplied elementwise by a parameter.

        The trace of this expression is then given by

            x11  x21  x12  x22
        [
            [[1   0   0   0]],

            [[0   0   0   0]],

            [[0   0   0   0]],

            [[0   0   0   1]]
        ]
        r   rP   r   r]   r   r6   r'  r   r&  r\   r   rx   Nr3   r  r<  r4   r  )r   rL   rK   rN   r`   r_   r   r   ra   r,  r(   r    r!   r#   )r@   r(  r-  rg   r.  r/  r0  r   rk   r1  r2  r3  r4  r5  r>  r?  r@  rA  s                     r   test_parametrized_tracez0TestParametrizedBackends.test_parametrized_trace  s   $ #6a@)*]"+,m##$ %f:AF 33O]EaEaEcd%<8&//J"(9: &&|^D55a;!11!4<<>q#2#vFHH&:%;<vvn(99::: 003;;=a"fE88%9$:;vvm'77888 003;;=a"fE88%9$:;vvm'77888"2215==?3B3GXX';&<=vvo);;<<< 11!Q7>;c;cq<
 
 	
 
r   N)r   r   r   r  r=   r  r  r(  r6  r8  r:  rB  rG  rJ  rL  rN  rP  rR  r   r   r   r#  r#  A  sj    V^^8$ % 1
fO
b)
VT`lO
b0`dP
d.``]
~2
r   r#  c            	          e Zd Ze ej
                  e      d               Zd Zej                  j                  ddg dg dgfdg d	g d
gfdg dg dgfg      d        Zd Zd Zy)TestND_BackendsrE   c                    dddddddddddd}t        j                  | j                  fi |}t        |t              sJ |S rH   rO   rQ   s      r   rA   zTestND_Backends.backend  rT   r   c                (   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        dd	d
g|g      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  g dg dg dg dg      }t        j                  ||k(        sJ |j                  dd      |j                  dd      k(  sJ y)a  
        define x = Variable((2,2,2)) with
        [[[x111, x112],
        [x121, x122]],

        [[x211, x212],
        [x221, x222]]]

        x is represented as eye(8) in the A matrix (in column-major order), i.e.,

        x111 x211 x121 x221 x112 x212 x122 x222
        [[1   0   0   0   0   0   0   0],
         [0   1   0   0   0   0   0   0],
         [0   0   1   0   0   0   0   0],
         [0   0   0   1   0   0   0   0],
         [0   0   0   0   1   0   0   0],
         [0   0   0   0   0   1   0   0],
         [0   0   0   0   0   0   1   0],
         [0   0   0   0   0   0   0   1]]

        sum(x, axis = 0) means we only consider entries in a given axis (axes)

        which, when using the same columns as before, now maps to

        sum(x, axis = 0)
        x111 x211 x121 x221 x112 x212 x122 x222
        [[1   1   0   0   0   0   0   0],
         [0   0   1   1   0   0   0   0],
         [0   0   0   0   1   1   0   0],
         [0   0   0   0   0   0   1   1]]

        sum(x, axis = 1)
        x111 x211 x121 x221 x112 x212 x122 x222
        [[1   0   1   0   0   0   0   0],
         [0   1   0   1   0   0   0   0],
         [0   0   0   0   1   0   1   0],
         [0   0   0   0   0   1   0   1]]

        sum(x, axis = 2)
        x111 x211 x121 x221 x112 x212 x122 x222
        [[1   0   0   0   1   0   0   0],
         [0   1   0   0   0   1   0   0],
         [0   0   1   0   0   0   1   0],
         [0   0   0   1   0   0   0   1]]

        To reproduce the outputs above, eliminate the given axis
        and put ones where the remaining axes (axis) match.

        Note: sum(x, keepdims=True) is equivalent to sum(x, keepdims=False)
        with a reshape, which is NO-OP in the backend.
        r   r\   r   r]   r   r   r   r   r   r   Tr   r6   r6   r   )r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   Nr   )	r@   rA   rg   rh   ri   
sum_lin_oprk   r)   ru   s	            r   test_nd_sum_entriesz#TestND_Backends.test_nd_sum_entries  s\   j &ijqI))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)*** y4yGXY
&&z48..q!4 MM166AEE155>2&AIIK8855557 8 vva8m$$$ 11!Q74;Y;YZ[]^;____r   zaxes, expected)r   r   )r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   c                   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        d|d	g|g
      }|j                  ||      }|j                  dd      }	t	        j
                  |	j                  |	j                  |	j                  ffd      j                         }	t        j                  |	t        j                  |      k(        sJ |j                  dd      |j                  dd      k(  sJ y)a  
        define x = Variable((2,2,2)) with
        [[[x111, x112],
        [x121, x122]],

        [[x211, x212],
        [x221, x222]]]

        x is represented as eye(8) in the A matrix (in column-major order), i.e.,

        x111 x211 x121 x221 x112 x212 x122 x222
        [[1   0   0   0   0   0   0   0],
         [0   1   0   0   0   0   0   0],
         [0   0   1   0   0   0   0   0],
         [0   0   0   1   0   0   0   0],
         [0   0   0   0   1   0   0   0],
         [0   0   0   0   0   1   0   0],
         [0   0   0   0   0   0   1   0],
         [0   0   0   0   0   0   0   1]]

        sum(x, axis = (0,1))
        x111 x211 x121 x221 x112 x212 x122 x222
        [[1   1   1   1   0   0   0   0],
         [0   0   0   0   1   1   1   1]]

        sum(x, axis = (0,2))
        x111 x211 x121 x221 x112 x212 x122 x222
        [[1   1   0   0   1   1   0   0],
         [0   0   1   1   0   0   1   1]]

        sum(x, axis = (1,2))
        x111 x211 x121 x221 x112 x212 x122 x222
        [[1   0   1   0   1   0   1   0],
         [0   1   0   1   0   1   0   1]]

        To reproduce the outputs above, eliminate the given axes
        and put ones where the remaining axes match.
        r   r\   r   r]   r   r   rW  r   Tr   r6   )r   r   Nr   )
r@   rA   axesru   rg   rh   ri   rY  rk   r)   s
             r   !test_nd_sum_entries_multiple_axesz1TestND_Backends.test_nd_sum_entries_multiple_axesN  sE   b &ijqI))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)*** yd|?J[\
&&z48..q!4 MM166AEE155>2&AIIKvva288H--... 11!Q74;Y;YZ[]^;____r   c           	        t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        t        dd	d      t        ddd      t        dd	d      g|g
      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  g dg dg dg dg      }t        j                  ||k(        sJ t        t        dd	d      g|g
      }	|j                  |	|      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  g dg      }t        j                  ||k(        sJ |j                  dd      |j                  dd      k(  sJ y)a  
        define x = Variable((2,2,2)) with
        [[[x111, x112],
        [x121, x122]],

        [[x211, x212],
        [x221, x222]]]

        x is represented as eye(8) in the A matrix (in column-major order), i.e.,

        x111 x211 x121 x221 x112 x212 x122 x222
        [[1   0   0   0   0   0   0   0],
         [0   1   0   0   0   0   0   0],
         [0   0   1   0   0   0   0   0],
         [0   0   0   1   0   0   0   0],
         [0   0   0   0   1   0   0   0],
         [0   0   0   0   0   1   0   0],
         [0   0   0   0   0   0   1   0],
         [0   0   0   0   0   0   0   1]]

        index() returns the subset of rows corresponding to the slicing of variables.

        e.g. x[0:2, 0, 0:2] yields
        x111 x211 x121 x221 x112 x212 x122 x222
        [[1   0   0   0   0   0   0   0],
         [0   1   0   0   0   0   0   0],
         [0   0   0   0   1   0   0   0],
         [0   0   0   0   0   1   0   0]]

         -> It reduces to selecting a subset of the rows of A.
        r   r\   r   r]   r   r   rW  r   r   rn   r6   rX  )r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   )r   r   Nr   r   s
             r   test_nd_indexzTestND_Backends.test_nd_index  s   B &ijqI))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***%E!QNE!QNERSUVXYN+[,;+<>==$7..q!4 MM166AEE155>2&AIIK8855557 8 vva8m$$$%E!QN+;?BST==$7..q!4 MM166AEE155>2&AIIK88567vva8m$$$ 11!Q74;Y;YZ[]^;____r   c                T   t        ddd      }|j                  ||j                               }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  |t        j                  d      k(        sJ t        d	d	|g
      }|j                  ||      }|j                  dd      }t	        j
                  |j                  |j                  |j                  ffd      j                         }t        j                  g dg dg dg dg dg dg dg dg dg dg dg dg      }t        j                  ||k(        sJ |j                  dd      |j                  dd      k(  sJ y)a  
        define x = Variable((2,1,2)) with
        [[x11, x12], 
         [x21, x22]]

        x is represented as eye(4) in the A matrix, i.e.,
         x11 x21 x12 x22
        [[1   0   0   0],
         [0   1   0   0],
         [0   0   1   0],
         [0   0   0   1]]
        
        broadcast_to(x, (2, 3, 2)) means we repeat columns of x three times each subsequently.

        Thus we expect the following A matrix:
        
        x11 x21 x12 x22
        [[1   0   0   0],
         [0   1   0   0],
         [1   0   0   0],
         [0   1   0   0],
         [1   0   0   0],
         [0   1   0   0],

         [0   0   1   0],
         [0   0   0   1],
         [0   0   1   0],
         [0   0   0   1],
         [0   0   1   0],
         [0   0   0   1]]
        )r   r   r   r\   r   r]   r   r6   r^   r   )r   r4   r   rn   r   )r   r6   ro   rq   rp   rr   Nr   r   s	            r   test_nd_broadcast_toz$TestND_Backends.test_nd_broadcast_to  sq   @ &gJQG))/7;Q;Q;ST //15fjj&**-EFfU]]_vvfq	)***&wWOCTU''(8$?..q"5 MM166AEE155>2'BJJL88\)))))))))))+ , vva8m$$$ 11!Q74;Y;YZ[]^;____r   N)r   r   r   r  r=   r  r  rA   rZ  r  r  r^  r`  rb  r   r   r   rT  rT    s    V^^8$ %  J`X [[-1I0H1J1K 271I0H1J1K 271I0H1J1K0L M9`M9`v@`D=`r   rT  c                  N    e Zd Ze ej
                  e      d               Zd Zy)TestParametrizedND_BackendsrE   c                    ddiddddddddd}t        j                  | j                  fi |}t        |t              sJ |S )Nr   r   r   r&  r'  r   rI   rO   rQ   s      r   r(  z)TestParametrizedND_Backends.param_backend	  r)  r   c                   t        ddd      }t        ddd      }|j                  ||j                               }t        |      }|j                  ||      }t        ddd	g|g
      }|j	                  ||      }|j                  dd      }	|	j                  d      j                         ddddf   }
t        j                  g dg dg      }t        j                  |
|k(        sJ |	j                  d      j                         ddddf   }t        j                  g dg dg      }t        j                  ||k(        sJ |	j                  d      j                         ddddf   }t        j                  g dg dg      }t        j                  ||k(        sJ |j                  dd      |j                  dd      k(  sJ y)a   
        starting with a (2,2,2) parametrized expression
        x111 x211 x121 x221 x112 x212 x122 x222
        slice(0)
        [[1   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]]
        slice(1)
        [[0   0   0   0   0   0   0   0],
         [0   1   0   0   0   0   0   0],
         ...
         [0   0   0   0   0   0   0   0],
         [0   0   0   0   0   0   0   0]]
        ...
        slice(7)
        [[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   1]]

        sum(x, axis = (0,2)) means we only consider entries in a given axis (axes)

        Thus, when using the same columns as before, we now perform the sum operation
        over each slice individually:

        x111 x211 x121 x221 x112 x212 x122 x222
        slice(0)
        [[1   0   0   0   0   0   0   0],
         [0   0   0   0   0   0   0   0]]
        slice(2)
        [[0   1   0   0   0   0   0   0],
         [0   0   0   0   0   0   0   0]]
        slice(7)
        [[0   0   0   0   0   0   0   0],
         [0   0   0   0   0   0   0   1]]
        r   rP   r   r]   r\   r   r   r[  Tr   r   Nr3   )r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   r6   )r   r`   r_   r   r   ra   r,  r(   r    r!   r#   )r@   r(  r-  rg   r.  r/  r0  r   rk   r1  r2  r3  r4  r5  slice_idx_sevenexpected_idx_sevens                   r    test_parametrized_nd_sum_entriesz<TestParametrizedND_Backends.test_parametrized_nd_sum_entries$	  s   P #7qA%gJQG 33O]EaEaEcd%<8&//J(weT]RaQbc ,,-?P55a;!11!4<<>q#2#vFHH&F$D&F Gvvn(99::: 003;;=a"fE88%E$D%F Gvvm'77888"2215==?3B3GXX'G$D'F Gvvo);;<<< 11!Q7>;c;cq<
 
 	
 
r   N)	r   r   r   r  r=   r  r  r(  ri  r   r   r   rd  rd  	  s-    V^^8$ % D
r   rd  c                      e Zd Ze ej
                         d               Zd Zej                  j                  d e
j                  ddgddgg       ej                  d      dz  g      d        Zd	 Zd
 Zy)TestNumPyBackendc                     ddiddddddddd} t        j                  t        j                  fi | }t	        |t
              sJ |S r%  )r   r8   r9   r<   r;   r   rS   rA   s     r   numpy_backendzTestNumPyBackend.numpy_backendl	  Y     Q"#] !qM#$
 **1+@+@KFK'#4555r   c                   |j                  dd      }|j                         dhk(  sJ d       |d   }|j                         dhk(  sJ d       |d   }t        |t        j                        sJ d       |j
                  dk(  sJ d       t        j                  |d	   t        j                  d
      k(        sJ d       y )Nr   r   $Should only be in variable with ID 1r3   <Should only be in parameter slice -1, i.e. non parametrized.Should be a numpy array)r   r   r   zShould be a 1x2x2 tensorr   r   Should be eye(2))get_variable_tensorkeysr;   r    ndarrayr   r#   rd   )r@   rn  outerinnertensors        r   test_get_variable_tensorz)TestNumPyBackend.test_get_variable_tensorz	  s    11$:zz|s"J$JJ"azz|t#c%cc#r&"**-H/HH-||y(D*DD(vvfQi266!9,-A/AA-r   r   r   r   r4   r6   c                   |j                  |      }|j                         dhk(  sJ d       |d   }|j                         dhk(  sJ d       |d   }t        |t        j                        sJ d       t        |d   t        j                        sJ d       |j
                  dk(  sJ d       |j                  |      j                  d	d
      }t        j                  |d   |k(        sJ y )Nr3   $Should only be constant variable ID.rr  rs  r   z)Inner matrix should also be a numpy array)r   r6   r   zShould be a 1x4x1 tensorr3   r   Forder)	get_data_tensorrv  r;   r    rw  r   	_to_densereshaper#   )r@   rn  r   rx  ry  rz  ru   s          r   test_get_data_tensorz%TestNumPyBackend.test_get_data_tensor	  s    --d3zz|t#K%KK#b	zz|t#c%cc#r&"**-H/HH-&)RZZ0]2]]0||y(D*DD( **40888LvvfQi8+,,,r   c                   d}t        j                  |      }|j                  |d      }|j                         dhk(  sJ d       |d   }|j                         dhk(  sJ d       |d   }t	        |t         j
                        sJ d       |j                  dk(  sJ d       t        j                  |d d d d d	f   t        j                  |      k(        sJ d
       y )Nr   r4   r3   r}  :Should only be the parameter slice of parameter with id 3.rs  )r6   r6   r   zShould be a 4x4x1 tensorr   z#Should be eye(4) along axes 1 and 2)	r    prodget_param_tensorrv  r;   rw  r   r#   rd   )r@   rn  r   sizerx  ry  rz  s          r   test_get_param_tensorz&TestNumPyBackend.test_get_param_tensor	  s    wwu~..ua8zz|t#K%KK#b	zz|s"`$``"q&"**-H/HH-||y(D*DD(vvfQ1Wo56]8]]6r   c                   |j                         }t        j                  dg      }t        j                  dg      }t        j                  dg      }|j                  i i       i k(  sJ |j                  d|id|i      d|ik(  sJ |j                  d|id|i      ||dk(  sJ |j                  dd|iidd|ii      dd|iik(  sJ t	        j
                  t        d	      5  |j                  ddiddi       d d d        y # 1 sw Y   y xY w)
Nr   r   r4   r
  r  r
  r  cz6Values must either be dicts or <class 'numpy.ndarray'>match)r_   r    r!   r  r=   r>   
ValueError)r@   rn  rh   onetwothrees         r   test_tensor_view_add_dictsz+TestNumPyBackend.test_tensor_view_add_dicts	  s   ++-hhsmhhsm!~~b"%+++~~sCj3*5#uEEE~~sCj3*5s9MMMM~~sS#J/#Sz1BCcSVZGXXXX]]V
 	/ NNC8c1X.	/ 	/ 	/s   #DDN)r   r   r   r  r=   r  rn  r{  r  r  r    r!   rb   	eye_arrayr  r  r  r   r   r   rk  rk  k	  s    V^^
  
B [[VhbhhAA/?&@,",,q/TUBU%VW
- X
-
^/r   rk  c                     e Zd Ze ej
                         d               Zd Zej                  j                  d e
j                  ddgddgg       ej                  d      dz  g      d        Zd	 Zd
 Zeej                  j                  dg d      d               Zeej                  j                  dg d      d               Zed        Zeej                  j                  dg d      d               Zy)TestSciPyBackendc                     ddiddddddddd} t        j                  t        j                  fi | }t	        |t
              sJ |S r%  )r   r8   r9   r:   r;   r	   rm  s     r   scipy_backendzTestSciPyBackend.scipy_backend	  ro  r   c                p   |j                  dd      }|j                         dhk(  sJ d       |d   }|j                         dhk(  sJ d       |d   }t        j                  |      sJ d       |j                  dk(  sJ d       t        j                  |t        j                  d	      k(        sJ d
       y )Nr   r   rq  r3   rr  z(Should be a scipy sparse matrix or arrayr   zShould be a 1*2x2 tensorr   rt  )ru  rv  rb   issparser   r    r#   rd   )r@   r  rx  ry  rz  s        r   r{  z)TestSciPyBackend.test_get_variable_tensor	  s    11$:zz|s"J$JJ"azz|t#c%cc#r{{6"N$NN"||v%A'AA%vvfq	)*>,>>*r   r   r   r   r4   r6   c                ~   |j                  |      }|j                         dhk(  sJ d       |d   }|j                         dhk(  sJ d       |d   }t        j                  |      sJ d       |j                  dk(  sJ d       t        j
                  |j                  dd	            }||k7  j                  d
k(  sJ y )Nr3   r}  rr  Should be scipy sparse)r6   r   zShould be a 1*4x1 tensorr~  r  r  r   )r  rv  rb   r  r   	csr_arrayr  nnz)r@   r  r   rx  ry  rz  ru   s          r   r  z%TestSciPyBackend.test_get_data_tensor	  s    --d3zz|t#K%KK#b	zz|t#c%cc#r{{6"<$<<"||v%A'AA%<<WC @A("''1,,,r   c                   d}t        j                  |      }ddd|_        |j                  |d      }|j	                         dhk(  sJ d       |d   }|j	                         dhk(  sJ d       |d   }t        j                  |      sJ d	       |j                  d
k(  sJ d       |j                  ||f      t        j                  |d      k7  j                  dk(  sJ d       y )Nr   r   r6   r2   r4   r3   r}  r  r  )r   r   zShould be a 4*4x1 tensorcsr)formatr   zShould be eye(4) when reshaping)r    r  rK   r  rv  rb   r  r   r  r  r  )r@   r  r   r  rx  ry  rz  s          r   r  z&TestSciPyBackend.test_get_param_tensor	  s    wwu~+,m#..ua8zz|t#K%KK#b	zz|s"`$``"q{{6"<$<<"||w&B(BB&NND$<(BLLe,LL
# 	65	6 r   c                $   |j                         }t        j                  d      }t        j                  d      dz  }t        j                  d      dz  }|j                  i i       i k(  sJ |j                  d|id|i      d|ik(  sJ |j                  d|id|i      ||dk(  sJ |j                  dd|iidd|ii      dd|iik(  sJ t	        j
                  t        d	      5  |j                  ddiddi       d d d        y # 1 sw Y   y xY w)
Nr   r   r4   r
  r  r  r  z6Values must either be dicts or \(<class 'scipy.sparse.r  )r_   rb   r  r  r=   r>   r  )r@   r  rh   r  r  r  s         r   r  z+TestSciPyBackend.test_tensor_view_add_dicts	  s   ++-ll1oll1o!Q!#~~b"%+++~~sCj3*5#uEEE~~sCj3*5s9MMMM~~sS#J/#Sz1BCcSVZGXXXX]]W
 	/ NNC8c1X.	/ 	/ 	/s   &DDr   )r   r   r   r^   c           
        d}d}d}t        |      D cg c]  }t        j                  | |d       }}t        j                  |      }|j	                  ||i|      }||   }t        j                  |D 	cg c]+  }	t        j
                  t        j                  |      |	      - c}	      }
|
|k7  j                  dk(  sJ y c c}w c c}	w Nr   r4   r   random_statedensityr   )r!  rb   random_arrayr   _stacked_kron_rkronr  r  r   r  prepsparam_idimatricesstackedrepeatedmru   s              r   test_stacked_kron_rz$TestSciPyBackend.test_stacked_kron_r	  s     QVWXQYZABOOE3GZZ))H% 00(G1DdKH%99hObggbll4&8!<OPH$))Q... [ P   C60Cc                   d}d}d}t        |      D cg c]  }t        j                  | |d       }}t        j                  |      }|j	                  ||i|      }||   }t        j                  |D 	cg c]+  }	t        j
                  |	t        j                  |            - c}	      }
|
|k7  j                  dk(  sJ y c c}w c c}	w r  )r!  rb   r  r   _stacked_kron_lr  r  r  r  s              r   test_stacked_kron_lz$TestSciPyBackend.test_stacked_kron_l	  s     QVWXQYZABOOE3GZZ))H% 00(G1DdKH%99hObggad);<OPH$))Q... [ Pr  c                   t        j                  t        j                  t        j                  d      d      j                  d            }| j                  |d      }t        j                  d      j                  dd      }t        j                  t        j                  |d            }||k7  j                  dk(  sJ y )	Nr   r4   r~  r  r  r  r   r   )rb   	csc_arrayr    tiler   r  _reshape_single_constant_tensorr  )r  r
  reshapedru   s       r   #test_reshape_single_constant_tensorz4TestSciPyBackend.test_reshape_single_constant_tensor
  s    LL1q199'BC @@FK99Q<''c':<<& 9:H$))Q...r   )r   r   r  r   c                L   d}d}t        |      D cg c]  }t        j                  | |d       }}t        j                  |      }|j	                  ||      }t        j                  |D cg c]  }|j
                   c}      }	|	|k7  j                  dk(  sJ y c c}w c c}w )Nr   r   r  r   )r!  rb   r  r   _transpose_stackedTr  )
r   r  r  r  r  r  r  
transposedr  ru   s
             r   test_transpose_stackedz'TestSciPyBackend.test_transpose_stacked
  s     QVWXQYZABOOE3GZZ))H%"55gxH
9984aacc45J&++q000	 [ 5s   B-B!N)r   r   r   r  r=   r  r  r{  r  r  r    r!   rb   r  r  r  r  r  r  r  r  r   r   r   r  r  	  s(   V^^
  
? [[VhbhhAA/?&@,",,q/TUBU%VW	- X	-6/  [[W&FG	/ H 	/ [[W&FG	/ H 	/ / / [[W&FG1 H 1r   r  )!
__future__r   dataclassesr   typingr   numpyr    r=   scipy.sparsesparserb   cvxpy.settingssettingsr9   cvxpy.lin_ops.canon_backendr   r   r   r	   r
   r   r-   r/   r:   r<   r  rD   r#  rT  rd  rk  r  r   r   r   <module>r     s    " !       	* 	* 	*W"4 4 !!1#8#89{K {K|'k

 k

\b` b`J	T
 T
n@/ @/Fo1 o1r   