'Minimize a function using the dog-leg trust-region algorithm.
This algorithm requires function values and first and second derivatives.
It also performs a costly Hessian decomposition for most iterations,
and the Hessian is required to be positive definite.
Parameters
trust_radius : float
We are allowed to wander only this far away from the origin.
Returns
p : ndarray
The proposed step.
hits_boundary : bool
True if the proposed step is on the boundary of the trust region.
Notes
The Hessian is required to be positive definite.
References
.. [1] Jorge Nocedal and Stephen Wright,
Numerical Optimization, second edition,
Springer-Verlag, 2006, page 73.'

def solve(self, trust_radius):

    p_best = self.newton_point()
    if (scipy.linalg.norm(p_best) < trust_radius):
        hits_boundary = False
        return (p_best, hits_boundary)
    p_u = self.cauchy_point()
    p_u_norm = scipy.linalg.norm(p_u)
    if (p_u_norm >= trust_radius):
        p_boundary = (p_u * (trust_radius / p_u_norm))
        hits_boundary = True
        return (p_boundary, hits_boundary)
    (_, tb) = self.get_boundaries_intersections(p_u, (p_best - p_u), trust_radius)
    p_boundary = (p_u + (tb * (p_best - p_u)))
    hits_boundary = True
    return (p_boundary, hits_boundary)
