//  [python]
def conjugate_gradient_delta_lambda(self,
                                        doc_lambda,
                                        doc_nu_square,
                                        doc_zeta_factor,
                                        sum_phi,
                                        total_word_count,

                                        conjugate_gradient_iteration=100,
                                        conjugate_gradient_threshold=1e-9,
                                        precondition_hessian_matrix=True
                                        ):
        # delta_doc_lambda = numpy.random.random(self._number_of_topics);
        delta_doc_lambda = numpy.zeros(self._number_of_topics);
        # delta_doc_lambda = numpy.ones(self._number_of_topics);

        if precondition_hessian_matrix:
            hessian_lambda = self.second_derivative_lambda(doc_lambda, doc_nu_square, doc_zeta_factor,
                                                           total_word_count);
            if not numpy.all(numpy.isfinite(hessian_lambda)):
                return numpy.zeros(self._number_of_topics);
            M_inverse = 1.0 / numpy.diag(hessian_lambda);
        # print numpy.linalg.cond(hessian_lambda), ">>>", numpy.linalg.cond(numpy.dot(numpy.diag(1.0/numpy.diag(hessian_lambda)), hessian_lambda)), ">>>", numpy.linalg.cond(numpy.dot(numpy.linalg.cholesky(hessian_lambda), hessian_lambda));

        r_vector = -self.first_derivative_lambda(doc_lambda, doc_nu_square, doc_zeta_factor, sum_phi, total_word_count);
        r_vector -= self.hessian_damping_direction_approximation_lambda(doc_lambda, doc_nu_square, doc_zeta_factor,
                                                                        sum_phi, total_word_count, delta_doc_lambda)

        if precondition_hessian_matrix:
            z_vector = M_inverse * r_vector;
        else:
            z_vector = numpy.copy(r_vector);

        p_vector = numpy.copy(z_vector);
        r_z_vector_square_old = numpy.sum(r_vector * z_vector);

        for conjugate_gradient_iteration_index in range(conjugate_gradient_iteration):
            # hessian_p_vector = self.hessian_direction_approximation_lambda(doc_lambda, doc_nu_square, doc_zeta_factor, total_word_count, p_vector);
            hessian_p_vector = self.hessian_damping_direction_approximation_lambda(doc_lambda, doc_nu_square,
                                                                                   doc_zeta_factor, sum_phi,
                                                                                   total_word_count, p_vector);

            alpha_value = r_z_vector_square_old / numpy.sum(p_vector * hessian_p_vector);

            delta_doc_lambda += alpha_value * p_vector;

            r_vector -= alpha_value * hessian_p_vector;

            if numpy.sqrt(numpy.sum(r_vector ** 2)) <= conjugate_gradient_threshold:
                break;

            if precondition_hessian_matrix:
                z_vector = M_inverse * r_vector;
            else:
                z_vector = numpy.copy(r_vector);

            r_z_vector_square_new = numpy.sum(r_vector * z_vector);

            p_vector *= r_z_vector_square_new / r_z_vector_square_old;

            p_vector += z_vector

            r_z_vector_square_old = r_z_vector_square_new;

        return delta_doc_lambda;