U
    `_K                     @   s  d Z dZddlZddlZddlmZmZmZmZm	Z	m
Z
 dddgZedeeef Zed	eee  Zd
ZdZdZdZdZG dd deZe ZdZG dd deZG dd dZd`ee	e
egef  edddZdaee	e ddddZedkrdddgdddgdd dggd!fdddd"gdddd#gdd dd$ggd%fd&d&d'gd(d'd"gd(d)d*ggd+fd,d-d.gd/d0d1gd2d3d4ggd5fd&d&d'd6gd(d'd"d"gd(d)d*d&ggd7fd8d9d:d;gd<d=d>d?gd@dAdBdCggdDfd*dEdFegd"d(dGd6gedEd*egdGdGdGd&ggdHfdIdJdKegdLdMdNdOgedPdQegdRdSdTdUggdVfd"eeeged#eegeed$egeeed*ggd&fdWeeegedXeegeedYegeeedZggd[fg
Z e Z!e D ]t\Z"Z#ee"d\d] e!$e"Z%dZ&e%D ]0\Z'Z(e"e' e( Z)e&e)7 Z&e*d^e'e(e)f  qe*d_e&  e#e&kst+qdS )ba!  
Introduction
============

The Munkres module provides an implementation of the Munkres algorithm
(also called the Hungarian algorithm or the Kuhn-Munkres algorithm),
useful for solving the Assignment Problem.

For complete usage documentation, see: https://software.clapper.org/munkres/
Zmarkdown    N)UnionNewTypeSequenceTupleOptionalCallableMunkresmake_cost_matrix
DISALLOWEDAnyNumMatrixz1.1.4zBrian Clapper, bmc@clapper.orgz%https://software.clapper.org/munkres/z(c) 2008-2020 Brian M. ClapperzApache Software Licensec                   @   s   e Zd ZdS )DISALLOWED_OBJN)__name__
__module____qualname__ r   r   &lib/python3.8/site-packages/munkres.pyr   +   s   r   Dc                   @   s   e Zd ZdZdS )UnsolvableMatrixz2
    Exception raised for unsolvable matrices
    N)r   r   r   __doc__r   r   r   r   r   4   s   r   c                   @   sT  e Zd ZdZdd Zd3eeedddZeee	eef  dd	d
Z
eedddZeeedddZedddZedddZedddZedddZedddZedddZedddZd4eee	eef d d!d"Zee ed#d$d%Zee ed&d'd(Zedd)d*Zeee  ed+d,d-d.Zd+dd/d0Zd+dd1d2Zd+S )5r   zy
    Calculate the Munkres solution to the classical assignment problem.
    See the module documentation for usage.
    c                 C   s4   d| _ g | _g | _d| _d| _d| _d| _d| _dS )zCreate a new instanceNr   )Crow_coveredcol_coverednZ0_rZ0_cmarkedpath)selfr   r   r   __init__D   s    zMunkres.__init__r   )matrix	pad_valuereturnc           	      C   s   d}t |}|D ]}t|t |}qt||}g }|D ]<}t |}|dd }||krh||g||  7 }||g7 }q6t ||k r||g| g7 }qt|S )a  
        Pad a possibly non-square matrix to make it square.

        **Parameters**

        - `matrix` (list of lists of numbers): matrix to pad
        - `pad_value` (`int`): value to use to pad the matrix

        **Returns**

        a new, possibly padded, matrix
        r   N)lenmax)	r   r    r!   Zmax_columnsZ
total_rowsrowZ
new_matrixZrow_lenZnew_rowr   r   r   
pad_matrixO   s    
zMunkres.pad_matrix)cost_matrixr"   c           	      C   s0  |  || _t| j| _t|| _t|d | _dd t| jD | _dd t| jD | _d| _	d| _
| | jd d| _| | jd| _d}d}| j| j| j| j| j| jd}|sz|| }| }W q tk
r   d	}Y qX qg }t| jD ]8}t| jD ](}| j| | dkr |||fg7 }q q|S )
a  
        Compute the indexes for the lowest-cost pairings between rows and
        columns in the database. Returns a list of `(row, column)` tuples
        that can be used to traverse the matrix.

        **WARNING**: This code handles square and rectangular matrices. It
        does *not* handle irregular matrices.

        **Parameters**

        - `cost_matrix` (list of lists of numbers): The cost matrix. If this
          cost matrix is not square, it will be padded with zeros, via a call
          to `pad_matrix()`. (This method does *not* modify the caller's
          matrix. It operates on a copy of the matrix.)


        **Returns**

        A list of `(row, column)` tuples that describe the lowest cost path
        through the matrix
        r   c                 S   s   g | ]}d qS Fr   .0ir   r   r   
<listcomp>   s     z#Munkres.compute.<locals>.<listcomp>c                 S   s   g | ]}d qS r(   r   r)   r   r   r   r,      s        F   )r.   r-               T)r&   r   r#   r   Zoriginal_lengthZoriginal_widthranger   r   r   r   _Munkres__make_matrixr   r   _Munkres__step1_Munkres__step2_Munkres__step3_Munkres__step4_Munkres__step5_Munkres__step6KeyError)	r   r'   donestepZstepsfuncresultsr+   jr   r   r   computer   s>    

zMunkres.compute)r    r"   c                 C   s
   t |S )z+Return an exact copy of the supplied matrix)copydeepcopy)r   r    r   r   r   Z__copy_matrix   s    zMunkres.__copy_matrix)r   valr"   c                    s2   g }t |D ] }| fddt |D g7 }q|S )z@Create an *n*x*n* matrix, populating it with the specific value.c                    s   g | ]} qS r   r   )r*   r@   rD   r   r   r,      s     z)Munkres.__make_matrix.<locals>.<listcomp>)r3   )r   r   rD   r    r+   r   rE   r   Z__make_matrix   s    zMunkres.__make_matrix)r"   c                 C   s   | j }| j}t|D ]p}dd | j | D }t|dkrFtd|t|}t|D ],}| j | | tk	rV| j | |  |8  < qVqdS )z
        For each row of the matrix, find the smallest element and
        subtract it from every element in its row. Go to Step 2.
        c                 S   s   g | ]}|t k	r|qS r   )r
   )r*   xr   r   r   r,      s      z#Munkres.__step1.<locals>.<listcomp>r   zRow {0} is entirely DISALLOWED.r-   )r   r   r3   r#   r   formatminr
   )r   r   r   r+   Zvalsminvalr@   r   r   r   Z__step1   s    zMunkres.__step1c                 C   sz   | j }t|D ]^}t|D ]P}| j| | dkr| j| s| j| sd| j| |< d| j|< d| j|<  qqq|   dS )z
        Find a zero (Z) in the resulting matrix. If there is no starred
        zero in its row or column, star Z. Repeat for each element in the
        matrix. Go to Step 3.
        r   r.   Tr/   )r   r3   r   r   r   r   _Munkres__clear_covers)r   r   r+   r@   r   r   r   Z__step2   s    

zMunkres.__step2c                 C   sj   | j }d}t|D ]@}t|D ]2}| j| | dkr| j| sd| j|< |d7 }qq||krbd}nd}|S )z
        Cover each column containing a starred zero. If K columns are
        covered, the starred zeros describe a complete set of unique
        assignments. In this case, Go to DONE, otherwise, Go to Step 4.
        r   r.   T   r0   )r   r3   r   r   )r   r   countr+   r@   r=   r   r   r   Z__step3   s    
zMunkres.__step3c                 C   s   d}d}d}d}d}|s|  ||\}}|dk r:d}d}qd| j| |< | |}|dkrt|}d| j|< d| j|< qd}|| _|| _d}q|S )ak  
        Find a noncovered zero and prime it. If there is no starred zero
        in the row containing this primed zero, Go to Step 5. Otherwise,
        cover this row and uncover the column containing the starred
        zero. Continue in this manner until there are no uncovered zeros
        left. Save the smallest uncovered value and Go to Step 6.
        r   FTr2   r-   r1   )_Munkres__find_a_zeror   _Munkres__find_star_in_rowr   r   r   r   )r   r=   r<   r%   colZstar_colr   r   r   Z__step4   s*    

zMunkres.__step4c                 C   s   d}| j }| j|| d< | j|| d< d}|s| || d }|dkrv|d7 }||| d< ||d  d || d< nd}|s*| || d }|d7 }||d  d || d< ||| d< q*| || |   |   dS )aG  
        Construct a series of alternating primed and starred zeros as
        follows. Let Z0 represent the uncovered primed zero found in Step 4.
        Let Z1 denote the starred zero in the column of Z0 (if any).
        Let Z2 denote the primed zero in the row of Z1 (there will always
        be one). Continue until the series terminates at a primed zero
        that has no starred zero in its column. Unstar each starred zero
        of the series, star each primed zero of the series, erase all
        primes and uncover every line in the matrix. Return to Step 3
        r   r.   FTr/   )r   r   r   _Munkres__find_star_in_col_Munkres__find_prime_in_row_Munkres__convert_pathrJ   _Munkres__erase_primes)r   rL   r   r<   r%   rP   r   r   r   Z__step5  s*    zMunkres.__step5c                 C   s   |   }d}t| jD ]}t| jD ]}| j| | tkr<q$| j| rd| j| |  |7  < |d7 }| j| s| j| |  |8  < |d7 }| j| r$| j| s$|d8 }q$q|dkrtddS )z
        Add the value found in Step 4 to every element of each covered
        row, and subtract it from every element of each uncovered column.
        Return to Step 4 without altering any stars, primes, or covered
        lines.
        r   r.   r-   zMatrix cannot be solved!r0   )_Munkres__find_smallestr3   r   r   r
   r   r   r   )r   rI   Zeventsr+   r@   r   r   r   Z__step6=  s"    

zMunkres.__step6c                 C   sp   t j}t| jD ]Z}t| jD ]J}| j| s| j| s| j| | tk	r|| j| | kr| j| | }qq|S )z0Find the smallest uncovered value in the matrix.)sysmaxsizer3   r   r   r   r   r
   )r   rI   r+   r@   r   r   r   Z__find_smallestV  s    $zMunkres.__find_smallest)i0j0r"   c           	      C   s   d}d}|}| j }d}|s|}| j| | dkrP| j| sP| j| sP|}|}d}|d | }||krqhq|d | }||krd}q||fS )z-Find the first uncovered element with value 0rM   Fr   Tr.   )r   r   r   r   )	r   rX   rY   r%   rP   r+   r   r<   r@   r   r   r   Z__find_a_zeroa  s,    zMunkres.__find_a_zero)r%   r"   c                 C   s2   d}t | jD ]}| j| | dkr|} q.q|S )z
        Find the first starred element in the specified row. Returns
        the column index, or -1 if no starred element was found.
        rM   r.   r3   r   r   r   r%   rP   r@   r   r   r   Z__find_star_in_row{  s    zMunkres.__find_star_in_row)rP   r"   c                 C   s2   d}t | jD ]}| j| | dkr|} q.q|S )z
        Find the first starred element in the specified row. Returns
        the row index, or -1 if no starred element was found.
        rM   r.   rZ   )r   rP   r%   r+   r   r   r   Z__find_star_in_col  s    zMunkres.__find_star_in_colc                 C   s2   d}t | jD ]}| j| | dkr|} q.q|S )z
        Find the first prime element in the specified row. Returns
        the column index, or -1 if no starred element was found.
        rM   r-   rZ   r[   r   r   r   Z__find_prime_in_row  s    zMunkres.__find_prime_in_rowN)r   rL   r"   c                 C   sv   t |d D ]d}| j|| d  || d  dkrRd| j|| d  || d < qd| j|| d  || d < qd S )Nr.   r   )r3   r   )r   r   rL   r+   r   r   r   Z__convert_path  s    " zMunkres.__convert_pathc                 C   s(   t | jD ]}d| j|< d| j|< q
dS )zClear all covered matrix cellsFN)r3   r   r   r   )r   r+   r   r   r   Z__clear_covers  s    
zMunkres.__clear_coversc                 C   sD   t | jD ]4}t | jD ]$}| j| | dkrd| j| |< qq
dS )zErase all prime markingsr-   r   NrZ   )r   r+   r@   r   r   r   Z__erase_primes  s    zMunkres.__erase_primes)r   )r   r   )r   r   r   r   r   r   intr&   r   r   rA   Z_Munkres__copy_matrixr   r4   r5   r6   r7   r8   r9   r:   rU   rN   rO   rQ   rR   rS   rJ   rT   r   r   r   r   r   >   s.   #;!$
 	)profit_matrixinversion_functionr"   c                    sL    s"t dd | D fdd g }| D ]}| fdd|D  q*|S )a  
    Create a cost matrix from a profit matrix by calling `inversion_function()`
    to invert each value. The inversion function must take one numeric argument
    (of any type) and return another numeric argument which is presumed to be
    the cost inverse of the original profit value. If the inversion function
    is not provided, a given cell's inverted value is calculated as
    `max(matrix) - value`.

    This is a static method. Call it like this:

        from munkres import Munkres
        cost_matrix = Munkres.make_cost_matrix(matrix, inversion_func)

    For example:

        from munkres import Munkres
        cost_matrix = Munkres.make_cost_matrix(matrix, lambda x : sys.maxsize - x)

    **Parameters**

    - `profit_matrix` (list of lists of numbers): The matrix to convert from
       profit to cost values.
    - `inversion_function` (`function`): The function to use to invert each
       entry in the profit matrix.

    **Returns**

    A new matrix representing the inversion of `profix_matrix`.
    c                 s   s   | ]}t |V  qd S N)r$   )r*   r%   r   r   r   	<genexpr>  s     z#make_cost_matrix.<locals>.<genexpr>c                    s    |  S r_   r   )rF   )maximumr   r   <lambda>      z"make_cost_matrix.<locals>.<lambda>c                    s   g | ]} |qS r   r   )r*   value)r^   r   r   r,     s     z$make_cost_matrix.<locals>.<listcomp>)r$   append)r]   r^   r'   r%   r   )r^   ra   r   r	     s    !)r    msgr"   c           	      C   s   ddl }|dk	rt| d}| D ],}|D ]"}|tkr8t}t|tt|}q(q d| }| D ]J}d}|D ]0}|tkrvt}|d | }tj	||  d}qftj	d qZdS )z
    Convenience function: Displays the contents of a matrix.

    **Parameters**

    - `matrix` (list of lists of numbers): The matrix to print
    - `msg` (`str`): Optional message to print before displaying the matrix
    r   Nz%%%d[sz, z]
)
mathprintr
   DISALLOWED_PRINTVALr$   r#   strrV   stdoutwrite)	r    rf   ri   widthr%   rD   rG   sep	formattedr   r   r   print_matrix  s&    	rr   __main__i     i  iX  i,     iR  r.   r-   r/   i  
      	   rK   r0      g333333$@gffffff$@g @g"@g      !@g?gffffff#@g333333@g@g     3@      gQ$@g
ףp=
$@g(\ @gGz&@g"@gQ @gQ?gHzG?gGz."@gffffff@gq=
ףp@g=
ףp=$@gffffff.@r1   r2         g/$@g5^I@gPn@gMb?g(\"@gPn(@g$&@gx&1@gK7	@gQ(@gʡ(@g/$(@g-$@gI+4@g?g@gffffff
@g@g      &@zcost matrix)rf   z(%d, %d) -> %szlowest cost=%s)N)N),r   Z__docformat__rV   rB   typingr   r   r   r   r   r   __all__r\   floatr   r   __version__
__author__Z__url__Z__copyright__Z__license__objectr   r
   rk   	Exceptionr   r   r	   rl   rr   r   Zmatricesmr'   Zexpected_totalrA   ZindexesZ
total_costrcrF   rj   AssertionErrorr   r   r   r   <module>   s    

    *(

























B
