U
    ZÊ¹j.  ã                   @  sø   d Z ddlmZ ddlmZ ddlmZ ddlmZm	Z	m
Z
mZ dddd	d
ddgZedƒZedddgiefd�ZerŽerŽejZejjZejjZG dd„ dƒZdd„ Zi fdd„Zddd„ZG dd	„ d	e	ƒZG dd
„ d
e	ƒZG dd„ deƒZddd„ZdS )aÉ  Matplotlib based plotting of quantum circuits.

Todo:

* Optimize printing of large circuits.
* Get this to work with single gates.
* Do a better job checking the form of circuits to make sure it is a Mul of
  Gates.
* Get multi-target gates plotting.
* Get initial and final states to plot.
* Get measurements to plot. Might need to rethink measurement as a gate
  issue.
* Get scale and figsize to be handled in a better way.
* Write some tests/examples!
é    )Úannotations)ÚMul)Úimport_module)ÚGateÚOneQubitGateÚCGateÚCGateSÚCircuitPlotÚcircuit_plotÚlabellerÚMzÚMxÚCreateOneQubitGateÚCreateCGateÚnumpyÚ
matplotlibÚfromlistÚpyplot)Zimport_kwargsZcatchc                   @  sÆ   e Zd ZU dZdZdZdZdZdZdZ	g Z
ded< i Zded	< d
Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd „ Zd!d"„ Zd#d$„ Zd%d&„ Zd'd(„ Zd)d*„ Zd+S ),r	   z$A class for managing a circuit plot.g      ð?g      4@gš™™™™™©?g333333Ã?z	list[str]Úlabelszdict[str, str]Úinitsç      à?c                 K  s`   t rtstdƒ‚|| _t| jjƒ| _|| _|  |¡ |  	¡  |  
¡  |  ¡  |  ¡  |  ¡  d S )Nz"numpy or matplotlib not available.)Únpr   ÚImportErrorÚcircuitÚlenÚargsÚngatesÚnqubitsÚupdateÚ_create_gridÚ_create_figureÚ_plot_wiresÚ_plot_gatesÚ_finish)ÚselfÚcr   Úkwargs© r'   ú`/var/www/html/bwave/python/venv/lib/python3.8/site-packages/sympy/physics/quantum/circuitplot.pyÚ__init__<   s    
zCircuitPlot.__init__c                 C  s   | j  |¡ dS )z'Load the kwargs into the instance dict.N)Ú__dict__r   )r$   r&   r'   r'   r(   r   I   s    zCircuitPlot.updatec                 C  sF   | j }tjd| j| |td�}tjd| j| |td�}|| _|| _dS )zCreate the grid of wires.g        )ZdtypeN)Úscaler   Zaranger   Úfloatr   Ú
_wire_gridÚ
_gate_grid)r$   r+   Z	wire_gridZ	gate_gridr'   r'   r(   r   M   s
    zCircuitPlot._create_gridc                 C  s    t j| j| j | j| j fddd�| _| jjddddd�}| ¡  d| j }| | j	d | | j	d | ¡ | 
| jd | | jd | ¡ | d	¡ || _d
S )z"Create the main matplotlib figure.Úw)ZfigsizeZ	facecolorZ	edgecoloré   T)Zframeonr   r   éÿÿÿÿÚequalN)r   Zfigurer   r+   r   Ú_figureZadd_subplotZset_axis_offZset_xlimr.   Zset_ylimr-   Z
set_aspectÚ_axes)r$   ZaxÚoffsetr'   r'   r(   r    U   s"    ý  þ
  
zCircuitPlot._create_figurec              
   C  sÒ   | j d }| j d }|| j || j f}t| jƒD ]’}| j| | j| f}t||d| jd�}| j |¡ | j	r2d}| j
 | j	| ¡rˆd}| jj|d | j | |d t| j	| | j
ƒ| jdddd� q2|  ¡  dS )	z&Plot the wires of the circuit diagram.r   r1   Úk©ÚcolorÚlwg      Ð?Úcenter)Úsizer8   ÚhaÚvaN)r.   r+   Úranger   r-   ÚLine2DÚ	linewidthr4   Úadd_liner   r   ÚgetÚtextÚlabel_bufferÚrender_labelÚfontsizeÚ_plot_measured_wires)r$   ZxstartÚxstopÚxdataÚiÚydataÚlineZinit_label_bufferr'   r'   r(   r!   g   s4    

 ý    üzCircuitPlot._plot_wiresc                 C  s  |   ¡ }| jd }d}|D ]V}| j||  || j f}| j| | | j| | f}t||d| jd�}| j |¡ qt|  	¡ ƒD ]–\}}	t
|	ttfƒr~|	j|	j }
|
D ]n}||kr¤| j| | j||  kr¤t|
ƒt|
ƒf}| j| | | j| | f}t||d| jd�}| j |¡ q¤q~d S )Nr1   g{®Gáz¤?r6   r7   )Ú_measurementsr.   r+   r-   r?   r@   r4   rA   Ú	enumerateÚ_gatesÚ
isinstancer   r   ZcontrolsÚtargetsÚminÚmax)r$   Ú
ismeasuredrH   ZdyZimrI   rK   rL   rJ   ÚgZwiresZwirer'   r'   r(   rG   ~   s:    
 ýÿ ýz CircuitPlot._plot_measured_wiresc                 C  sT   g }t | jtƒr8t| jjƒD ]}t |tƒr| |¡ qnt | jtƒrP| | j¡ |S )z/Create a list of all gates in the circuit plot.)rP   r   r   Úreversedr   r   Úappend)r$   ZgatesrU   r'   r'   r(   rO   ›   s    
zCircuitPlot._gatesc                 C  s&   t |  ¡ ƒD ]\}}| | |¡ qdS )z0Iterate through the gates and plot each of them.N)rN   rO   Z	plot_gate)r$   rJ   Zgater'   r'   r(   r"   ¦   s    zCircuitPlot._plot_gatesc                 C  s\   i }t |  ¡ ƒD ]F\}}t|ddƒr|jD ]*}||krL|| |krT|||< q*|||< q*q|S )z�Return a dict ``{i:j}`` where i is the index of the wire that has
        been measured, and j is the gate where the wire is measured.
        ÚmeasurementF)rN   rO   ÚgetattrrQ   )r$   rT   rJ   rU   Útargetr'   r'   r(   rM   «   s    

zCircuitPlot._measurementsc                 C  s   | j  ¡ D ]}| d¡ q
d S )NF)r3   ZfindobjZset_clip_on)r$   Úor'   r'   r(   r#   º   s    zCircuitPlot._finishc                 C  sB   | j | }| j| }| jj|||dddddd| jdœ| jd� dS )z#Draw a box for a single qubit gate.r6   r:   r/   T©ÚecÚfcÚfillr9   )r8   r<   r=   Zbboxr;   N)r.   r-   r4   rC   r@   rF   )r$   ÚtÚgate_idxÚwire_idxÚxÚyr'   r'   r(   Úone_qubit_box¿   s    

  úzCircuitPlot.one_qubit_boxc                 C  s   t | jƒ t | jƒ dS )z<Draw a box for a two qubit gate. Does not work yet.
        N)Úprintr.   r-   )r$   r`   ra   rb   r'   r'   r(   Útwo_qubit_boxÌ   s    
zCircuitPlot.two_qubit_boxc                 C  sJ   | j | | j | f}| j| | j| f}t||d| jd�}| j |¡ dS )zDraw a vertical control line.r6   r7   N)r.   r-   r?   r@   r4   rA   )r$   ra   Zmin_wireZmax_wirerI   rK   rL   r'   r'   r(   Úcontrol_lineÝ   s     ýzCircuitPlot.control_linec                 C  sJ   | j | }| j| }| j}t||f|| j ddd| jd�}| j |¡ dS )zDraw a control point.r6   Tr\   N)r.   r-   Úcontrol_radiusÚCircler+   r@   r4   Ú	add_patch)r$   ra   rb   rc   rd   Úradiusr%   r'   r'   r(   Úcontrol_pointè   s    

úzCircuitPlot.control_pointc                 C  sr   | j | }| j| }| j}t||f|ddd| jd�}| j |¡ t||f|| || fd| jd�}| j |¡ dS )z7Draw a NOT gates as the circle with plus in the middle.r6   r/   Fr\   r7   N)	r.   r-   Ú
not_radiusrj   r@   r4   rk   r?   rA   )r$   ra   rb   rc   rd   rl   r%   Úlr'   r'   r(   Ú	not_point÷   s&    

ú ýzCircuitPlot.not_pointc                 C  sŠ   | j | }| j| }| j}t|| || f|| || fd| jd�}t|| || f|| || fd| jd�}| j |¡ | j |¡ dS )zDraw a swap point as a cross.r6   r7   N)r.   r-   Ú
swap_deltar?   r@   r4   rA   )r$   ra   rb   rc   rd   ÚdÚl1Úl2r'   r'   r(   Ú
swap_point  s"    

üüzCircuitPlot.swap_pointN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r+   rF   r@   ri   rn   rq   r   Ú__annotations__r   rD   r)   r   r   r    r!   rG   rO   r"   rM   r#   re   rg   rh   rm   rp   ru   r'   r'   r'   r(   r	   /   s4   
c                 K  s   t | |f|ŽS )aE  Draw the circuit diagram for the circuit with nqubits.

    Parameters
    ==========

    c : circuit
        The circuit to plot. Should be a product of Gate instances.
    nqubits : int
        The number of qubits to include in the circuit. Must be at least
        as big as the largest ``min_qubits`` of the gates.
    )r	   )r%   r   r&   r'   r'   r(   r
      s    c                 C  s"   |  | ¡}|rd| |f S d|  S )a  Slightly more flexible way to render labels.

    >>> from sympy.physics.quantum.circuitplot import render_label
    >>> render_label('q0')
    '$\\left|q0\\right\\rangle$'
    >>> render_label('q0', {'q0':'0'})
    '$\\left|q0\\right\\rangle=\\left|0\\right\\rangle$'
    z-$\left|%s\right\rangle=\left|%s\right\rangle$z$\left|%s\right\rangle$)rB   )Úlabelr   Úinitr'   r'   r(   rE   .  s    	
rE   Úqc                   s   ‡ ‡fdd„t ˆ ƒD ƒS )aˆ  Autogenerate labels for wires of quantum circuits.

    Parameters
    ==========

    n : int
        number of qubits in the circuit.
    symbol : string
        A character string to precede all gate labels. E.g. 'q_0', 'q_1', etc.

    >>> from sympy.physics.quantum.circuitplot import labeller
    >>> labeller(2)
    ['q_1', 'q_0']
    >>> labeller(3,'j')
    ['j_2', 'j_1', 'j_0']
    c                   s    g | ]}d ˆˆ | d f ‘qS )z%s_%dr0   r'   )Ú.0rJ   ©ÚnÚsymbolr'   r(   Ú
<listcomp>M  s     zlabeller.<locals>.<listcomp>)r>   r   r'   r   r(   r   <  s    c                   @  s   e Zd ZdZdZd ZdZdS )r   zŠMock-up of a z measurement gate.

    This is in circuitplot rather than gate.py because it's not a real
    gate, it just draws one.
    TZM_zN©rv   rw   rx   ry   rX   Ú	gate_nameÚgate_name_latexr'   r'   r'   r(   r   O  s   c                   @  s   e Zd ZdZdZd ZdZdS )r   z‹Mock-up of an x measurement gate.

    This is in circuitplot rather than gate.py because it's not a real
    gate, it just draws one.
    TZM_xNrƒ   r'   r'   r'   r(   r   Y  s   c                   @  s   e Zd Zddd„ZdS )r   Nc                 C  s    |s|}t |d tf||dœƒS )Nr   )r„   r…   )Útyper   )ZmclÚnameÚ	latexnamer'   r'   r(   Ú__new__d  s
    ÿzCreateOneQubitGate.__new__)N)rv   rw   rx   r‰   r'   r'   r'   r(   r   c  s   Nc                   s"   |s| }t | |ƒ‰ ‡ fdd„}|S )z5Use a lexical closure to make a controlled gate.
    c                   s   t t| ƒˆ |ƒƒS )N)r   Útuple)ZctrlsrZ   ©Zonequbitgater'   r(   ÚControlledGatep  s    z#CreateCGate.<locals>.ControlledGate)r   )r‡   rˆ   rŒ   r'   r‹   r(   r   j  s
    
)r}   )N)ry   Ú
__future__r   Zsympy.core.mulr   Zsympy.externalr   Zsympy.physics.quantum.gater   r   r   r   Ú__all__r   ÚRuntimeErrorr   r   Úlinesr?   Zpatchesrj   r	   r
   rE   r   r   r   r†   r   r   r'   r'   r'   r(   Ú<module>   s>   ù
 þ r


