a
    .'Øaþ0  ã                   @   s.   d dl Zd dlmZ G dd„ dƒZdd„ ZdS )é    Nc                   @   sl   e Zd ZdZdd„ Zedd„ ƒZedd„ ƒZedd	„ ƒZed
d„ ƒZ	edd„ ƒZ
edd„ ƒZedd„ ƒZdS )ÚCanonicalConstrainta¯  Canonical constraint to use with trust-constr algorithm.

    It represents the set of constraints of the form::

        f_eq(x) = 0
        f_ineq(x) <= 0

    where ``f_eq`` and ``f_ineq`` are evaluated by a single function, see
    below.

    The class is supposed to be instantiated by factory methods, which
    should prepare the parameters listed below.

    Parameters
    ----------
    n_eq, n_ineq : int
        Number of equality and inequality constraints respectively.
    fun : callable
        Function defining the constraints. The signature is
        ``fun(x) -> c_eq, c_ineq``, where ``c_eq`` is ndarray with `n_eq`
        components and ``c_ineq`` is ndarray with `n_ineq` components.
    jac : callable
        Function to evaluate the Jacobian of the constraint. The signature
        is ``jac(x) -> J_eq, J_ineq``, where ``J_eq`` and ``J_ineq`` are
        either ndarray of csr_matrix of shapes (n_eq, n) and (n_ineq, n),
        respectively.
    hess : callable
        Function to evaluate the Hessian of the constraints multiplied
        by Lagrange multipliers, that is
        ``dot(f_eq, v_eq) + dot(f_ineq, v_ineq)``. The signature is
        ``hess(x, v_eq, v_ineq) -> H``, where ``H`` has an implied
        shape (n, n) and provide a matrix-vector product operation
        ``H.dot(p)``.
    keep_feasible : ndarray, shape (n_ineq,)
        Mask indicating which inequality constraints should be kept feasible.
    c                 C   s(   || _ || _|| _|| _|| _|| _d S ©N)Ún_eqÚn_ineqÚfunÚjacÚhessÚkeep_feasible)Úselfr   r   r   r   r   r	   © r   úVlib/python3.9/site-packages/scipy/optimize/_trustregion_constr/canonical_constraint.pyÚ__init__*   s    zCanonicalConstraint.__init__c                 C   sÞ   |j \}}|j}|j}t |tj k¡rDt |tjk¡rD|  |j¡S t |tj k¡rrt |tjk¡rr|  |j¡S t ||k¡rŒ|  ||¡S t |tj k¡r¬|  	|||¡S t |tjk¡rÊ|  
|||¡S |  ||||¡S dS )z5Create an instance from `PreparedConstrained` object.N)Úboundsr   r	   ÚnpÚallÚinfÚemptyÚnÚ_equal_to_canonicalÚ_less_to_canonicalÚ_greater_to_canonicalÚ_interval_to_canonical)ÚclsZ
constraintÚlbÚubÚcfunr	   r   r   r   Úfrom_PreparedConstraint2   s    
""z+CanonicalConstraint.from_PreparedConstraintc              
      sh   t  d¡‰ t  d|f¡‰t ||f¡‰‡ fdd„}‡fdd„}‡fdd„}| dd|||t jdt jdƒS )	z¦Create an "empty" instance.

        This "empty" instance is required to allow working with unconstrained
        problems as if they have some constraints.
        r   c                    s   ˆ ˆ fS r   r   ©Úx)Ú	empty_funr   r   r   R   s    z&CanonicalConstraint.empty.<locals>.func                    s   ˆ ˆ fS r   r   r   )Ú	empty_jacr   r   r   U   s    z&CanonicalConstraint.empty.<locals>.jacc                    s   ˆ S r   r   ©r   Úv_eqÚv_ineq)Ú
empty_hessr   r   r   X   s    z'CanonicalConstraint.empty.<locals>.hess©Zdtype)r   r   ÚspsÚ
csr_matrixZbool_)r   r   r   r   r   r   )r   r$   r    r   r   G   s    
zCanonicalConstraint.emptyc           	         s‚   ‡ fdd„}|rt j‰ntj‰‡ ‡fdd„}‡ fdd„}tdd„ ˆ D ƒƒ}td	d„ ˆ D ƒƒ}t d
d„ ˆ D ƒ¡}| ||||||ƒS )a  Concatenate multiple `CanonicalConstraint` into one.

        `sparse_jacobian` (bool) determines the Jacobian format of the
        concatenated constraint. Note that items in `canonical_constraints`
        must have their Jacobians in the same format.
        c                    s>   ˆr t ‡ fdd„ˆD ƒŽ \}}n
g g  }}t |¡t |¡fS )Nc                    s   g | ]}|  ˆ ¡‘qS r   ©r   ©Ú.0Úcr   r   r   Ú
<listcomp>h   ó    z@CanonicalConstraint.concatenate.<locals>.fun.<locals>.<listcomp>)Úzipr   Úhstack©r   Zeq_allZineq_all©Úcanonical_constraintsr   r   r   e   s    ÿ

z,CanonicalConstraint.concatenate.<locals>.func                    s:   ˆr t ‡ fdd„ˆD ƒŽ \}}n
g g  }}ˆ|ƒˆ|ƒfS )Nc                    s   g | ]}|  ˆ ¡‘qS r   ©r   r)   r   r   r   r,   v   r-   z@CanonicalConstraint.concatenate.<locals>.jac.<locals>.<listcomp>)r.   r0   ©r2   Úvstackr   r   r   s   s    ÿ

z,CanonicalConstraint.concatenate.<locals>.jacc           
         sŽ   g ‰ d}d}ˆD ]P}||||j  … }||||j … }ˆ  | | ||¡¡ ||j 7 }||j7 }q‡ fdd„}| jd }	tjj|	|	f|tdS )Nr   c                    s&   t  | ¡}ˆ D ]}|| | ¡7 }q|S r   )r   Ú
zeros_likeÚdot)ÚpÚresultÚh©Zhess_allr   r   Úmatvec‡   s    
z=CanonicalConstraint.concatenate.<locals>.hess.<locals>.matvecr%   )	r   r   Úappendr   Úshaper&   ZlinalgZLinearOperatorÚfloat)
r   r"   r#   Zindex_eqZ
index_ineqr+   Zvc_eqZvc_ineqr<   r   r1   r;   r   r   |   s    

z-CanonicalConstraint.concatenate.<locals>.hessc                 s   s   | ]}|j V  qd S r   )r   r)   r   r   r   Ú	<genexpr>   r-   z2CanonicalConstraint.concatenate.<locals>.<genexpr>c                 s   s   | ]}|j V  qd S r   )r   r)   r   r   r   r@   ‘   r-   c                 S   s   g | ]
}|j ‘qS r   )r	   r)   r   r   r   r,   ’   r-   z3CanonicalConstraint.concatenate.<locals>.<listcomp>)r&   r5   r   Úsumr/   )	r   r2   Úsparse_jacobianr   r   r   r   r   r	   r   r4   r   Úconcatenate]   s    		
ÿzCanonicalConstraint.concatenatec           
         sÀ   t  d¡‰ˆ j}ˆjd }d}t jdtd}ˆ jrBt d|f¡‰nt  d|f¡‰‡ ‡‡fdd„}‡ ‡fdd„}‡ fdd„}	t  d¡‰ˆ j}ˆ jr t d|f¡‰nt  d|f¡‰| |||||	|ƒS )	Nr   r%   c                    s   ˆ   | ¡ˆ ˆfS r   r(   r   )r   r   Úvaluer   r   r   ¥   s    z4CanonicalConstraint._equal_to_canonical.<locals>.func                    s   ˆ   | ¡ˆfS r   r3   r   ©r   r    r   r   r   ¨   s    z4CanonicalConstraint._equal_to_canonical.<locals>.jacc                    s   ˆ   | |¡S r   ©r   r!   ©r   r   r   r   «   s    z5CanonicalConstraint._equal_to_canonical.<locals>.hess)r   r   r   r>   ÚboolrB   r&   r'   )
r   r   rD   r   r   r   r	   r   r   r   r   )r   r   r    rD   r   r   —   s"    


z'CanonicalConstraint._equal_to_canonicalc           
         sâ   t  d¡‰ˆ j}ˆ jr&t d|f¡‰nt  d|f¡‰ˆt jk ‰d}t  ˆ¡}t  ˆ¡r‚‡ ‡‡fdd„}‡ ‡fdd„}‡ fdd„}	nNt  	ˆ¡d ‰|ˆ }ˆˆ ‰‡ ‡‡‡fdd„}‡ ‡‡fd	d„}‡ ‡fd
d„}	| |||||	|ƒS )Nr   c                    s   ˆˆ   | ¡ˆ fS r   r(   r   )r   r   r   r   r   r   Å   s    z3CanonicalConstraint._less_to_canonical.<locals>.func                    s   ˆˆ   | ¡fS r   r3   r   rE   r   r   r   È   s    z3CanonicalConstraint._less_to_canonical.<locals>.jacc                    s   ˆ   | |¡S r   rF   r!   rG   r   r   r   Ë   s    z4CanonicalConstraint._less_to_canonical.<locals>.hessc                    s   ˆˆ   | ¡ˆ ˆ fS r   r(   r   )r   r   Ú	finite_ubr   r   r   r   Ò   s    c                    s   ˆˆ   | ¡ˆ fS r   r3   r   )r   r    rI   r   r   r   Õ   s    c                    s    t  ˆ j¡}||ˆ< ˆ  | |¡S r   ©r   ZzerosÚmr   ©r   r"   r#   Úv)r   rI   r   r   r   Ø   s    ©
r   r   r   rB   r&   r'   r   rA   r   Únonzero)
r   r   r   r	   r   r   r   r   r   r   r   )r   r   r    rI   r   r   r   ·   s&    



z&CanonicalConstraint._less_to_canonicalc           
         sä   t  d¡‰ˆ j}ˆ jr&t d|f¡‰nt  d|f¡‰ˆt j k‰d}t  ˆ¡}t  ˆ¡r„‡ ‡‡fdd„}‡ ‡fdd„}‡ fdd„}	nNt  	ˆ¡d ‰|ˆ }ˆˆ ‰‡ ‡‡‡fdd„}‡ ‡‡fd	d„}‡ ‡fd
d„}	| |||||	|ƒS )Nr   c                    s   ˆˆˆ   | ¡ fS r   r(   r   )r   r   r   r   r   r   í   s    z6CanonicalConstraint._greater_to_canonical.<locals>.func                    s   ˆˆ   | ¡ fS r   r3   r   rE   r   r   r   ð   s    z6CanonicalConstraint._greater_to_canonical.<locals>.jacc                    s   ˆ   | | ¡S r   rF   r!   rG   r   r   r   ó   s    z7CanonicalConstraint._greater_to_canonical.<locals>.hessc                    s   ˆˆˆ   | ¡ˆ  fS r   r(   r   )r   r   Ú	finite_lbr   r   r   r   ú   s    c                    s   ˆˆ   | ¡ˆ  fS r   r3   r   )r   r    rP   r   r   r   ý   s    c                    s"   t  ˆ j¡}| |ˆ< ˆ  | |¡S r   rJ   rL   )r   rP   r   r   r      s    
rN   )
r   r   r   r	   r   r   r   r   r   r   r   )r   r   r    rP   r   r   r   ß   s&    


z)CanonicalConstraint._greater_to_canonicalc              	      s0  ˆt j k}ˆ	t jk}ˆˆ	k‰|| @ ‰|| @ ‰ˆ | @ | @ ‰t  ˆ¡d ‰t  ˆ¡d ‰t  ˆ¡d ‰t  ˆ¡d ‰ˆjd ‰ˆjd ‰ˆjd ‰ˆˆ dˆ  }ˆjd }t  |ˆ |ˆ |ˆ |ˆ f¡}‡ ‡‡‡‡‡‡	fdd„}	‡ ‡‡‡‡fdd„}
‡ ‡‡‡‡‡‡‡‡f	dd„}| |||	|
||ƒS )	Nr   é   c                    sp   ˆ   | ¡}|ˆ ˆˆ  }|ˆ ˆˆ  }ˆˆ |ˆ  }|ˆ ˆˆ  }ˆˆ |ˆ  }|t ||||f¡fS r   )r   r   r/   )r   ÚfÚeqÚleÚgeÚilÚig)r   ÚequalÚgreaterÚintervalr   Úlessr   r   r   r     s    
z7CanonicalConstraint._interval_to_canonical.<locals>.func                    sj   ˆ   | ¡}|ˆ }|ˆ }|ˆ  }|ˆ }| }t |¡rPt ||||f¡}nt ||||f¡}||fS r   )r   r&   Zissparser5   r   )r   ÚJrS   rT   rU   rV   rW   Zineq)r   rX   rY   rZ   r[   r   r   r   (  s    


z7CanonicalConstraint._interval_to_canonical.<locals>.jacc           	         s˜   d}|||ˆ … }|ˆ7 }|||ˆ … }|ˆ7 }|||ˆ … }|ˆ7 }|||ˆ … }t  ˆ¡}||ˆ< ||ˆ< | |ˆ< || |ˆ< ˆ  | |¡S )Nr   )r   r6   r   )	r   r"   r#   Zn_startZv_lZv_gZv_ilZv_igrM   )	r   rX   rY   rZ   r   r[   Ú	n_greaterÚ
n_intervalÚn_lessr   r   r   5  s    

z8CanonicalConstraint._interval_to_canonical.<locals>.hess)r   r   rO   r>   r/   )r   r   r   r   r	   Úlb_infÚub_infr   r   r   r   r   r   )
r   rX   rY   rZ   r   r[   r]   r^   r_   r   r   r     s0    







ý	z*CanonicalConstraint._interval_to_canonicalN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Úclassmethodr   r   rC   r   r   r   r   r   r   r   r   r      s    $


9

'
'r   c                 C   st  g }g }g }g }|D ]È}|j j}|j j}	|j\}
}t |
|k¡r\| ||
 ¡ | |	¡ qt |
tj k¡rž|tjk }| || ||  ¡ | |	| ¡ qt |tjk¡râ|
tj k}| |
| ||  ¡ | |	|  ¡ q|
tj k}|tjk}|
|k}|| @ }|| @ }| | @ | @ }| || |
|  ¡ | || ||  ¡ | |
| ||  ¡ | || ||  ¡ | |
| ||  ¡ | |	| ¡ | |	| ¡ | |	|  ¡ | |	| ¡ | |	|  ¡ q|rðt |¡nt 	d¡}|r
t |¡nt 	d¡}|r0t
j}t
 d| f¡}ntj}t 	d| f¡}|rR||ƒn|}|rd||ƒn|}||||fS )a  Convert initial values of the constraints to the canonical format.

    The purpose to avoid one additional call to the constraints at the initial
    point. It takes saved values in `PreparedConstraint`, modififies and
    concatenates them to the the canonical constraint format.
    r   )r   rR   r\   r   r   r   r=   r   r/   r   r&   r5   r'   )r   Zprepared_constraintsrB   Zc_eqZc_ineqZJ_eqZJ_ineqr+   rR   r\   r   r   rI   rP   r`   ra   rX   r[   rY   rZ   r5   r   r   r   r   Ú initial_constraints_as_canonicalJ  sZ    





rg   )Znumpyr   Zscipy.sparseZsparser&   r   rg   r   r   r   r   Ú<module>   s
     G