o
    ˷ep                     @   sp   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dd ZdddZdS )z=Lukes Algorithm for exact optimal weighted tree partitioning.    )deepcopy)	lru_cache)choiceN)not_implemented_forlukes_partitioningweightg      ?   
partitionsi   c                 c   s4    | |ksJ t || d D ]	}|| | fV  qd S )Nr   )range)nmin_size_of_first_partp1 r   Z/var/www/ideatree/venv/lib/python3.10/site-packages/networkx/algorithms/community/lukes.py_split_n_from   s
   r   c              	      s  t | s
t dt | r)dd |  D }t|dks J |d }t| }ntt| j	}t 
| |}du s>du r]t| du rOt tt tdu r\t tt tn| t  }|D ]}t|tsxtd dqitd	d
d  td	 fdd}ttfddfddttfdddd fdd}	t |D ]'}
t |j	|
 t< j	|
  }|
hg|j	|
 t |< |
hg|j	|
 t d< qfdd|j	D D ]}t |j	| t< j	|  }|hg|j	| t |< q	 ||}j	|  }d}d}t }t ||}|D ]}t||d D ]c}t||D ]Z\}}||j	| t  vsQ||j	| t  vrSq5|j	| t | }|j	| t | }|	|||||\}}|| vs|| d |k r||f||< ||kr|}|}q5q.|  D ]\}\}}||j	| t |< q|!  q%||j	| t d< |"| ||kr|j	| t d S q)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 ()
undirectedc                 s   s$    | j D ]}t| |s|V  qd S N)nodesnxdescendants)grxr   r   r   _leavesv   s   
z#lukes_partitioning.<locals>._leavesc                    sJ   t |  t | j  D ]}t fddt| |D r"|  S qd S )Nc                    s   g | ]}| v 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_onlyc                    s,    fddj D }tfdd|D S )Nc                    s(   g | ]}|d   v r|d  v r|qS )r   r   r   r   eclusterr   r   r      s   ( zAlukes_partitioning.<locals>._value_of_cluster.<locals>.<listcomp>c                 3       | ]
}j |   V  qd S r   )edgesr#   edge_weightsafe_Gr   r   	<genexpr>       z@lukes_partitioning.<locals>._value_of_cluster.<locals>.<genexpr>)r(   sum)r&   valid_edgesr)   r%   r   _value_of_cluster   s   z-lukes_partitioning.<locals>._value_of_clusterc                    s   t  fdd| D S )Nc                 3   s    | ]	} t |V  qd S r   )	frozensetr   cr0   r   r   r,      s    zBlukes_partitioning.<locals>._value_of_partition.<locals>.<genexpr>r.   )	partitionr4   r   r   _value_of_partition   s   z/lukes_partitioning.<locals>._value_of_partitionc                    s   t  fdd| D S )Nc                 3   r'   r   )r   )r   r   node_weightr+   r   r   r,      r-   zAlukes_partitioning.<locals>._weight_of_cluster.<locals>.<genexpr>r5   r%   r8   r   r   _weight_of_cluster   s   z.lukes_partitioning.<locals>._weight_of_clusterc                    s*    fdd| D }t |dksJ |d S )Nc                    s   g | ]} |v r|qS r   r   r2   noder   r   r          z6lukes_partitioning.<locals>._pivot.<locals>.<listcomp>r   r   )len)r6   r<   ccxr   r;   r   _pivot   s   z"lukes_partitioning.<locals>._pivotc           
         s   | |||   }t||kr:ttfdd| }tt fdd|}|g| | }||fS | | }	|	|	fS )Nc                       |  kS r   r   r   )r?   r   r   <lambda>       zClukes_partitioning.<locals>._concatenate_or_merge.<locals>.<lambda>c                    rA   r   r   rB   )ccir   r   rC      rD   )unionr1   listfilter)
partition_1partition_2r   i
ref_weigth	merged_xicp1cp2option_2option_1)r@   r7   r:   )rE   r?   r   _concatenate_or_merge   s   


z1lukes_partitioning.<locals>._concatenate_or_mergec                    s   g | ]}| vr|qS r   r   r   )leavesr   r   r      r=   )#r   is_treeNotATreeis_directed	in_degreer>   r   r   rG   r   dfs_treeset_edge_attributesD_EDGE_VALUED_EDGE_Wset_node_attributesD_NODE_VALUED_NODE_Wget_node_attributesvalues
isinstanceint	TypeErrorr   r   CLUSTER_EVAL_CACHE_SIZEr    dictPKEYr   r
   r   keysitemsclearremove_nodes_from)Gmax_sizer9   r*   roott_G
all_n_attrr   r"   rR   lvslotinnerx_nodeweight_of_x
best_valuebest_partition	bp_bufferx_descendantsi_nodejabpart1part2partvaluewbest_part_for_vlvlr   )	r   r@   r0   r7   r:   r*   rS   r9   r+   r   r      s   
/




 


)NN)__doc__copyr   	functoolsr   randomr   networkxr   networkx.utilsr   __all__r[   rZ   r^   r]   rf   rd   r   r   r   r   r   r   <module>   s    