o
    jg                     @   s   d Z ddlZddlZddlmZ ddlmZ ddlmZ ddl	m
Z
 ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZmZ ddlmZ ddlmZ ddlmZ G dd deZG dd deZdd Zdd Z dd Z!dd Z"dS )zShor's algorithm and helper functions.

Todo:

* Get the CMod gate working again using the new Gate API.
* Fix everything.
* Update docstrings and reformat.
    N)Mul)S)log)sqrt)igcd)continued_fraction_periodic)
variations)Gate)Qubitmeasure_partial_oneshot)qapply)QFT)QuantumErrorc                   @   s   e Zd ZdS )OrderFindingExceptionN)__name__
__module____qualname__ r   r   R/var/www/html/zoom/venv/lib/python3.10/site-packages/sympy/physics/quantum/shor.pyr      s    r   c                   @   sH   e Zd ZdZedd Zedd Zedd Zedd	 Z	d
d Z
dS )CModzA controlled mod gate.

    This is black box controlled Mod function for use by shor's algorithm.
    TODO: implement a decompose property that returns how to do this in terms
    of elementary gates
    c                 C   s   t d)Nz%The CMod gate has not been completed.)NotImplementedError)clsargsr   r   r   
_eval_args(   s   zCMod._eval_argsc                 C   
   | j d S )z4Size of 1/2 input register.  First 1/2 holds output.r   labelselfr   r   r   t/      
zCMod.tc                 C   r   )z$Base of the controlled mod function.   r   r   r   r   r   a4   r    zCMod.ac                 C   r   )z1N is the type of modular arithmetic we are doing.   r   r   r   r   r   N9   r    zCMod.Nc                 K   s   d}d}t | jD ]}|||| j|   7 }|d9 }q	t| j| | j }t|jd d| j }tt | jD ]}|||? d@  q8t	| S )z
            This directly calculates the controlled mod of the second half of
            the register and puts it in the second
            This will look pretty when we get Tensor Symbolically working
        r!   r   r#   N)
ranger   intr"   r$   listr   reversedappendr
   )r   qubitsoptionsnkioutoutarrayr   r   r   _apply_operator_Qubit>   s   
zCMod._apply_operator_QubitN)r   r   r   __doc__classmethodr   propertyr   r"   r$   r1   r   r   r   r   r       s    



r   c                 C   sx   t | d d }t| |dkrt| |S t|| }|d dkr$t|  t||d  d | t||d  d | f}|S )a  This function implements Shor's factoring algorithm on the Integer N

    The algorithm starts by picking a random number (a) and seeing if it is
    coprime with N. If it is not, then the gcd of the two numbers is a factor
    and we are done. Otherwise, it begins the period_finding subroutine which
    finds the period of a in modulo N arithmetic. This period, if even, can
    be used to calculate factors by taking a**(r/2)-1 and a**(r/2)+1.
    These values are returned.
    r#   r!   )random	randranger   period_findshor)r$   r"   ranswerr   r   r   r8   X   s   


,r8   c                 C   s   t | |}t||}|S )N)continued_fractionratioize)xyr$   fractiontotalr   r   r   getrl   s   

rA   c                 C   s@   | d |kr	t jS t| dkr| d S | d t| dd  | S )Nr   r!   )r   Zerolenr<   )r'   r$   r   r   r   r<   s   s
   r<   c                 C   s  d}t dtt|d }dd t|D }dtd|  }d}ttd|ddD ]}t|| }|t|  }q*|| 	 }	t
|| ||	 }	t|	}	t|D ]}
t|	|
}	qOtt||d  |	 dd	}	t|D ]	}
t|	|
| }	qjt|	tr||	}nt|	tr|	jd
 }n|	jd
 jd
 }d}d}tt|d D ]}
||||
|   7 }|d> }q|dkrtd| t|d| |}|S )a0  Finds the period of a in modulo N arithmetic

    This is quantum part of Shor's algorithm. It takes two registers,
    puts first in superposition of states with Hadamards so: ``|k>|0>``
    with k being all possible choices. It then does a controlled mod and
    a QFT to determine the order of a.
    g      ?r#   c                 S   s   g | ]}d qS )r   r   ).0r=   r   r   r   
<listcomp>   s    zperiod_find.<locals>.<listcomp>r!   r   T)
repetition)floatingPointz/Order finder returned 0. Happens with chance %f)r&   mathceilr   r%   r   r   r'   r
   expandr   r   r   r   	decompose
isinstancer   r   rC   r   rA   )r"   r$   epsilonr   startfactorr*   arr	qbitArraycircuitr.   registerr,   r:   gr   r   r   r7   {   s@   


r7   )#r2   rI   r5   sympy.core.mulr   sympy.core.singletonr   &sympy.functions.elementary.exponentialr   (sympy.functions.elementary.miscellaneousr   sympy.core.intfuncr   sympy.ntheoryr   r;   sympy.utilities.iterablesr   sympy.physics.quantum.gater	   sympy.physics.quantum.qubitr
   r   sympy.physics.quantum.qapplyr   sympy.physics.quantum.qftr   sympy.physics.quantum.qexprr   r   r   r8   rA   r<   r7   r   r   r   r   <module>   s*    	8