3
Md                 @   s   d Z ddlmZ ddlmZ ddlmZ ddlZddl	m
Z
 dgZdZd	ZdZd
ZdZdZeedddZdeedddZdS )z=Lukes Algorithm for exact optimal weighted tree partitioning.    )deepcopy)	lru_cache)choiceN)not_implemented_forlukes_partitioningZweightg      ?   Z
partitionsi   )nmin_size_of_first_partc             c   s6   | |kst x$t|| d D ]}|| | fV  qW d S )Nr   )AssertionErrorrange)r   r	   p1 r   U/var/www/html/virt/lib/python3.6/site-packages/networkx/algorithms/community/lukes.py_split_n_from   s    r   )max_sizereturnc          	      s  t j| st jdnXt j| rTdd | j D }t|dksBt|d }t| }ntt	| j
}t j| |}dks~dkrt| dkrt jtt tdkrt jtt tn| t jj }x&|D ]}t|tstd dqW td	d
d  td	 fdd}tttdfddt	dfddtttdfddt	dddt	t	dfdd}	t |xXD ]P}
t |j
|
 t< j
|
  }|
hg|j
|
 t |< |
hg|j
|
 t d< qW xRfdd|j
D D ]:}t |j
| t< j
|  }|hg|j
| t |< qW x||}j
|  }d}d}t }t j||}x$|D ]}xt||d D ]}xt ||D ]\}}||j
| t j! ks||j
| t j! krq|j
| t | }|j
| t | }|	|||||\}}||j! ks<|| d |k rH||f||< ||kr|}|}qW qW x,|j" D ] \}\}}||j
| t |< qpW |j#  qW ||j
| t d< |j$| ||krJ|j
| t d S qJW dS )u  Optimal partitioning of a weighted tree using the Lukes algorithm.

    This algorithm partitions a connected, acyclic graph featuring integer
    node weights and float edge weights. The resulting clusters are such
    that the total weight of the nodes in each cluster does not exceed
    max_size and that the weight of the edges that are cut by the partition
    is minimum. The algorithm is based on LUKES[1].

    Parameters
    ----------
    G : graph

    max_size : int
        Maximum weight a partition can have in terms of sum of
        node_weight for all nodes in the partition

    edge_weight : key
        Edge data key to use as weight. If None, the weights are all
        set to one.

    node_weight : key
        Node data key to use as weight. If None, the weights are all
        set to one. The data must be int.

    Returns
    -------
    partition : list
        A list of sets of nodes representing the clusters of the
        partition.

    Raises
    -------
    NotATree
        If G is not a tree.
    TypeError
        If any of the values of node_weight is not int.

    References
    ----------
    .. Lukes, J. A. (1974).
       "Efficient Algorithm for the Partitioning of Trees."
       IBM Journal of Research and Development, 18(3), 217–224.

    z&lukes_partitioning works only on treesc             S   s   g | ]\}}|d kr|qS )r   r   ).0r   dr   r   r   
<listcomp>O   s    z&lukes_partitioning.<locals>.<listcomp>r   r   Nz9lukes_partitioning needs integer values for node_weight ()Z
undirectedc             s   s&   x | j D ]}tj| |s|V  qW d S )N)nodesnxdescendants)grxr   r   r   _leavesv   s    z#lukes_partitioning.<locals>._leavesc                sJ   t |  x8t | j  D ]&}t fddtj| |D r|S qW d S )Nc                s   g | ]}| kqS r   r   )r   r   )tleavesr   r   r      s    zHlukes_partitioning.<locals>._a_parent_of_leaves_only.<locals>.<listcomp>)setr   allr   r   )r   r   )r   )r   r   _a_parent_of_leaves_only}   s    z4lukes_partitioning.<locals>._a_parent_of_leaves_only)clusterc                s,    fddj D }tfdd|D S )Nc                s(   g | ] }|d   kr|d  kr|qS )r   r   r   )r   e)r    r   r   r      s    zAlukes_partitioning.<locals>._value_of_cluster.<locals>.<listcomp>c                s   g | ]}j |   qS r   )edges)r   r!   )edge_weightsafe_Gr   r   r      s    )r"   sum)r    Zvalid_edges)r#   r$   )r    r   _value_of_cluster   s    z-lukes_partitioning.<locals>._value_of_cluster)	partitionc                s   t  fdd| D S )Nc                s   g | ]} t |qS r   )	frozenset)r   c)r&   r   r   r      s    zClukes_partitioning.<locals>._value_of_partition.<locals>.<listcomp>)r%   )r'   )r&   r   r   _value_of_partition   s    z/lukes_partitioning.<locals>._value_of_partitionc                s   t  fdd| D S )Nc                s   g | ]}j |   qS r   )r   )r   r   )node_weightr$   r   r   r      s    zBlukes_partitioning.<locals>._weight_of_cluster.<locals>.<listcomp>)r%   )r    )r+   r$   r   r   _weight_of_cluster   s    z.lukes_partitioning.<locals>._weight_of_clusterc                s*    fdd| D }t |dks"t|d S )Nc                s   g | ]} |kr|qS r   r   )r   r)   )noder   r   r      s    z6lukes_partitioning.<locals>._pivot.<locals>.<listcomp>r   r   )lenr
   )r'   r-   ccxr   )r-   r   _pivot   s    z"lukes_partitioning.<locals>._pivot)partition_1partition_2c       
         s   | ||| j  }t||krtttfdd| }tt fdd|}|g| | }||fS | | }	|	|	fS d S )Nc                s   |  kS )Nr   )r   )r/   r   r   <lambda>   s    zClukes_partitioning.<locals>._concatenate_or_merge.<locals>.<lambda>c                s   |  kS )Nr   )r   )ccir   r   r3      s    )unionr(   listfilter)
r1   r2   r   iZ
ref_weigthZ	merged_xiZcp1Zcp2Zoption_2Zoption_1)r0   r*   r,   )r4   r/   r   _concatenate_or_merge   s    


z1lukes_partitioning.<locals>._concatenate_or_mergec                s   g | ]}| kr|qS r   r   )r   r   )leavesr   r   r      s    )%r   Zis_treeZNotATreeZis_directedZ	in_degreer.   r
   r   r   r6   r   Zdfs_treeZset_edge_attributesD_EDGE_VALUED_EDGE_WZset_node_attributesD_NODE_VALUED_NODE_WZget_node_attributesvalues
isinstanceint	TypeErrorr   r   CLUSTER_EVAL_CACHE_SIZEr(   r   dictPKEYr   r   r   keysitemsclearZremove_nodes_from)Gr   r+   r#   rootZt_GZ
all_n_attrr   r   r9   lvslotinnerZx_nodeZweight_of_xZ
best_valueZbest_partitionZ	bp_bufferZx_descendantsZi_nodejabZpart1Zpart2partvaluewZbest_part_for_vlZvlr   )	r   r0   r&   r*   r,   r#   r:   r+   r$   r   r      s    /




	
 


)NN)__doc__copyr   	functoolsr   randomr   Znetworkxr   Znetworkx.utilsr   __all__r<   r;   r>   r=   rE   rC   rA   r   r6   r   r   r   r   r   <module>   s   