#NEWLINE# def solve( self , trust_radius ) : #NEWLINE# #INDENT# '\n        Solve the subproblem using a conjugate gradient method.\n\n        Parameters\n        ----------\n        trust_radius : float\n            We are allowed to wander only this far away from the origin.\n\n        Returns\n        -------\n        p : ndarray\n            The proposed step.\n        hits_boundary : bool\n            True if the proposed step is on the boundary of the trust region.\n\n        Notes\n        -----\n        This is algorithm (7.2) of Nocedal and Wright 2nd edition.\n        Only the function that computes the Hessian-vector product is required.\n        The Hessian itself is not required, and the Hessian does\n        not need to be positive semidefinite.\n        ' #NEWLINE# p_origin = np . zeros_like ( self . jac ) #NEWLINE# tolerance = ( min ( 0.5 , math . sqrt ( self . jac_mag ) ) * self . jac_mag ) #NEWLINE# if ( self . jac_mag < tolerance ) : #NEWLINE# #INDENT# hits_boundary = False #NEWLINE# return ( p_origin , hits_boundary ) #NEWLINE# #UNINDENT# z = p_origin #NEWLINE# r = self . jac #NEWLINE# d = ( - r ) #NEWLINE# while True : #NEWLINE# #INDENT# Bd = self . hessp ( d ) #NEWLINE# dBd = np . dot ( d , Bd ) #NEWLINE# if ( dBd <= 0 ) : #NEWLINE# #INDENT# ( ta , tb ) = self . get_boundaries_intersections ( z , d , trust_radius ) #NEWLINE# pa = ( z + ( ta * d ) ) #NEWLINE# pb = ( z + ( tb * d ) ) #NEWLINE# if ( self ( pa ) < self ( pb ) ) : #NEWLINE# #INDENT# p_boundary = pa #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# p_boundary = pb #NEWLINE# #UNINDENT# hits_boundary = True #NEWLINE# return ( p_boundary , hits_boundary ) #NEWLINE# #UNINDENT# r_squared = np . dot ( r , r ) #NEWLINE# alpha = ( r_squared / dBd ) #NEWLINE# z_next = ( z + ( alpha * d ) ) #NEWLINE# if ( scipy . linalg . norm ( z_next ) >= trust_radius ) : #NEWLINE# #INDENT# ( ta , tb ) = self . get_boundaries_intersections ( z , d , trust_radius ) #NEWLINE# p_boundary = ( z + ( tb * d ) ) #NEWLINE# hits_boundary = True #NEWLINE# return ( p_boundary , hits_boundary ) #NEWLINE# #UNINDENT# r_next = ( r + ( alpha * Bd ) ) #NEWLINE# r_next_squared = np . dot ( r_next , r_next ) #NEWLINE# if ( math . sqrt ( r_next_squared ) < tolerance ) : #NEWLINE# #INDENT# hits_boundary = False #NEWLINE# return ( z_next , hits_boundary ) #NEWLINE# #UNINDENT# beta_next = ( r_next_squared / r_squared ) #NEWLINE# d_next = ( ( - r_next ) + ( beta_next * d ) ) #NEWLINE# z = z_next #NEWLINE# r = r_next #NEWLINE# d = d_next