
    Ed.                     x   d Z ddlmZ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lmZ ddlmZ g dZ ed	          Z ed
ddgief          Zer!erej        Zej        j        Zej        j        Z G d d          Zd Zi fdZddZ G d de          Z G d de          Z  G d de          Z!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!
    )ListDict)Mul)import_module)GateOneQubitGateCGateCGateS)	BasicMeta)ManagedProperties)CircuitPlotcircuit_plotlabellerMzMxCreateOneQubitGateCreateCGatenumpy
matplotlibfromlistpyplot)import_kwargscatchc                       e Zd ZdZdZdZdZdZdZdZ	g Z
i 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d ZdS )r   z$A class for managing a circuit plot.g      ?g      4@g?g333333?      ?c                    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#   kwargss       Alib/python3.11/site-packages/sympy/physics/quantum/circuitplot.py__init__zCircuitPlot.__init__>   s     	D 	DBCCC$,+,,F    c                 :    | j                             |           dS )z'Load the kwargs into the instance dict.N)__dict__r$   )r*   r,   s     r-   r$   zCircuitPlot.updateK   s    V$$$$$r/   c                     | j         }t                              d| j        |z  |t                    }t                              d| j        |z  |t                    }|| _        || _        dS )zCreate the grid of wires.g        )dtypeN)scaler   aranger#   floatr"   
_wire_grid
_gate_grid)r*   r4   	wire_grid	gate_grids       r-   r%   zCircuitPlot._create_gridO   s[    
IIc4<#5uEIJJ	IIc4;u#4e5III	##r/   c                    t                               | j        | j        z  | j        | j        z  fdd          | _        | j                            dddd          }|                                 d| j        z  }|                    | j	        d         |z
  | j	        d         |z              |
                    | j        d         |z
  | j        d         |z              |                    d	           || _        d
S )z"Create the main matplotlib figure.w)figsize	facecolor	edgecolor   T)frameonr   r   equalN)r   figurer"   r4   r#   _figureadd_subplotset_axis_offset_xlimr8   set_ylimr7   
set_aspect_axes)r*   axoffsets      r-   r&   zCircuitPlot._create_figureW   s    }}[+T\$*-DE % 
 

 \%%q! & 
 
 	TZ
DOA&/1Dv1MNNN
DOA&/1Dv1MNNN
g


r/   c           
      f   | j         d         }| j         d         }|| j        z
  || j        z   f}t          | j                  D ]}| j        |         | j        |         f}t          ||d| j                  }| j                            |           | j	        rd}| j
                            | j	        |                   rd}| j                            |d         | j        z
  |z
  |d         t          | j	        |         | j
                  | j        ddd           |                                  dS )	z&Plot the wires of the circuit diagram.r   rB   kcolorlwg      ?center)sizerQ   havaN)r8   r4   ranger#   r7   Line2D	linewidthrK   add_linelabelsinitsgettextlabel_bufferrender_labelfontsize_plot_measured_wires)r*   xstartxstopxdataiydatalineinit_label_buffers           r-   r'   zCircuitPlot._plot_wiresi   s?   ##$*$edj&89t|$$ 	7 	7A_Q');<Eu>  D
 J%%%{ 7$%!:>>$+a.11Kt3D
!HT../@@q Q
;;X	   7 7 7
 	!!#####r/   c                    |                                  }| j        d         }d}|D ]q}| j        ||                  || j        z   f}| j        |         |z   | j        |         |z   f}t	          ||d| j                  }| j                            |           rt          | 	                                          D ]\  }}	t          |	t          t          f          r|	j        |	j        z   }
|
D ]}||v r| j        |         | j        ||                  k    rpt          |
          t!          |
          f}| j        |         |z
  | j        |         |z
  f}t	          ||d| j                  }| j                            |           d S )NrB   g{Gz?rO   rP   )_measurementsr8   r4   r7   rX   rY   rK   rZ   	enumerate_gates
isinstancer	   r
   controlstargetsminmax)r*   
ismeasuredrd   dyimre   rg   rh   rf   gwireswires               r-   rb   z CircuitPlot._plot_measured_wires   s   ''))
# 	& 	&B_Z^4U4:5EFE_R(+DOB,?,BCEu>  D
 J%%%%T[[]]++ 	2 	2CAa!eV_-- 2
QY.! 
2 
2Dz) 	2?1-
4@P0QQ	2 #E

CJJ 6 $ 22 5tq7I"7L L%!5"%#~     
 
++D111	2 	2r/   c                 4   g }t          | j        t                    rGt          | j        j                  D ],}t          |t
                    r|                    |           -n4t          | j        t
                    r|                    | j                   |S )z/Create a list of all gates in the circuit plot.)rn   r   r   reversedr!   r   append)r*   gatesrv   s      r-   rm   zCircuitPlot._gates   s    dlC(( 	'dl/00 $ $a&& $LLOOO$ d++ 	'LL&&&r/   c                     t          |                                           D ]\  }}|                    | |           dS )z0Iterate through the gates and plot each of them.N)rl   rm   	plot_gate)r*   rf   gates      r-   r(   zCircuitPlot._plot_gates   sF     // 	$ 	$GAtNN4####	$ 	$r/   c                     i }t          |                                           D ];\  }}t          |dd          r%|j        D ]}||v r||         |k    r|||<   |||<   <|S )zReturn 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)rl   rm   getattrrp   )r*   rs   rf   rv   targets        r-   rk   zCircuitPlot._measurements   s     
T[[]]++ 	/ 	/CAaqu-- /i / /F+ /%f-1 312Jv.-.
6**r/   c                 h    | j                                         D ]}|                    d           d S )NF)rE   findobjset_clip_on)r*   os     r-   r)   zCircuitPlot._finish   s>    %%'' 	! 	!AMM%    	! 	!r/   c                     | j         |         }| j        |         }| j                            |||dddt	          ddd| j                  | j                   dS )z#Draw a box for a single qubit gate.rO   rS   r<   TecfcfillrR   )rQ   rU   rV   bboxrT   N)r8   r7   rK   r^   dictrY   ra   )r*   tgate_idxwire_idxxys         r-   one_qubit_boxzCircuitPlot.one_qubit_box   sl    OH%OH%
q!4DNCCC 	 	
 	
 	
 	
 	
r/   c                 V    t          | j                   t          | j                   dS )z<Draw a box for a two qubit gate. Does not work yet.
        N)printr8   r7   )r*   r   r   r   s       r-   two_qubit_boxzCircuitPlot.two_qubit_box   s*    
 	dodor/   c                     | j         |         | j         |         f}| j        |         | j        |         f}t          ||d| j                  }| j                            |           dS )zDraw a vertical control line.rO   rP   N)r8   r7   rX   rY   rK   rZ   )r*   r   min_wiremax_wirere   rg   rh   s          r-   control_linezCircuitPlot.control_line   sq    *DOH,EF*DOH,EF5~
 
 

 	
D!!!!!r/   c                     | j         |         }| j        |         }| j        }t          ||f|| j        z  ddd| j                  }| j                            |           dS )zDraw a control point.rO   Tr   N)r8   r7   control_radiusCircler4   rY   rK   	add_patch)r*   r   r   r   r   radiusr+   s          r-   control_pointzCircuitPlot.control_point   ss    OH%OH%$F4:~
 
 
 	
Qr/   c                 ,   | j         |         }| j        |         }| j        }t          ||f|ddd| j                  }| j                            |           t          ||f||z
  ||z   fd| j                  }| j                            |           dS )z7Draw a NOT gates as the circle with plus in the middle.rO   r<   Fr   rP   N)	r8   r7   
not_radiusr   rY   rK   r   rX   rZ   )r*   r   r   r   r   r   r+   ls           r-   	not_pointzCircuitPlot.not_point   s    OH%OH%F~
 
 
 	
QFQZV,~
 
 

 	
Ar/   c                 P   | j         |         }| j        |         }| j        }t          ||z
  ||z   f||z
  ||z   fd| j                  }t          ||z
  ||z   f||z   ||z
  fd| j                  }| j                            |           | j                            |           dS )zDraw a swap point as a cross.rO   rP   N)r8   r7   
swap_deltarX   rY   rK   rZ   )r*   r   r   r   r   dl1l2s           r-   
swap_pointzCircuitPlot.swap_point  s    OH%OH%OUAENUAEN~	
 
 
 UAENUAEN~	
 
 
 	
B
Br/   N)__name__
__module____qualname____doc__r4   ra   rY   r   r   r   r[   r\   r_   r.   r$   r%   r&   r'   rb   rm   r(   rk   r)   r   r   r   r   r   r    r/   r-   r   r   1   s7       ..EHINJJFEL  % % %$ $ $  $$ $ $.2 2 2:	 	 	$ $ $
  ! ! !

 
 
  "	" 	" 	"       *         r/   r   c                     t          | |fi |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,   s      r-   r   r   "  s     q',,V,,,r/   c                 L    |                     |           }|r	d| d|dS d| z  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|z\right\rangle=\left|z\right\rangle$z$\left|%s\right\rangle$)r]   )labelr\   inits      r-   r`   r`   0  sB     99UD P PCH55$$$OO%--r/   qc                 >      f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                 *    g | ]}d |z
  dz
  fz  S )z%s_%dr@   r   ).0rf   nsymbols     r-   
<listcomp>zlabeller.<locals>.<listcomp>O  s*    777Gvac!en$777r/   )rW   )r   r   s   ``r-   r   r   >  s)    " 87777eAhh7777r/   c                       e Zd ZdZdZd ZdZdS )r   zMock-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.
    TM_zNr   r   r   r   r   	gate_namegate_name_latexr   r/   r-   r   r   Q  )         
 KIOOOr/   r   c                       e Zd ZdZdZd ZdZdS )r   zMock-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.
    TM_xNr   r   r/   r-   r   r   [  r   r/   r   c                       e Zd ZddZdS )r   Nc                 P    |s|}t          j        | |dz   t          f||d          S )Nr   )r   r   )r   __new__r   )mclname	latexnames      r-   r   zCreateOneQubitGate.__new__f  s>     	I dVml_/3	!R!RT T 	Tr/   N)r   r   r   r   r   r/   r-   r   r   e  s.        T T T T T Tr/   r   Nc                 :    |s| }t          | |          fd}|S )z5Use a lexical closure to make a controlled gate.
    c                 P    t          t          |            |                    S r   )r	   tuple)ctrlsr   onequbitgates     r-   ControlledGatez#CreateCGate.<locals>.ControlledGater  s#    U5\\,,v"6"6777r/   )r   )r   r   r   r   s      @r-   r   r   l  s@      	%dI66L8 8 8 8 8r/   )r   r   )#r   typingr   r   tDictsympy.core.mulr   sympy.externalr   sympy.physics.quantum.gater   r   r	   r
   sympy.core.corer   sympy.core.assumptionsr   __all__r   RuntimeErrorr   r   linesrX   patchesr   r   r   r`   r   r   r   r   r   r   r/   r-   <module>r      s     ' & & & & & & &       ( ( ( ( ( ( H H H H H H H H H H H H % % % % % % 4 4 4 4 4 4   ]7]hZ 8/  
  '* 'F$F&F
o  o  o  o  o  o  o  o b- - - ! . . . .8 8 8 8&              T T T T T* T T T     r/   