o
    *ήc.                     @   s
  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dZerPerPe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!
    )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                   @   s   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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?      ?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*   H/tmp/pip-target-vg8gfxp4/lib/python/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!   K   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        )dtypeN)scaler   aranger    floatr   
_wire_grid
_gate_grid)r'   r/   	wire_grid	gate_gridr*   r*   r+   r"   O   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)figsize	facecolor	edgecolor   T)frameonr   r   equalN)r   figurer   r/   r    _figureadd_subplotset_axis_offset_xlimr3   set_ylimr2   
set_aspect_axes)r'   axoffsetr*   r*   r+   r#   W   s   
  

zCircuitPlot._create_figurec              
   C   s   | j d }| j d }|| j || j f}t| jD ]I}| j| | j| f}t||d| jd}| j| | j	rbd}| j
| j	| rDd}| jj|d | j | |d t| j	| | j
| jdddd q|   dS )	z&Plot the wires of the circuit diagram.r   r<   kcolorlwg      ?center)sizerJ   havaN)r3   r/   ranger    r2   Line2D	linewidthrE   add_linelabelsinitsgettextlabel_bufferrender_labelfontsize_plot_measured_wires)r'   xstartxstopxdataiydatalineinit_label_bufferr*   r*   r+   r$   i   s,   

zCircuitPlot._plot_wiresc                 C   s  |   }| jd }d}|D ]+}| j||  || j f}| j| | | j| | f}t||d| jd}| j| qt| 	 D ]K\}}	t
|	ttfr|	j|	j }
|
D ]7}||v r| j| | j||  krt|
t|
f}| j| | | j| | f}t||d| jd}| j| qRq?d S )Nr<   g{Gz?rH   rI   )_measurementsr3   r/   r2   rQ   rR   rE   rS   	enumerate_gates
isinstancer   r	   controlstargetsminmax)r'   
ismeasuredr]   dyimr^   r`   ra   r_   gwireswirer*   r*   r+   r[      s:   
z CircuitPlot._plot_measured_wiresc                 C   sV   g }t | jtrt| jjD ]}t |tr|| q|S t | jtr)|| j |S )z/Create a list of all gates in the circuit plot.)rf   r   r   reversedr   r   append)r'   gatesrn   r*   r*   r+   re      s   

zCircuitPlot._gatesc                 C   s&   t |  D ]
\}}|| | qdS )z0Iterate through the gates and plot each of them.N)rd   re   	plot_gate)r'   r_   gater*   r*   r+   r%      s   zCircuitPlot._plot_gatesc                 C   s\   i }t |  D ]#\}}t|ddr+|jD ]}||v r&|| |kr%|||< q|||< qq|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)rd   re   getattrrh   )r'   rk   r_   rn   targetr*   r*   r+   rc      s   

zCircuitPlot._measurementsc                 C   s   | j  D ]}|d qd S )NF)r?   findobjset_clip_on)r'   or*   r*   r+   r&      s   zCircuitPlot._finishc                 C   sD   | j | }| j| }| jj|||dddtddd| jd| jd dS )z#Draw a box for a single qubit gate.rH   rL   r6   TecfcfillrK   )rJ   rN   rO   bboxrM   N)r3   r2   rE   rW   dictrR   rZ   )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)printr3   r2   )r'   r   r   r   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.rH   rI   N)r3   r2   rQ   rR   rE   rS   )r'   r   min_wiremax_wirer^   r`   ra   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.rH   Tr|   N)r3   r2   control_radiusCircler/   rR   rE   	add_patch)r'   r   r   r   r   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.rH   r6   Fr|   rI   N)	r3   r2   
not_radiusr   rR   rE   r   rQ   rS   )r'   r   r   r   r   r   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.rH   rI   N)r3   r2   
swap_deltarQ   rR   rE   rS   )r'   r   r   r   r   dl1l2r*   r*   r+   
swap_point  s"   

zCircuitPlot.swap_pointN)__name__
__module____qualname____doc__r/   rZ   rR   r   r   r   rT   rU   rX   r,   r!   r"   r#   r$   r[   re   r%   rc   r&   r   r   r   r   r   r   r*   r*   r*   r+   r   1   s6    r   c                 K   s   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)   r*   r*   r+   r   "  s   r   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$)rV   )labelrU   initr*   r*   r+   rY   0  s   
	rY   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_%dr:   r*   ).0r_   nsymbolr*   r+   
<listcomp>O  s     zlabeller.<locals>.<listcomp>)rP   r   r*   r   r+   r   >  s   r   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   rv   	gate_namegate_name_latexr*   r*   r*   r+   r   Q  
    r   c                   @   r   )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   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   )r
   __new__r   )mclname	latexnamer*   r*   r+   r   f  s
   zCreateOneQubitGate.__new__N)r   r   r   r   r*   r*   r*   r+   r   e  s    r   Nc                    s"   |s| }t | |  fdd}|S )z5Use a lexical closure to make a controlled gate.
    c                    s   t t|  |S r   )r   tuple)ctrlsrx   onequbitgater*   r+   ControlledGater  s   z#CreateCGate.<locals>.ControlledGate)r   )r   r   r   r*   r   r+   r   l  s
   
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   linesrQ   patchesr   r   r   rY   r   r   r   r   r   r*   r*   r*   r+   <module>   s4    

 r


