Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
735 views
�
�F�V�+�@s�dZddlZddljZddljZddl	Z	ddl
Z
dd�Zdd�Zddd	d
�Z
ddddd�Zdd
dd�Zddd�Zddd�Zddd�ZdS)z!A package for computing Pfaffians�NcCs�|jddkst�tj|dd�|dd��}|dkrltj|jd�d|dfStj|dd|�}|j�}|ddkr�|d|8<|
}n|d|7<|}|tjj	|�}|d|fSdS)z�(v, tau, alpha) = householder_real(x)

    Compute a Householder transformation such that
    (1-tau v v^T) x = alpha e_1
    where x and v a real vectors, tau is 0 or 2, and
    alpha a real number (e_1 is the first unit vector)
    r�N�)
�shape�AssertionError�np�dot�zeros�math�sqrt�copy�linalg�norm)�x�sigma�norm_x�v�alpha�r�../code/pfaffian.py�householder_real	s	&!
rcCs
|jddkst�tjtj|dd��|dd��}|dkrutj|jd�d|dfStj|dj�|d|�}|j	�}tj
dtj|dj
|dj��}|d||7<|tjj|�}|d||fS)z�(v, tau, alpha) = householder_real(x)

    Compute a Householder transformation such that
    (1-tau v v^T) x = alpha e_1
    where x and v a complex vectors, tau is 0 or 2, and
    alpha a complex number (e_1 is the first unit vector)
    rrNy�?r)rrrr�conjr�cmathr
�	conjugater�expr	�atan2�imag�realrr
)rrrr�phaserrr�householder_complex*s/!%-rFTcCs�|jd|jdko%dkns0t�t||jj��dksUt�|jd}tj|�}tj|jtj	�r�t
}n-tj|jtj�s�td��nt
}|s�|j�}n|r�tj|jdd|j�}nx�t|jdd�D]y}|||dd�|f�\}}}	|	||d|f<|	|||df<d||dd�|f<d|||dd�f<|tj||dd�|dd�f|j��}
||dd�|dd�ftj||
�tj|
|�7<|r|tj|dd�|dd�f|�}|dd�|dd�ftj||j��8<qqW|r�tj|�tj|�fStj|�SdS)a T, Q = skew_tridiagonalize(A, overwrite_a, calc_q=True)

    or

    T = skew_tridiagonalize(A, overwrite_a, calc_q=False)

    Bring a real or complex skew-symmetric matrix (A=-A^T) into
    tridiagonal form T (with zero diagonal) with a orthogonal
    (real case) or unitary (complex case) matrix U such that
    A = Q T Q^T
    (Note that Q^T and *not* Q^dagger also in the complex case)

    A is overwritten if overwrite_a=True (default: False), and
    Q only calculated if calc_q=True (default: True)
    rrg�+����=z)pfaffian() can only work on numeric input�dtyperN)rr�abs�T�maxr�asarray�
issubdtyper�complexfloatingr�number�	TypeErrorrr�eye�rangerr�outer�asmatrix)�A�overwrite_a�calc_q�n�householder�Q�ir�taur�w�yrrr�skew_tridiagonalizeEs60%
	"):D0=r6c
Cs||jd|jdko%dkns0t�t||jj��dksUt�|jd}tj|�}|s�|j�}n|r�tj|d|j	�}n|r�tj
|�}nxt|d�D]�}|dtj||dd�|f�j�}||dkr�||d|d�fj�}	|||d�f||d|d�f<|	|||d�f<||d�|dfj�}	||d�|f||d�|df<|	||d�|f<|rP||dd|d�fj�}	||d|d�f||dd|d�f<|	||d|d�f<n|r�||d}	||||d<|	||<q�n||d|fdkr�||dd�|fj�}
|
||d|f}
d||dd�|f<d|||dd�f<||dd�|dd�ftj
|
||dd�|df�7<||dd�|dd�ftj
||dd�|df|
�8<|r�|
||dd�|df<q�q�q�W|rtjtj|�tj
|�|ff�}n|rR|r3tj|�tj|�|fStj|�tj|�fSn&|rktj|�|fStj|�SdS)a� T, L, P = skew_LTL(A, overwrite_a, calc_q=True)

    Bring a real or complex skew-symmetric matrix (A=-A^T) into
    tridiagonal form T (with zero diagonal) with a lower unit
    triangular matrix L such that
    P A P^T= L T L^T

    A is overwritten if overwrite_a=True (default: False),
    L and P only calculated if calc_L=True or calc_P=True,
    respectively (default: True).
    rrg�+����=rrNg)rrr r!r"rr#rr(r�aranger)�argmaxr*�sp�
csr_matrix�onesr+)r,r-Zcalc_LZcalc_Pr/�LZPv�k�kp�tempr3�Prrr�skew_LTL�sZ0%
1 * *$2 LL(0rAr@cCs�|jd|jdko%dkns0t�t||jj��dksntt||jj����|dks�|dks�t�|dkr�t||�St||�SdS)aQ pfaffian(A, overwrite_a=False, method='P')

    Compute the Pfaffian of a real or complex skew-symmetric
    matrix A (A=-A^T). If overwrite_a=True, the matrix A
    is overwritten in the process. This function uses
    either the Parlett-Reid algorithm (method='P', default),
    or the Householder tridiagonalization (method='H')
    rrg�+����=r@�HN)rrr r!r"�pfaffian_LTL�pfaffian_householder)r,r-�methodrrr�pfaffian�s
0>
rFc
Cs�|jd|jdko%dkns0t�t||jj��dksUt�|jd}tj|�}|ddkr�dS|s�|j�}nd}xHtd|dd�D]0}|dtj||dd�|f�j	�}||dkr�||d|d�fj�}|||d�f||d|d�f<||||d�f<||d�|dfj�}||d�|f||d�|df<|||d�|f<|d9}n||d|fdkr�|||dd�fj�}||||df}||||df9}|d|kr�||dd�|dd�ftj
|||dd�|df�7<||dd�|dd�ftj
||dd�|df|�8<q�q�dSq�W|S)	z� pfaffian_LTL(A, overwrite_a=False)

    Compute the Pfaffian of a real or complex skew-symmetric
    matrix A (A=-A^T). If overwrite_a=True, the matrix A
    is overwritten in the process. This function uses
    the Parlett-Reid algorithm.
    rrg�+����=rg�?Ng�����)rrr r!r"rr#rr)r8r*)r,r-r/�pfaffian_valr=r>r?r3rrrrC�s8	0%
1 * *
 LRrCc
Cso|jd|jdko%dkns0t�t||jj��dksUt�|jd}|ddkrvdStj|jtj�r�t	}n-tj|jtj
�s�td��nt}tj
|�}|s�|j�}nd}x^t|jdd�D]E}|||dd�|f�\}}}|||d|f<||||df<d||dd�|f<d|||dd�f<|tj||dd�|dd�f|j��}	||dd�|dd�ftj||	�tj|	|�7<|dkr-|d|9}n|ddkr||9}qqW|||d|df9}|S)a� pfaffian(A, overwrite_a=False)

    Compute the Pfaffian of a real or complex skew-symmetric
    matrix A (A=-A^T). If overwrite_a=True, the matrix A
    is overwritten in the process. This function uses the
    Householder tridiagonalization.

    Note that the function pfaffian_schur() can also be used in the
    real case. That function does not make use of the skew-symmetry
    and is only slightly slower than pfaffian_householder().
    rrg�+����=rz)pfaffian() can only work on numeric inputg�?N)rrr r!r"rr$rr%rr&r'rr#rr)rrr*)
r,r-r/r0rHr2rr3rr4rrrrD3s80%
	):DrDcCstj|jtj�r1tj|jtj�s7t�|jd|jdko\dknsgt�t||j�j	�dks�t�|jdddkr�dSt
j|ddd|�\}}tj|d�}tj
|ddd��t
j|�S)	a�Calculate Pfaffian of a real antisymmetric matrix using
    the Schur decomposition. (Hessenberg would in principle be faster,
    but scipy-0.8 messed up the performance for scipy.linalg.hessenberg()).

    This function does not make use of the skew-symmetry of the matrix A,
    but uses a LAPACK routine that is coded in FORTRAN and hence faster
    than python. As a consequence, pfaffian_schur is only slightly slower
    than pfaffian().
    rrg�+����=r�outputrr-N)rr$rr&r%rrr r!r"�la�schur�diag�prod�det)r,r-�t�z�lrrr�pfaffian_schuros70%!rR)�__doc__�numpyr�scipy.linalgrrJ�scipy.sparse�sparser9r	rrrr6rArFrCrDrRrrrr�<module>s!?Z@<