a
    ¬J5deS  ã                   @   s~   d dl Z d dlZd dlZddlmZ ddlmZ ddlmZ ddlmZ G dd„ de	ƒZ
G d	d
„ d
e
dZG dd„ deƒZdS )é    Né   )Úfields©Úmatrix)Ú	distances)Úutilsc                       s   e Zd Z‡ fdd„Z‡  ZS )ÚFileMetac                    sl  i i i i dœ}t | ¡ ƒD ]T\}}t|tjƒr||d |< ||d |j< ||d |j< |j|d |< | |¡ q| |¡ tƒ  	| |||¡}|D ]Ö}i }	t
|jƒD ]¶}
t|
|ƒrÀ|	 t|
|ƒ¡ t |
j ¡ ƒD ]ˆ\}}|d u rÎ||	v rÎ|	 |¡}t|tjƒrÎ|ddg|jddgi}| ¡ D ]:\}}|D ]*}z|	| |= W n tyL   Y n0 q&qqÎq¢t|||	ƒ q|S )N)Úfields_by_nameÚfields_by_keywordÚnames_by_keywordÚkeywords_by_namer	   r
   r   r   )ÚlistÚitemsÚ
isinstanceÚFÚFieldÚkeywordÚpopÚupdateÚsuperÚ__new__ÚreversedÚ__mro__ÚhasattrÚgetattrÚ__dict__ÚKeyErrorÚsetattr)ÚmcsÚ
class_nameÚbasesÚattrsÚcurrentÚnameÚvalueÚ	new_classÚkeyÚdataÚbaseZ
base_valueZworkZk2ÚkeysZk1©Ú	__class__© úK/var/www/html/django/DPS/env/lib/python3.9/site-packages/tsplib95/models.pyr      sL    ü


ÿÿýzFileMeta.__new__)Ú__name__Ú
__module__Ú__qualname__r   Ú__classcell__r,   r,   r*   r-   r      s   r   c                       s’   e Zd ZdZ‡ fdd„Zedd„ ƒZedd„ ƒZedd	„ ƒZd
d„ Z	‡ fdd„Z
ddd„Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Z‡  ZS )ÚProblemzCBase class for all problems.

    :param data: name-value data
    c                    s2   t ƒ  ¡  | ¡ D ]\}}t| ||ƒ qi | _d S ©N)r   Ú__init__r   r   Ú	_defaults)Úselfr'   r#   r$   r*   r,   r-   r4   O   s    
zProblem.__init__c                 K   s²   d  | j¡}d}d|› d|› d}t |tj¡}| |¡^}}|ddd… }	|ddd… }
i }t|	|
ƒD ]6\}}|d	krh| j| }| j| }| | 	¡ ¡||< qh| f i |¤|¤ŽS )
a  Parse text into a problem instance.

        Any keyword options are passed to the class constructor. If a keyword
        argument has the same name as a field then they will collide and cause
        an error.

        :param str text: problem text
        :param options: any keyword arguments to pass to the constructor
        :return: problem instance
        :rtype: :class:`Problem`
        ú|z\s*:\s*|\s*\nú(z|EOF)(?:ú)Né   r   ÚEOF)
Újoinr
   ÚreÚcompileÚMÚsplitÚzipr   ÚparseÚstrip)ÚclsÚtextÚoptionsÚkeywordsÚsepÚpatternÚregexÚ__ÚresultsZfield_keywordsZfield_valuesr'   r   r$   Úfieldr#   r,   r,   r-   rB   V   s    

zProblem.parsec                 K   s>   t |ƒ"}| j|fi |¤ŽW  d  ƒ S 1 s00    Y  dS )a£  Load a problem instance from a text file.

        Any keyword options are passed to the class constructor. If a keyword
        argument has the same name as a field then they will collide and cause
        an error.

        :param str filepath: path to a problem file
        :param options: any keyword arguments to pass to the constructor
        :return: problem instance
        :rtype: :class:`Problem`
        N)ÚopenÚread)rD   ÚfilepathrF   Úfr,   r,   r-   Úload{   s    
zProblem.loadc                 K   s   | j | ¡ fi |¤ŽS )a   Read a problem instance from a file-like object.

        Any keyword options are passed to the class constructor. If a keyword
        argument has the same name as a field then they will collide and cause
        an error.

        :param str fp: a file-like object
        :param options: any keyword arguments to pass to the constructor
        :return: problem instance
        :rtype: :class:`Problem`
        )rB   rO   )rD   ÚfprF   r,   r,   r-   rO   ‹   s    zProblem.readc                 C   s   |   ¡ S r3   )Úrender©r6   r,   r,   r-   Ú__str__š   s    zProblem.__str__c                    s¬   zt  | d¡}|| W S  ty(   Y n0 zt  | d¡}|j| }W n tyV   Y nJ0 | ¡ }|| jv rŒ| j| |krŒt| || j| ƒ n
|| j|< | j| S tƒ  |¡S )Nr   r+   )ÚobjectÚ__getattribute__r   r	   Úget_default_valuer5   r   r   )r6   r#   r!   rD   rM   Údefaultr*   r,   r-   rX      s     


zProblem.__getattribute__Fc                 C   sT   i }| j j ¡ D ]>\}}t| |ƒ}|| jv s8|| ¡ kr|rB|jn|}|||< q|S )z²Return the problem data as a dictionary.

        :param bool by_keyword: use keywords (True) or names (False) or keys
        :return: problem data
        :rtype: dict
        )r+   r	   r   r   r   rY   r   )r6   Ú
by_keywordr'   r#   rM   r$   r&   r,   r,   r-   Úas_dictº   s    

zProblem.as_dictc                 C   s   | j ddS )zsReturn the problem data as a dictionary by field name.

        :return: problem data
        :rtype: dict
        F©r[   ©r\   rU   r,   r,   r-   Úas_name_dictÉ   s    zProblem.as_name_dictc                 C   s   | j ddS )zvReturn the problem data as a dictionary by field keyword.

        :return: problem data
        :rtype: dict
        Tr]   r^   rU   r,   r,   r-   Úas_keyword_dictÑ   s    zProblem.as_keyword_dictc                 C   s¢   |   ¡ }t|ƒD ]@}| |¡}| jj| }|| jv s@|| ¡ kr| |¡||j< qg }| 	¡ D ].\}}d|v rrdnd}| 
|› |› |› ¡ q^| 
d¡ d |¡S )NÚ
z:
z: r;   )r_   r   r   r+   r	   r   rY   rT   r   r   Úappendr<   )r6   Úrenderedr#   r$   rM   Zkvpairsr   rH   r,   r,   r-   rT   Ù   s    

zProblem.renderc                 C   s8   t |dƒ}|  |¡ W d   ƒ n1 s*0    Y  d S )NÚw)rN   Úwrite)r6   ÚfilenamerQ   r,   r,   r-   Úsaveì   s    zProblem.savec                 C   s   |  |  ¡ ¡ d S r3   )re   rT   )r6   rS   r,   r,   r-   re   ð   s    zProblem.writec                 C   s   d S r3   r,   rU   r,   r,   r-   Úvalidateó   s    zProblem.validate)F)r.   r/   r0   Ú__doc__r4   ÚclassmethodrB   rR   rO   rV   rX   r\   r_   r`   rT   rg   re   rh   r1   r,   r,   r*   r-   r2   I   s"   
$


r2   )Ú	metaclassc                       s|  e Zd ZdZe d¡Ze d¡Ze d¡Ze 	d¡Z
e 	d¡Ze d¡Ze d¡Ze d	¡Ze d
¡Ze d¡ZejdddZe d¡Ze d¡ZejdddZe d¡Ze d¡Ze d¡Ze d¡Zd>‡ fdd„	Z e!dd„ ƒZ"e"j#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/d0„ Z-d1d2„ Z.d3d4„ Z/d5d6„ Z0d?d8d9„Z1d@d:d;„Z2d<d=„ Z3‡  Z4S )AÚStandardProblema³  Standard problem as outlined in the original TSLIB95 documentation.

    The available fields and their keywords are:

     * ``name`` - NAME
     * ``comment`` - COMMENT
     * ``type`` - TYPE
     * ``dimension`` - DIMENSION
     * ``capacity`` - CAPACITY
     * ``edge_weight_type`` - EDGE_WEIGHT_TYPE
     * ``edge_weight_format`` - EDGE_WEIGHT_FORMAT
     * ``edge_data_format`` - EDGE_DATA_FORMAT
     * ``node_coord_type`` - NODE_COORD_TYPE
     * ``display_data_type`` - DISPLAY_DATA_TYPE
     * ``depots`` - DEPOT_SECTION
     * ``demands`` - DEMAND_SECTION
     * ``node_coords`` - NODE_COORD_SECTION
     * ``edge_weights`` - EDGE_WEIGHT_SECTION
     * ``display_data`` - DISPLAY_DATA_SECTION
     * ``edge_data`` - EDGE_DATA_SECTION
     * ``fixed_edges`` - FIXED_EDGES_SECTION
     * ``tours`` - TOUR_SECTION

    For SPECIAL FUNCTION problems, the special function must accept a start
    and an end node and return the weight, distance, or cost of the edge that
    joins them. It can be provided at construction time or simply set on an
    existing object using the ``special`` attribute.

    :param callable special: special function for distance
    :param data: name-value data
    ÚNAMEÚCOMMENTZTYPEZ	DIMENSIONZCAPACITYZNODE_COORD_TYPEZEDGE_WEIGHT_TYPEZDISPLAY_DATA_TYPEZEDGE_WEIGHT_FORMATZEDGE_DATA_FORMATZNODE_COORD_SECTION)r:   é   )Ú
dimensionsZEDGE_DATA_SECTIONZEDGE_WEIGHT_SECTIONZDISPLAY_DATA_SECTIONr:   ZFIXED_EDGES_SECTIONZDEPOT_SECTIONZDEMAND_SECTIONZTOUR_SECTIONNc                    s"   t ƒ jf i |¤Ž d | _|| _d S r3   )r   r4   Ú_wfuncÚspecial)r6   rr   r'   r*   r,   r-   r4   .  s    zStandardProblem.__init__c                 C   s   | j S )z±Special distance function.

        Special/custom distance functions must accept two coordinates of
        appropriate dimension and return the distance between them.
        )Ú_specialrU   r,   r,   r-   rr   3  s    zStandardProblem.specialc                 C   s   || _ | j|d| _d S )N)rr   )rs   Ú_create_wfuncrq   )r6   Úfuncr,   r,   r-   rr   <  s    c                 C   s   |   ||¡S )a‚  Return the weight of the edge between start and end.

        This method provides a single way to obtain edge weights regardless of
        whether the problem uses an explicit matrix or a distance function.

        :param int start: starting node index
        :param int end: ending node index
        :return: weight of the edge between start and end
        :rtype: float
        )rq   )r6   ÚstartÚendr,   r,   r-   Ú
get_weightA  s    zStandardProblem.get_weightc                 C   s
   | j dkS )z¢Check whether the problem specifies edge weights explicitly.

        :return: True if the problem specifies edge weights explicitly
        :rtype: bool
        ZEXPLICIT©Úedge_weight_typerU   r,   r,   r-   Úis_explicitN  s    zStandardProblem.is_explicitc                 C   s
   | j dkS )zšCheck whether the problem is specified as a full matrix.

        :return: True if the problem is specified as a full matrix
        :rtype: bool
        ZFULL_MATRIX)Úedge_weight_formatrU   r,   r,   r-   Úis_full_matrixV  s    zStandardProblem.is_full_matrixc                 C   s   t | jƒpt | jƒS )zùCheck whether the problem has weighted edges.

        A problem is considered unweighted if neither the EDGE_WEIGHT_FORMAT
        nor the EDGE_WEIGHT_TYPE are defined.

        :return: True if the problem is weighted
        :rtype: bool
        )Úboolr|   rz   rU   r,   r,   r-   Úis_weighted^  s    	zStandardProblem.is_weightedc                 C   s
   | j dkS )zÍCheck whether the problem is special.

        SPECIAL problems require a special distance function.

        :return: True if the problem requires a special distance function
        :rtype: bool
        ZSPECIALry   rU   r,   r,   r-   Ú
is_speciali  s    zStandardProblem.is_specialc                 C   s   t | jƒ S )z”Check whether the problem specifies a complete graph.

        :return: True if the problem specifies a complete graph
        :rtype: bool
        )r~   Úedge_data_formatrU   r,   r,   r-   Úis_completes  s    zStandardProblem.is_completec                 C   s   |   ¡  o|  ¡  S )ak  Check whether the problem is symmetrical.

        .. warning::

            Although a result of ``True`` guarantees symmetry, a value of
            ``False`` merely indicates the *possibliity* for asymmetry. Avoid
            using ``not problem.is_symmetric()`` when possible.

        :return: True if the problem is symmetrical
        :rtype: bool
        )r}   r€   rU   r,   r,   r-   Úis_symmetric{  s    zStandardProblem.is_symmetricc                 C   s&   t | jƒrdS | jdkrdS t | jƒS )z÷Check whether the problem can be depicted.

        A problem is depictable if it has display data or has node coordinates
        and does not specify NO_DISPLAY.

        :return: True if the problem can be depicted
        :rtype: bool
        TZ
NO_DISPLAYF)r~   Údisplay_dataÚdisplay_data_typeÚnode_coordsrU   r,   r,   r-   Úis_depictable‰  s
    	

zStandardProblem.is_depictablec                    s<   g }|D ].}t  |¡}t‡ fdd„|D ƒƒ}| |¡ q|S )a*  Return the weights of the given tours.

        Each tour is a list of node indices. The weights returned are the sum
        of the individual weights of the edges in each tour including the final
        edge back to the starting node.

        The list of weights returned parallels the list of tours given so that
        ``weights[i]`` corresponds to ``tours[i]``::

            weights = p.trace_tours(tours)

        :param list tours: one or more lists of node indices
        :return: one weight for each given tour
        :rtype: list
        c                 3   s   | ]\}}ˆ   ||¡V  qd S r3   )rx   )Ú.0ÚiÚjrU   r,   r-   Ú	<genexpr>­  ó    z.StandardProblem.trace_tours.<locals>.<genexpr>)r   ÚpairwiseÚsumrb   )r6   ÚtoursZ	solutionsZtourÚedgesÚweightr,   rU   r-   Útrace_toursš  s    
zStandardProblem.trace_toursc                 C   s   t |  ¡ ƒ}|  |g¡d S )zðReturn the weight of the canonical tour.

        The "canonical tour" uses the nodes in order. This method is present
        primarily for testing and purposes.

        :return: weight of the canonical tour
        :rtype: float
        r   )r   Ú	get_nodesr’   )r6   Únodesr,   r,   r-   Útrace_canonical_tour±  s    	z$StandardProblem.trace_canonical_tourc                 C   sæ   | j rtt| j ƒƒS | jr(tt| jƒƒS | jdkrbtƒ }| jD ]\}}| ||h¡ q>tt|ƒƒS | jdkr¢tƒ }| j ¡ D ]\}}| |h|£¡ q|tt|ƒƒS | j	r¶tt| j	ƒƒS ztt
| jƒƒW S  tyà   tdƒ‚Y n0 dS )a–  Return an iterator over the nodes.

        This method provides a single way to obtain the nodes of a problem
        regardless of how it is specified. However, if the nodes are not
        specified, the EDGE_DATA_FORMAT is not set, and DIMENSION has no value,
        then nodes are undefined.

        :return: nodes
        :rtype: iter
        :raises ValueError: if the nodes are undefined
        Ú	EDGE_LISTÚADJ_LISTzundefined nodesN)r†   ÚiterÚsortedr„   r   ÚsetÚ	edge_datar   r   ÚdemandsÚrangeÚ	dimensionÚ	ExceptionÚ
ValueError)r6   r”   ÚaÚbZendsr,   r,   r-   r“   ½  s(    

zStandardProblem.get_nodesc                 #   sn   | j dkr| jE dH  nR| j dkrP| j ¡ D ] \‰ }‡ fdd„|D ƒE dH  q,nt |  ¡ |  ¡ ¡E dH  dS )a‰  Return an iterator over the edges.

        This method provides a single way to obtain the edges of a problem
        regardless of how it is specified. If the EDGE_DATA_FORMAT is not set
        and the nodes are undefined, then the edges are also undefined.

        :return: edges
        :rtype: iter
        :raises ValueError: if the nodes and therefore the edges are undefined
        r–   Nr—   c                 3   s   | ]}ˆ |fV  qd S r3   r,   )rˆ   rŠ   ©r‰   r,   r-   r‹   ò  rŒ   z,StandardProblem.get_edges.<locals>.<genexpr>)r   r›   r   Ú	itertoolsÚproductr“   )r6   Zadjr,   r£   r-   Ú	get_edgesã  s    

zStandardProblem.get_edgesc              	   C   s@   |   ¡ r8z| j| W S  ttfy4   | j|  Y S 0 ndS dS )zÇReturn the display data for node at index *i*.

        If the problem is not depictable, None is returned instead.

        :param int i: node index
        :return: display data for node i
        N)r‡   r„   r   Ú	TypeErrorr†   )r6   r‰   r,   r,   r-   Úget_displayö  s    zStandardProblem.get_displayFc                 C   s  |   ¡ rt ¡ nt ¡ }| j|jd< | j|jd< | j|jd< | j|jd< | j	|jd< t
|  ¡ ƒ}|rxdd„ t|ƒD ƒ}ndd„ |D ƒ}|D ]>}|| jv }|j|| | j |¡| j |¡| j |¡|d	 qŠ|  ¡ D ]<\}}|  ||¡}	||f| jv }
|j|| || |	|
d
 qÒ|S )a  Return a networkx graph instance representing the problem.

        The metadata of the problem is associated with the graph itself.
        Additional problem information is associated with the nodes and edges.
        For example:

        .. code-block:: python

            >>> G = problem.get_graph()
            >>> G.graph
            {'name': None,
             'comment': '14-Staedte in Burma (Zaw Win)',
             'type': 'TSP',
             'dimension': 14,
             'capacity': None}
            >>> G.nodes[1]
            {'coord': (16.47, 96.1),
             'display': None,
             'demand': None,
             'is_depot': False}
            >>> G.edges[1, 2]
            {'weight': 2, 'is_fixed': False}

        If the graph is asymmetric then a :class:`networkx.DiGraph` is
        returned. Optionally, the nodes can be renamed to be sequential and
        zero-indexed.

        :param bool normalize: rename nodes to be zero-indexed
        :return: graph
        :rtype: :class:`networkx.Graph`
        r#   ÚcommentÚtyperž   Úcapacityc                 S   s   i | ]\}}||“qS r,   r,   )rˆ   r‰   Únr,   r,   r-   Ú
<dictcomp>4  rŒ   z-StandardProblem.get_graph.<locals>.<dictcomp>c                 S   s   i | ]
}||“qS r,   r,   )rˆ   r¬   r,   r,   r-   r­   6  rŒ   )ZcoordÚdisplayZdemandÚis_depot)r‘   Úis_fixed)rƒ   ÚnetworkxZGraphZDiGraphr#   Úgraphr©   rª   rž   r«   r   r“   Ú	enumerateÚdepotsÚadd_noder†   Úgetr„   rœ   r¦   rx   Úfixed_edgesZadd_edge)r6   Ú	normalizeÚGr”   Únamesr¬   r¯   r¡   r¢   r‘   r°   r,   r,   r-   Ú	get_graph  s,    !


ýzStandardProblem.get_graphc                    sj   ˆ  ¡ rˆ ¡ ‰ ‡ fdd„S ˆ ¡ r:|d u r4tdƒ‚|‰nˆ ¡ rPtjˆj ‰ndd„ S ‡‡fdd„}|S )Nc                    s   ˆ | |f S r3   r,   ©r‰   rŠ   r   r,   r-   Ú<lambda>M  rŒ   z/StandardProblem._create_wfunc.<locals>.<lambda>z&missing needed special weight functionc                 S   s   dS )Nr   r,   r¼   r,   r,   r-   r½   Y  rŒ   c                    s   ˆˆ j |  ˆ j | ƒS r3   )r†   r¼   )r6   Úwfuncr,   r-   Úadapter]  s    z.StandardProblem._create_wfunc.<locals>.adapter)r{   Ú_create_explicit_matrixr€   rŸ   r   r   ÚTYPESrz   )r6   rr   r¿   r,   )r   r6   r¾   r-   rt   I  s    zStandardProblem._create_wfuncc                 C   s8   t |  ¡ ƒ}tj| j }ttj| jŽ ƒ}||| j	|dS )N)Ú	min_index)
Úminr“   r   rÁ   r|   r   r¤   ÚchainÚedge_weightsrž   )r6   ÚmZMatrixÚweightsr,   r,   r-   rÀ   b  s    z'StandardProblem._create_explicit_matrix)N)F)N)5r.   r/   r0   ri   r   ZStringFieldr#   r©   rª   ZIntegerFieldrž   r«   Znode_coord_typerz   r…   r|   r   ZIndexedCoordinatesFieldr†   ZEdgeDataFieldr›   ZMatrixFieldrÅ   r„   ZEdgeListFieldr·   ZDepotsFieldr´   ZDemandsFieldrœ   Z
ToursFieldr   r4   Úpropertyrr   Úsetterrx   r{   r}   r   r€   r‚   rƒ   r‡   r’   r•   r“   r¦   r¨   r»   rt   rÀ   r1   r,   r,   r*   r-   rl   ÷   sP    


















&
B
rl   )r¤   r=   r±   Ú r   r   r   r   r   rª   r   r2   rl   r,   r,   r,   r-   Ú<module>   s   < /