o
    8Va                     @   s   d Z ddlZddlZddlmZmZ ddlmZ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   </usr/lib/python3/dist-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   Zlabelselfr   r   r   t-      
zCMod.tc                 C   r   )z$Base of the controlled mod function.   r   r   r   r   r   a2   r   zCMod.ac                 C   r   )z1N is the type of modular arithmetic we are doing.   r   r   r   r   r   N7   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outZoutarrayr   r   r   _apply_operator_Qubit<   s   
zCMod._apply_operator_QubitN)r   r   r   __doc__classmethodr   propertyr   r!   r#   r/   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 isn't, 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    )randomZ	randranger   period_findshor)r#   r!   ranswerr   r   r   r5   V   s   


,r5   c                 C   s   t | |}t||}|S )N)continued_fractionratioize)xyr#   Zfractiontotalr   r   r   getrj   s   

r=   c                 C   s@   | d |kr	t jS t| dkr| d S | d t| dd  | S )Nr   r    )r   ZZerolenr9   )r&   r#   r   r   r   r9   q   s
   r9   c                 C   s|  d}t dtt|d }dd t|D }dtd|  }d}ttd|ddD ]}|| }|t|  }q*||  }	t	|| ||	 }	t
|	}	t|D ]}
t|	|
}	qMt
t||d  |	 dd	}	t|D ]	}
t|	|
| }	qht|	trz|	}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)Z
repetition)ZfloatingPointz/Order finder returned 0. Happens with chance %f)r%   mathZceilr   r$   r   r   r
   expandr   r   r   r   Z	decompose
isinstancer   r   r>   r   r=   )r!   r#   epsilonr   startZfactorr)   ZarrZ	qbitArrayZcircuitr-   registerr+   r7   gr   r   r   r4   y   s@   


r4   ) r0   rB   r3   Zsympyr   r   r   r   Zsympy.core.numbersr   Zsympy.ntheoryr   r8   Zsympy.utilities.iterablesr   Zsympy.physics.quantum.gater	   Zsympy.physics.quantum.qubitr
   r   Zsympy.physics.quantum.qapplyr   Zsympy.physics.quantum.qftr   Zsympy.physics.quantum.qexprr   r   r   r5   r=   r9   r4   r   r   r   r   <module>   s&    	8