U
    ?h0                     @   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   i/var/www/html/venv/lib/python3.8/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)cls
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 )	zCreate 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   s     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   s     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>   s     z2CanonicalConstraint.concatenate.<locals>.<genexpr>c                 s   s   | ]}|j V  qd S r   )r   r*   r   r   r   r@      s     c                 S   s   g | ]
}|j qS r   )r	   r*   r   r   r   r-      s     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rt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'   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|rt|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 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   ra   rb   rX   r[   rY   rZ   r5   r   r   r   r    initial_constraints_as_canonicalJ  sZ    





rh   )numpyr   Zscipy.sparsesparser'   r   rh   r   r   r   r   <module>   s
     G