o
    5ήc5                     @   sP   d Z ddlmZ ddlZddlmZ ddlmZ dgZ	G dd dZ
d	d ZdS )
a  Trust-region interior point method.

References
----------
.. [1] Byrd, Richard H., Mary E. Hribar, and Jorge Nocedal.
       "An interior point algorithm for large-scale nonlinear
       programming." SIAM Journal on Optimization 9.4 (1999): 877-900.
.. [2] Byrd, Richard H., Guanghui Liu, and Jorge Nocedal.
       "On the local behavior of an interior point method for
       nonlinear programming." Numerical analysis 1997 (1997): 37-56.
.. [3] Nocedal, Jorge, and Stephen J. Wright. "Numerical optimization"
       Second Edition (2006).
    N   )equality_constrained_sqp)LinearOperatortr_interior_pointc                   @   s   e Zd Z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d Zdd Zdd Zdd Zdd Zdd Zd d! Zd"S )#BarrierSubproblemz
    Barrier optimization problem:
        minimize fun(x) - barrier_parameter*sum(log(s))
        subject to: constr_eq(x)     = 0
                  constr_ineq(x) + s = 0
    c                 C   s   || _ || _|| _|| _|| _|| _|	| _|
| _|| _|| _	|| _
|| _|| _|| _|| _| |||| _| || _| |||| _| |||| _d| _d S )NF)n_varsx0s0fungrad	lagr_hessconstrjacbarrier_parameter	tolerancen_eqn_ineqenforce_feasibilityglobal_stop_criteriaxtol_compute_functionfun0_compute_gradientgrad0_compute_constrconstr0_compute_jacobianjac0	terminate)selfr   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   constr_ineq0	jac_ineq0
constr_eq0jac_eq0 r$   [/tmp/pip-target-vg8gfxp4/lib/python/scipy/optimize/_trustregion_constr/tr_interior_point.py__init__   s(   
zBarrierSubproblem.__init__c                 C   s   || _ || _d S N)r   r   )r   r   r   r$   r$   r%   update:   s   
zBarrierSubproblem.updatec                 C   s   || j | j | j  S r'   )r   r   r   zr$   r$   r%   	get_slack>   s   zBarrierSubproblem.get_slackc                 C   s   |d | j  S r'   )r   r)   r$   r$   r%   get_variablesA   s   zBarrierSubproblem.get_variablesc                 C   sH   |  |}| |}| |}| |\}}| |||| |||fS )a?  Returns barrier function and constraints at given point.

        For z = [x, s], returns barrier function:
            function(z) = fun(x) - barrier_parameter*sum(log(s))
        and barrier constraints:
            constraints(z) = [   constr_eq(x)     ]
                             [ constr_ineq(x) + s ]

        )r,   r+   r
   r   r   r   )r   r*   xsfc_eqc_ineqr$   r$   r%   function_and_constraintsD   s   


z*BarrierSubproblem.function_and_constraintsc                 C   s4   || j   || j < dd |D }|| jt|  S )Nc                 S   s&   g | ]}|d krt |nt j qS )r   )nploginf).0s_ir$   r$   r%   
<listcomp>]   s   & z7BarrierSubproblem._compute_function.<locals>.<listcomp>)r   r   r3   sum)r   r/   r1   r.   log_sr$   r$   r%   r   X   s   z#BarrierSubproblem._compute_functionc                 C   s   t ||| fS r'   )r3   hstack)r   r1   r0   r.   r$   r$   r%   r   a   s   z!BarrierSubproblem._compute_constrc                    sJ   |  |}tt| j|f  fdd}t| j| j | j| j f|S )zZReturns scaling vector.
        Given by:
            scaling = [ones(n_vars), s]
        c                    s    |  S r'   r$   )vecdiag_elementsr$   r%   matveco   s   z)BarrierSubproblem.scaling.<locals>.matvec)r+   r3   r;   onesr   r   r   )r   r*   r.   r?   r$   r=   r%   scalingf   s   

zBarrierSubproblem.scalingc                 C   sD   |  |}| |}| |}| |\}}| || |||fS )av  Returns scaled gradient.

        Return scaled gradient:
            gradient = [             grad(x)             ]
                       [ -barrier_parameter*ones(n_ineq) ]
        and scaled Jacobian matrix:
            jacobian = [  jac_eq(x)  0  ]
                       [ jac_ineq(x) S  ]
        Both of them scaled by the previously defined scaling factor.
        )r,   r+   r   r   r   r   )r   r*   r-   r.   gJ_eqJ_ineqr$   r$   r%   gradient_and_jacobianu   s   


z'BarrierSubproblem.gradient_and_jacobianc                 C   s   t || j t | j fS r'   )r3   r;   r   r@   r   )r   rB   r$   r$   r%   r      s   z#BarrierSubproblem._compute_gradientc                 C   s   | j dkr|S t|st|r"t|}t|}| |||S t|}t| j| j f}t|r9|	 }t|rB|	 }t
||g||ggS Nr   )r   spsissparse
csr_matrix_assemble_sparse_jacobianr3   diagzerosr   toarrayblock)r   rC   rD   r.   SrL   r$   r$   r%   r      s   






z#BarrierSubproblem._compute_jacobianc                 C   s   | j | j| j}}}t||gd}|j|j|j}}	}
|t	tj
|tdtj|d tdf }|	j| }t|}t|}t|dt}d||| d d < |t| ||< |	|| < |||< |
|| < t|||f|| || f}|S )a  Assemble sparse Jacobian given its components.

        Given ``J_eq``, ``J_ineq`` and ``s`` returns:
            jacobian = [ J_eq,     0     ]
                       [ J_ineq, diag(s) ]

        It is equivalent to:
            sps.bmat([[ J_eq,   None    ],
                      [ J_ineq, diag(s) ]], "csr")
        but significantly more efficient for this
        given structure.
        csr)dtyper   FTN)r   r   r   rG   vstackindptrindicesdatar3   r;   rL   intarangesizeemptyfullboolrI   )r   rC   rD   r.   r   r   r   J_auxrS   rT   rU   
new_indptrrX   new_indicesnew_datamaskJr$   r$   r%   rJ      s&   




z+BarrierSubproblem._assemble_sparse_jacobianc                 C   s@   |  |}|d| j }|| j| j| j  }| j}||||S )z5Returns Lagrangian Hessian (in relation to `x`) -> HxN)r,   r   r   r   )r   r*   vr-   v_eqv_ineqr   r$   r$   r%   lagrangian_hessian_x   s
   
z&BarrierSubproblem.lagrangian_hessian_xc                 C   sB   |  |}| j}|| j d | }t|| j d dk||S )z?Returns scaled Lagrangian Hessian (in relation to`s`) -> S Hs SNr   )r+   r   r   r3   where)r   r*   rb   r.   primalprimal_dualr$   r$   r%   lagrangian_hessian_s   s   
z&BarrierSubproblem.lagrangian_hessian_sc                    sP    || jdkr|| fdd}tjj jj f|S )z!Returns scaled Lagrangian Hessianr   c                    s@    | }| }jdkrt || fS  |S rF   )r,   r+   r   r3   r;   dot)r<   vec_xvec_sHxS_Hs_Sr   r$   r%   r?      s
   



z4BarrierSubproblem.lagrangian_hessian.<locals>.matvec)re   r   ri   r   r   )r   r*   rb   r?   r$   rm   r%   lagrangian_hessian   s   

z$BarrierSubproblem.lagrangian_hessianc	              
   C   sV   |  |}	| ||	||||| j| jrd| _dS || jk o!|| jk }
|| jk }|
p*|S )zStop criteria to the barrier problem.
        The criteria here proposed is similar to formula (2.3)
        from [1]_, p.879.
        T)r,   r   r   r   r   r   )r   stater*   last_iteration_failed
optimalityconstr_violationtrust_radiuspenaltycg_infor-   g_condx_condr$   r$   r%   stop_criteria   s   


zBarrierSubproblem.stop_criteriaN)__name__
__module____qualname____doc__r&   r(   r+   r,   r2   r   r   rA   rE   r   r   rJ   re   ri   rp   rz   r$   r$   r$   r%   r      s$    	
r   c           (      C   st  d}d}d}|du rt |t}|}|}|}t d| t |}t||| |||||||||||||	|
||||}t ||f} |j|j}!}"|j	|j
}#}$t t |jt j t |j| f}%t |j|j t j}&	 t|j|j|j| |!|#|"|$|j|||||%|&|j\} }|jrn%t|||j }||9 }||9 }||| || \}!}"|| \}#}$qn|| }'|'|fS )zTrust-region interior points method.

    Solve problem:
        minimize fun(x)
        subject to: constr_ineq(x) <= 0
                    constr_eq(x) = 0
    using trust-region interior point method described in [1]_.
    gףp=
?g?   Ng      )r3   rL   r[   maximumr@   r   r;   r   r   r   r   rZ   r   r5   r   r   r2   rE   rp   rz   rA   r   max	tr_radiusr(   r,   )(r
   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   rz   r   r   rq   initial_barrier_parameterinitial_toleranceinitial_penaltyinitial_trust_radiusfactorization_methodBOUNDARY_PARAMETERBARRIER_DECAY_RATIOTRUST_ENLARGEMENTr   r   ru   r	   subprobr*   fun0_subprobconstr0_subprobgrad0_subprobjac0_subprobtrust_lbtrust_ubr-   r$   r$   r%   r   
  sZ   

)r~   scipy.sparsesparserG   numpyr3   r   scipy.sparse.linalgr   __all__r   r   r$   r$   r$   r%   <module>   s     t