U
    ¹mœdo  ã                   @   sn   d Z ddlmZ ddlZdddddd	gZG d
d„ dƒZG dd„ dƒZG dd„ dƒZdd„ Z	dd„ Z
dd	„ ZdS )z<
Utility classes and functions for network flow algorithms.
é    )ÚdequeNÚCurrentEdgeÚLevelÚGlobalRelabelThresholdÚbuild_residual_networkÚdetect_unboundednessÚbuild_flow_dictc                   @   s4   e Zd ZdZdZdd„ Zdd„ Zdd„ Zd	d
„ ZdS )r   z’Mechanism for iterating over out-edges incident to a node in a circular
    manner. StopIteration exception is raised when wraparound occurs.
    )Ú_edgesÚ_itÚ_currc                 C   s   || _ | j r|  ¡  d S ©N)r	   Ú_rewind)ÚselfÚedges© r   úW/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/networkx/algorithms/flow/utils.pyÚ__init__   s    zCurrentEdge.__init__c                 C   s   | j S r   )r   ©r   r   r   r   Úget   s    zCurrentEdge.getc                 C   s4   zt | jƒ| _W n tk
r.   |  ¡  ‚ Y nX d S r   )Únextr
   r   ÚStopIterationr   r   r   r   r   Úmove_to_next"   s
    zCurrentEdge.move_to_nextc                 C   s    t | j ¡ ƒ| _t| jƒ| _d S r   )Úiterr	   Úitemsr
   r   r   r   r   r   r   r   )   s    zCurrentEdge._rewindN)	Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú	__slots__r   r   r   r   r   r   r   r   r      s   c                   @   s   e Zd ZdZdZdd„ ZdS )r   z%Active and inactive nodes in a level.)ÚactiveÚinactivec                 C   s   t ƒ | _t ƒ | _d S r   )Úsetr   r    r   r   r   r   r   3   s    zLevel.__init__N)r   r   r   r   r   r   r   r   r   r   r   .   s   c                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )r   zVMeasurement of work before the global relabeling heuristic should be
    applied.
    c                 C   s$   |r|| | nt dƒ| _d| _d S )NÚinfr   )ÚfloatÚ
_thresholdÚ_work)r   ÚnÚmÚfreqr   r   r   r   =   s    zGlobalRelabelThreshold.__init__c                 C   s   |  j |7  _ d S r   ©r%   )r   Zworkr   r   r   Úadd_workA   s    zGlobalRelabelThreshold.add_workc                 C   s   | j | jkS r   )r%   r$   r   r   r   r   Ú
is_reachedD   s    z!GlobalRelabelThreshold.is_reachedc                 C   s
   d| _ d S )Nr   r)   r   r   r   r   Ú
clear_workG   s    z!GlobalRelabelThreshold.clear_workN)r   r   r   r   r   r*   r+   r,   r   r   r   r   r   8   s
   c                    s"  |   ¡ rt d¡‚t ¡ }| | ¡ tdƒ‰‡ ‡fdd„| jdd�D ƒ}dt‡ ‡fdd	„|D ƒƒ pfd
‰|  ¡ rÒ|D ]Z\}}}t	| 
ˆ ˆ¡ˆƒ}| ||¡s¾|j|||d� |j||dd� qt||| | d< qtnB|D ]<\}}}t	| 
ˆ ˆ¡ˆƒ}|j|||d� |j|||d� qÖˆ|jd< |S )aù  Build a residual network and initialize a zero flow.

    The residual network :samp:`R` from an input graph :samp:`G` has the
    same nodes as :samp:`G`. :samp:`R` is a DiGraph that contains a pair
    of edges :samp:`(u, v)` and :samp:`(v, u)` iff :samp:`(u, v)` is not a
    self-loop, and at least one of :samp:`(u, v)` and :samp:`(v, u)` exists
    in :samp:`G`.

    For each edge :samp:`(u, v)` in :samp:`R`, :samp:`R[u][v]['capacity']`
    is equal to the capacity of :samp:`(u, v)` in :samp:`G` if it exists
    in :samp:`G` or zero otherwise. If the capacity is infinite,
    :samp:`R[u][v]['capacity']` will have a high arbitrary finite value
    that does not affect the solution of the problem. This value is stored in
    :samp:`R.graph['inf']`. For each edge :samp:`(u, v)` in :samp:`R`,
    :samp:`R[u][v]['flow']` represents the flow function of :samp:`(u, v)` and
    satisfies :samp:`R[u][v]['flow'] == -R[v][u]['flow']`.

    The flow value, defined as the total flow into :samp:`t`, the sink, is
    stored in :samp:`R.graph['flow_value']`. If :samp:`cutoff` is not
    specified, reachability to :samp:`t` using only edges :samp:`(u, v)` such
    that :samp:`R[u][v]['flow'] < R[u][v]['capacity']` induces a minimum
    :samp:`s`-:samp:`t` cut.

    z0MultiGraph and MultiDiGraph not supported (yet).r"   c                    s4   g | ],\}}}||kr|  ˆ ˆ¡d kr|||f‘qS ©r   )r   ©Ú.0ÚuÚvÚattr©Úcapacityr"   r   r   Ú
<listcomp>l   s    þz*build_residual_network.<locals>.<listcomp>T)Údataé   c                 3   s0   | ](\}}}ˆ |kr|ˆ  ˆkr|ˆ  V  qd S r   r   r.   r3   r   r   Ú	<genexpr>}   s    þz)build_residual_network.<locals>.<genexpr>é   )r4   r   r4   )Zis_multigraphÚnxZNetworkXErrorZDiGraphZadd_nodes_fromr#   r   ÚsumZis_directedÚminr   Zhas_edgeZadd_edgeÚgraph)ÚGr4   ÚRZ	edge_listr0   r1   r2   Úrr   r3   r   r   K   s8    


þþÿù	
c           	      C   s|   t |gƒ}|h}| jd }|rx| ¡ }| |  ¡ D ]B\}}|d |kr2||kr2||kr`t d¡‚| |¡ | |¡ q2qdS )z*Detect an infinite-capacity s-t path in R.r"   r4   z-Infinite capacity path, flow unbounded above.N)r   r=   Úpopleftr   r:   ZNetworkXUnboundedÚaddÚappend)	r?   ÚsÚtÚqÚseenr"   r0   r1   r2   r   r   r   r   œ   s    

ÿ
c                 C   sH   i }| D ]:}dd„ | | D ƒ||< ||   dd„ ||  ¡ D ƒ¡ q|S )z0Build a flow dictionary from a residual network.c                 S   s   i | ]
}|d “qS r-   r   )r/   r1   r   r   r   Ú
<dictcomp>±   s      z#build_flow_dict.<locals>.<dictcomp>c                 s   s*   | ]"\}}|d  dkr||d  fV  qdS )Zflowr   Nr   )r/   r1   r2   r   r   r   r8   ²   s     z"build_flow_dict.<locals>.<genexpr>)Úupdater   )r>   r?   Z	flow_dictr0   r   r   r   r   ­   s    
ÿ
)r   Úcollectionsr   Znetworkxr:   Ú__all__r   r   r   r   r   r   r   r   r   r   Ú<module>   s   ú

Q