
    \h.                    |   S r SSKJr  SSKJr  SSKJr  SSKJrJ	r	J
r
Jr  / SQr\" S5      r\" SS	S
/0\4S9r\(       a?  \(       a8  \R                   r\R"                  R$                  r\R&                  R(                  r " S S5      rS r0 4S jrSS jr " S S\	5      r " S S\	5      r " S S\5      rSS jrg)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)import_kwargscatchc                      \ rS rSr% SrSrSrSrSrSr	Sr
/ rS\S'   0 rS	\S
'   SrS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rSrg)r
   /   z$A class for managing a circuit plot.g      ?g      4@g?g333333?z	list[str]labelszdict[str, str]inits      ?c                h   [         (       a  [        (       d  [        S5      eXl        [	        U R                  R
                  5      U l        X l        U R                  U5        U R                  5         U R                  5         U R                  5         U R                  5         U R                  5         g )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       Y/var/www/auris/envauris/lib/python3.13/site-packages/sympy/physics/quantum/circuitplot.py__init__CircuitPlot.__init__<   s|    rBCC$,,++,F    c                :    U R                   R                  U5        g)z'Load the kwargs into the instance dict.N)__dict__r$   )r*   r,   s     r-   r$   CircuitPlot.updateI   s    V$r0   c                    U R                   n[        R                  SU R                  U-  U[        S9n[        R                  SU R
                  U-  U[        S9nX l        X0l        g)zCreate the grid of wires.g        )dtypeN)scaler   aranger#   floatr"   
_wire_grid
_gate_grid)r*   r6   	wire_grid	gate_grids       r-   r%   CircuitPlot._create_gridM   sS    

IIc4<<#5uEIJ	IIc4;;u#4e5II	##r0   c                   [         R                  U R                  U R                  -  U R                  U R                  -  4SSS9U l        U R
                  R                  SSSSS9nUR                  5         SU R                  -  nUR                  U R                  S   U-
  U R                  S   U-   5        UR                  U R                  S   U-
  U R                  S   U-   5        UR                  S	5        Xl        g
)z"Create the main matplotlib figure.w)figsize	facecolor	edgecolor   T)frameonr   r   equalN)r   figurer"   r6   r#   _figureadd_subplotset_axis_offset_xlimr:   set_ylimr9   
set_aspect_axes)r*   axoffsets      r-   r&   CircuitPlot._create_figureU   s    }}[[+T\\$**-DE % 

 \\%%q! & 
 	TZZ
DOOA&/1Dv1MN
DOOA&/1Dv1MN
g
r0   c                   U R                   S   nU R                   S   nXR                  -
  X R                  -   4n[        U R                  5       H  nU R                  U   U R                  U   4n[        X5SU R                  S9nU R                  R                  U5        U R                  (       d  Md  SnU R                  R                  U R                  U   5      (       a  SnU R                  R                  US   U R                  -
  U-
  US   [        U R                  U   U R                  5      U R                  SSSS9  M     U R!                  5         g)	z&Plot the wires of the circuit diagram.r   rE   kcolorlwg      ?center)sizerU   havaN)r:   r6   ranger#   r9   Line2D	linewidthrN   add_liner   r   gettextlabel_bufferrender_labelfontsize_plot_measured_wires)r*   xstartxstopxdataiydatalineinit_label_buffers           r-   r'   CircuitPlot._plot_wiresg   s$   ##**$ejj&89t||$A__Q');<E>>D
 JJ%{{{$%!::>>$++a.11t3D

!HT.../@@q Q

;X	   7 %  	!!#r0   c           	     *   U R                  5       nU R                  S   nSnU Hv  nU R                  X      X R                  -   4nU R                  U   U-   U R                  U   U-   4n[	        XVSU R
                  S9nU R                  R                  U5        Mx     [        U R                  5       5       H  u  p[        U	[        [        45      (       d  M"  U	R                  U	R                  -   n
U
 H  nX;   d  M
  U R                  U   U R                  X      :  d  M.  [        U
5      [!        U
5      4nU R                  U   U-
  U R                  U   U-
  4n[	        XVSU R
                  S9nU R                  R                  U5        M     M     g )NrE   g{Gz?rS   rT   )_measurementsr:   r6   r9   r\   r]   rN   r^   	enumerate_gates
isinstancer   r	   controlstargetsminmax)r*   
ismeasuredrf   dyimrg   ri   rj   rh   gwireswires               r-   rd    CircuitPlot._plot_measured_wires~   sf   '')
#B__Z^4U::5EFE__R(+DOOB,?,BCE>>D
 JJ%  T[[]+CA!eV_--

QYY.!D)??1-
@P0QQ #E
CJ 6 $ 22 5tq7I"7L L%!"%#~~ 
 

++D1 " ,r0   c                \   / n[        U R                  [        5      (       aP  [        U R                  R                  5       H+  n[        U[
        5      (       d  M  UR                  U5        M-     U$ [        U R                  [
        5      (       a  UR                  U R                  5        U$ )z/Create a list of all gates in the circuit plot.)rq   r   r   reversedr!   r   append)r*   gatesry   s      r-   rp   CircuitPlot._gates   sx    dllC((dll//0a&&LLO 1
  d++LL&r0   c                j    [        U R                  5       5       H  u  pUR                  X5        M     g)z0Iterate through the gates and plot each of them.N)ro   rp   	plot_gate)r*   rh   gates      r-   r(   CircuitPlot._plot_gates   s%     /GANN4# 0r0   c                    0 n[        U R                  5       5       HE  u  p#[        USS5      (       d  M  UR                   H  nXA;   a  X   U:  a  X!U'   M  M  X!U'   M     MG     U$ )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)ro   rp   getattrrs   )r*   rv   rh   ry   targets        r-   rn   CircuitPlot._measurements   sm     
T[[]+CAqu--iiF+%-112v. 2 ./6* ( , r0   c                h    U R                   R                  5        H  nUR                  S5        M     g )NF)rH   findobjset_clip_on)r*   os     r-   r)   CircuitPlot._finish   s%    %%'AMM%  (r0   c                    U R                   U   nU R                  U   nU R                  R                  XEUSSSSSSU R                  S.U R
                  S9  g)z#Draw a box for a single qubit gate.rS   rW   r?   TecfcfillrV   )rU   rY   rZ   bboxrX   N)r:   r9   rN   r`   r]   rc   )r*   tgate_idxwire_idxxys         r-   one_qubit_boxCircuitPlot.one_qubit_box   sX    OOH%OOH%

!3DNNK 	 	
r0   c                X    [        U R                  5        [        U R                  5        g)z<Draw a box for a two qubit gate. Does not work yet.
        N)printr:   r9   )r*   r   r   r   s       r-   two_qubit_boxCircuitPlot.two_qubit_box   s    
 	doodoor0   c                    U R                   U   U R                   U   4nU R                  U   U R                  U   4n[        XESU R                  S9nU R                  R                  U5        g)zDraw a vertical control line.rS   rT   N)r:   r9   r\   r]   rN   r^   )r*   r   min_wiremax_wirerg   ri   rj   s          r-   control_lineCircuitPlot.control_line   se    *DOOH,EF*DOOH,EF~~

 	

D!r0   c           	         U R                   U   nU R                  U   nU R                  n[        X44XPR                  -  SSSU R
                  S9nU R                  R                  U5        g)zDraw a control point.rS   Tr   N)r:   r9   control_radiusCircler6   r]   rN   	add_patch)r*   r   r   r   r   radiusr+   s          r-   control_pointCircuitPlot.control_point   sf    OOH%OOH%$$F::~~
 	

Qr0   c           	     0   U R                   U   nU R                  U   nU R                  n[        X44USSSU R                  S9nU R
                  R                  U5        [        X34XE-
  XE-   4SU R                  S9nU R
                  R                  U5        g)z7Draw a NOT gates as the circle with plus in the middle.rS   r?   Fr   rT   N)	r:   r9   
not_radiusr   r]   rN   r   r\   r^   )r*   r   r   r   r   r   r+   ls           r-   	not_pointCircuitPlot.not_point   s    OOH%OOH%F~~
 	

QFQZ,~~

 	

Ar0   c                L   U R                   U   nU R                  U   nU R                  n[        X5-
  X5-   4XE-
  XE-   4SU R                  S9n[        X5-
  X5-   4XE-   XE-
  4SU R                  S9nU R
                  R                  U5        U R
                  R                  U5        g)zDraw a swap point as a cross.rS   rT   N)r:   r9   
swap_deltar\   r]   rN   r^   )r*   r   r   r   r   dl1l2s           r-   
swap_pointCircuitPlot.swap_point  s    OOH%OOH%OOUAENUAEN~~	
 UAENUAEN~~	
 	

B

Br0   )rN   rH   r:   r9   r   r"   r#   N) __name__
__module____qualname____firstlineno____doc__r6   rc   r]   r   r   r   r   __annotations__r   ra   r.   r$   r%   r&   r'   rd   rp   r(   rn   r)   r   r   r   r   r   r   __static_attributes__ r0   r-   r
   r
   /   s    .EHINJJFIE>L%$$$.2:	$
!

"	" * r0   r
   c                    [        X40 UD6$ )a%  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,,r0   c                R    UR                  U 5      nU(       a  SU < SU< S3$ SU -  $ )zSlightly 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-   rb   rb   .  s+     99UDCH$OO%--r0   c                X    [        U 5       Vs/ s H  nSXU-
  S-
  4-  PM     sn$ s  snf )aX  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']
z%s_%drC   )r[   )nsymbolrh   s      r-   r   r   <  s/    " /4Ah7hGvc!en$h777s   'c                  $    \ rS rSrSrSrS rSrSrg)r   iO  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.
TM_zr   N	r   r   r   r   r   r   	gate_namegate_name_latexr   r   r0   r-   r   r   O      
 KIOr0   r   c                  $    \ rS rSrSrSrS rSrSrg)r   iY  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.
TM_xr   Nr   r   r0   r-   r   r   Y  r   r0   r   c                      \ rS rSrSS jrSrg)r   ic  Nc                B    U(       d  Un[        US-   [        4XS.5      $ )Nr   )r   r   )typer   )mclname	latexnames      r-   __new__CreateOneQubitGate.__new__d  s'    ID6ML?=? 	?r0   r   N)r   r   r   r   r   r   r   r0   r-   r   r   c  s    ?r0   r   Nc                <   ^ U(       d  U n[        X5      mU4S jnU$ )z5Use a lexical closure to make a controlled gate.
    c                :   > [        [        U 5      T" U5      5      $ r   )r   tuple)ctrlsr   onequbitgates     r-   ControlledGate#CreateCGate.<locals>.ControlledGatep  s    U5\,v"677r0   )r   )r   r   r   r   s      @r-   r   r   j  s"     	%d6L8r0   )qr   )r   
__future__r   sympy.core.mulr   sympy.externalr   sympy.physics.quantum.gater   r   r   r	   __all__r   RuntimeErrorr   r   linesr\   patchesr   r
   r   rb   r   r   r   r   r   r   r   r0   r-   <module>r      s     #  ( H H 7hZ 8/
 *F$$F&&F
o  o b- ! .8&  ? ?r0   