o
    5ήcDX                     @   s   d Z ddlmZmZmZ ddlmZ ddlZddl	m
Z
 g dZdd Z		dd
dZ		dddZ				dddZdd Zdd Zdd Zejdddddd	fddZdS )z3Equality-constrained quadratic programming solvers.    )linalgbmat
csc_matrix)copysignN)norm)eqp_kktfactsphere_intersectionsbox_intersectionsbox_sphere_intersectionsinside_box_boundariesmodified_doglegprojected_cgc                 C   s~   t |\}t |\}tt| |jg|dgg}t | | g}t|}||}	|	d| }
|	|||   }|
|fS )a  Solve equality-constrained quadratic programming (EQP) problem.

    Solve ``min 1/2 x.T H x + x.t c`` subject to ``A x + b = 0``
    using direct factorization of the KKT system.

    Parameters
    ----------
    H : sparse matrix, shape (n, n)
        Hessian matrix of the EQP problem.
    c : array_like, shape (n,)
        Gradient of the quadratic objective function.
    A : sparse matrix
        Jacobian matrix of the EQP problem.
    b : array_like, shape (m,)
        Right-hand side of the constraint equation.

    Returns
    -------
    x : array_like, shape (n,)
        Solution of the KKT problem.
    lagrange_multipliers : ndarray, shape (m,)
        Lagrange multipliers of the KKT problem.
    N)	npshaper   r   Thstackr   splusolve)HcAbnm
kkt_matrixkkt_veclukkt_solxlagrange_multipliers r    W/tmp/pip-target-vg8gfxp4/lib/python/scipy/optimize/_trustregion_constr/qp_subproblem.pyr      s   

r   Fc                 C   s*  t |dkrdS t|r"|rtj }tj}nd}d}d}|||fS t||}dt| | }t| | |d  }	|| d| |	  }
|
dk rOd}dd|fS t|
}|t|| }| d|  }d|	 | }t||g\}}|rud}n|dk s}|dkrd}d}d}nd}td|}t	d|}|||fS )	aH  Find the intersection between segment (or line) and spherical constraints.

    Find the intersection between the segment (or line) defined by the
    parametric  equation ``x(t) = z + t*d`` and the ball
    ``||x|| <= trust_radius``.

    Parameters
    ----------
    z : array_like, shape (n,)
        Initial point.
    d : array_like, shape (n,)
        Direction.
    trust_radius : float
        Ball radius.
    entire_line : bool, optional
        When ``True``, the function returns the intersection between the line
        ``x(t) = z + t*d`` (``t`` can assume any value) and the ball
        ``||x|| <= trust_radius``. When ``False``, the function returns the intersection
        between the segment ``x(t) = z + t*d``, ``0 <= t <= 1``, and the ball.

    Returns
    -------
    ta, tb : float
        The line/segment ``x(t) = z + t*d`` is inside the ball for
        for ``ta <= t <= tb``.
    intersect : bool
        When ``True``, there is a intersection between the line/segment
        and the sphere. On the other hand, when ``False``, there is no
        intersection.
    r   r   r   F   T      F)
r   r   isinfinfdotsqrtr   sortedmaxmin)zdtrust_radiusentire_linetatb	intersectar   r   discriminantsqrt_discriminantauxr    r    r!   r   A   s@   !



	


r   c                 C   s*  t | } t |}t |}t |}t|dkrdS |dk}| | || k  s4| | || k r;d}dd|fS t |}| | } || }|| }|| }||  | }||  | }	tt ||	}
tt ||	}|
|krsd}nd}|s|dk s|
dkrd}d}
d}n
td|
}
td|}|
||fS )a5  Find the intersection between segment (or line) and box constraints.

    Find the intersection between the segment (or line) defined by the
    parametric  equation ``x(t) = z + t*d`` and the rectangular box
    ``lb <= x <= ub``.

    Parameters
    ----------
    z : array_like, shape (n,)
        Initial point.
    d : array_like, shape (n,)
        Direction.
    lb : array_like, shape (n,)
        Lower bounds to each one of the components of ``x``. Used
        to delimit the rectangular box.
    ub : array_like, shape (n, )
        Upper bounds to each one of the components of ``x``. Used
        to delimit the rectangular box.
    entire_line : bool, optional
        When ``True``, the function returns the intersection between the line
        ``x(t) = z + t*d`` (``t`` can assume any value) and the rectangular
        box. When ``False``, the function returns the intersection between the segment
        ``x(t) = z + t*d``, ``0 <= t <= 1``, and the rectangular box.

    Returns
    -------
    ta, tb : float
        The line/segment ``x(t) = z + t*d`` is inside the box for
        for ``ta <= t <= tb``.
    intersect : bool
        When ``True``, there is a intersection between the line (or segment)
        and the rectangular box. On the other hand, when ``False``, there is no
        intersection.
    r   r"   FTr#   )	r   asarrayr   anylogical_notr,   minimumr-   maximum)r.   r/   lbubr1   zero_dr4   
not_zero_dt_lbt_ubr2   r3   r    r    r!   r	      s<   
%


(




r	   c                 C   s   t | ||||\}}}	t| |||\}
}}t||
}t||}|	r,|r,||kr,d}nd}|rC|
||d}|||	d}|||||fS |||fS )a  Find the intersection between segment (or line) and box/sphere constraints.

    Find the intersection between the segment (or line) defined by the
    parametric  equation ``x(t) = z + t*d``, the rectangular box
    ``lb <= x <= ub`` and the ball ``||x|| <= trust_radius``.

    Parameters
    ----------
    z : array_like, shape (n,)
        Initial point.
    d : array_like, shape (n,)
        Direction.
    lb : array_like, shape (n,)
        Lower bounds to each one of the components of ``x``. Used
        to delimit the rectangular box.
    ub : array_like, shape (n, )
        Upper bounds to each one of the components of ``x``. Used
        to delimit the rectangular box.
    trust_radius : float
        Ball radius.
    entire_line : bool, optional
        When ``True``, the function returns the intersection between the line
        ``x(t) = z + t*d`` (``t`` can assume any value) and the constraints.
        When ``False``, the function returns the intersection between the segment
        ``x(t) = z + t*d``, ``0 <= t <= 1`` and the constraints.
    extra_info : bool, optional
        When ``True``, the function returns ``intersect_sphere`` and ``intersect_box``.

    Returns
    -------
    ta, tb : float
        The line/segment ``x(t) = z + t*d`` is inside the rectangular box and
        inside the ball for for ``ta <= t <= tb``.
    intersect : bool
        When ``True``, there is a intersection between the line (or segment)
        and both constraints. On the other hand, when ``False``, there is no
        intersection.
    sphere_info : dict, optional
        Dictionary ``{ta, tb, intersect}`` containing the interval ``[ta, tb]``
        for which the line intercepts the ball. And a boolean value indicating
        whether the sphere is intersected by the line.
    box_info : dict, optional
        Dictionary ``{ta, tb, intersect}`` containing the interval ``[ta, tb]``
        for which the line intercepts the box. And a boolean value indicating
        whether the box is intersected by the line.
    TF)r2   r3   r4   )r	   r   r   r=   r<   )r.   r/   r>   r?   r0   r1   
extra_infota_btb_bintersect_bta_stb_sintersect_sr2   r3   r4   sphere_infobox_infor    r    r!   r
      s"   
1


r
   c                 C   s   || k  o| |k  S )zCheck if lb <= x <= ub.)allr   r>   r?   r    r    r!   r   1  s   r   c                 C   s   t t | ||S )zReturn clipped value of x)r   r<   r=   rN   r    r    r!   reinforce_box_boundaries6  s   rO   c                 C   s  | | }t|||rt||kr|}|S | j |}|  |}	t || t |	|	 | }
t|
}|
}||
 }t|||||\}}}|rO|||  }n|}|
}t|||||\}}}|||  }|}|}t|||||\}}}|||  }t|  || t|  || k r|S |S )aA  Approximately  minimize ``1/2*|| A x + b ||^2`` inside trust-region.

    Approximately solve the problem of minimizing ``1/2*|| A x + b ||^2``
    subject to ``||x|| < Delta`` and ``lb <= x <= ub`` using a modification
    of the classical dogleg approach.

    Parameters
    ----------
    A : LinearOperator (or sparse matrix or ndarray), shape (m, n)
        Matrix ``A`` in the minimization problem. It should have
        dimension ``(m, n)`` such that ``m < n``.
    Y : LinearOperator (or sparse matrix or ndarray), shape (n, m)
        LinearOperator that apply the projection matrix
        ``Q = A.T inv(A A.T)`` to the vector. The obtained vector
        ``y = Q x`` being the minimum norm solution of ``A y = x``.
    b : array_like, shape (m,)
        Vector ``b``in the minimization problem.
    trust_radius: float
        Trust radius to be considered. Delimits a sphere boundary
        to the problem.
    lb : array_like, shape (n,)
        Lower bounds to each one of the components of ``x``.
        It is expected that ``lb <= 0``, otherwise the algorithm
        may fail. If ``lb[i] = -Inf``, the lower
        bound for the ith component is just ignored.
    ub : array_like, shape (n, )
        Upper bounds to each one of the components of ``x``.
        It is expected that ``ub >= 0``, otherwise the algorithm
        may fail. If ``ub[i] = Inf``, the upper bound for the ith
        component is just ignored.

    Returns
    -------
    x : array_like, shape (n,)
        Solution to the problem.

    Notes
    -----
    Based on implementations described in pp. 885-886 from [1]_.

    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.
    )r)   r   r   r   r   
zeros_liker
   )r   Yr   r0   r>   r?   newton_pointr   gA_gcauchy_pointorigin_pointr.   p_alphar4   x1x2r    r    r!   r   ;  s@   0








$r   c           (   	   C   sf  d}t |\}t |\}|| }|| || }||}| }|r+|g}| |}t|d }|t| }|dk rDtd||k r]dddd}|rY|| ||d< ||fS |du rpttd	t | d
| |}|du r|t 	|t j
 }|du rt 	|t j
}|	du r|| }	t|	|| }	|
du r|| }
d}d}d}t |}d}t|	D ]}||k rd} n|d7 }||}|dkrt |rtdt|||||dd\}} }!|!r|| |  }t|||}d}d} n|| } || |  }"t j|"|kr't|| | |||\}}#}!|!r||#|  |  }t|||}d}d} npt|"||r1d}n|d7 }|dkrZt|| | |||\}}#}!|!rZ||#|  |  }t|||}d}||
kra n6|ri||" || |  }$||$}%t|%d }&|&| }'|% |'|  }|"}|%}|%}t|d }| |}qt|||s|}d}|||d}|r||d< ||fS )a  Solve EQP problem with projected CG method.

    Solve equality-constrained quadratic programming problem
    ``min 1/2 x.T H x + x.t c``  subject to ``A x + b = 0`` and,
    possibly, to trust region constraints ``||x|| < trust_radius``
    and box constraints ``lb <= x <= ub``.

    Parameters
    ----------
    H : LinearOperator (or sparse matrix or ndarray), shape (n, n)
        Operator for computing ``H v``.
    c : array_like, shape (n,)
        Gradient of the quadratic objective function.
    Z : LinearOperator (or sparse matrix or ndarray), shape (n, n)
        Operator for projecting ``x`` into the null space of A.
    Y : LinearOperator,  sparse matrix, ndarray, shape (n, m)
        Operator that, for a given a vector ``b``, compute smallest
        norm solution of ``A x + b = 0``.
    b : array_like, shape (m,)
        Right-hand side of the constraint equation.
    trust_radius : float, optional
        Trust radius to be considered. By default, uses ``trust_radius=inf``,
        which means no trust radius at all.
    lb : array_like, shape (n,), optional
        Lower bounds to each one of the components of ``x``.
        If ``lb[i] = -Inf`` the lower bound for the i-th
        component is just ignored (default).
    ub : array_like, shape (n, ), optional
        Upper bounds to each one of the components of ``x``.
        If ``ub[i] = Inf`` the upper bound for the i-th
        component is just ignored (default).
    tol : float, optional
        Tolerance used to interrupt the algorithm.
    max_iter : int, optional
        Maximum algorithm iterations. Where ``max_inter <= n-m``.
        By default, uses ``max_iter = n-m``.
    max_infeasible_iter : int, optional
        Maximum infeasible (regarding box constraints) iterations the
        algorithm is allowed to take.
        By default, uses ``max_infeasible_iter = n-m``.
    return_all : bool, optional
        When ``true``, return the list of all vectors through the iterations.

    Returns
    -------
    x : array_like, shape (n,)
        Solution of the EQP problem.
    info : Dict
        Dictionary containing the following:

            - niter : Number of iterations.
            - stop_cond : Reason for algorithm termination:
                1. Iteration limit was reached;
                2. Reached the trust-region boundary;
                3. Negative curvature detected;
                4. Tolerance was satisfied.
            - allvecs : List containing all intermediary vectors (optional).
            - hits_boundary : True if the proposed step is on the boundary
              of the trust region.

    Notes
    -----
    Implementation of Algorithm 6.2 on [1]_.

    In the absence of spherical and box constraints, for sufficient
    iterations, the method returns a truly optimal result.
    In the presence of those constraints, the value returned is only
    a inexpensive approximation of the optimal value.

    References
    ----------
    .. [1] Gould, Nicholas IM, Mary E. Hribar, and Jorge Nocedal.
           "On the solution of equality constrained quadratic
            programming problems arising in optimization."
            SIAM Journal on Scientific Computing 23.4 (2001): 1376-1395.
    g}:r$   r   z.Trust region problem does not have a solution.T)niter	stop_condhits_boundaryallvecsNg{Gz?g?Fr#   r%   z9Negative curvature not allowed for unrestricted problems.)r1      )r   r   r)   r   
ValueErrorappendr,   r-   r*   fullr(   rP   ranger'   r
   rO   r   r   )(r   r   ZrQ   r   r0   r>   r?   tolmax_itermax_infeasible_iter
return_allCLOSE_TO_ZEROr   r   r   rrS   rW   r_   H_prt_gtr_distanceinfor^   r]   counterlast_feasible_xkipt_H_prX   rY   r4   x_nextthetar_nextg_next	rt_g_nextbetar    r    r!   r     s   P











r   )F)FF)__doc__scipy.sparser   r   r   mathr   numpyr   numpy.linalgr   __all__r   r   r	   r
   r   rO   r   r(   r   r    r    r    r!   <module>   s,    .
W
V
E`