//  [python]
def newton_method_lambda(self,
                             doc_lambda,
                             doc_nu_square,
                             doc_zeta_factor,
                             sum_phi,
                             total_word_count,
                             newton_method_iteration=10,
                             newton_method_decay_factor=0.9,
                             # newton_method_step_size=0.1,
                             eigen_value_tolerance=1e-9
                             ):
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);
        assert sum_phi.shape == (self._number_of_topics,)

        newton_method_power_index = 0;
        for newton_method_iteration_index in range(newton_method_iteration):
            exp_over_doc_zeta = scipy.special.logsumexp(
                doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
            exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);
            assert exp_over_doc_zeta.shape == (self._number_of_topics,);

            if self._diagonal_covariance_matrix:
                first_derivative_lambda = (self._alpha_mu - doc_lambda) / self._alpha_sigma;
                first_derivative_lambda += sum_phi
                first_derivative_lambda -= total_word_count * exp_over_doc_zeta
            else:
                first_derivative_lambda = numpy.dot((self._alpha_mu - doc_lambda[numpy.newaxis, :]),
                                                    self._alpha_sigma_inv)
                assert first_derivative_lambda.shape == (1, self._number_of_topics);
                first_derivative_lambda += sum_phi[numpy.newaxis, :]
                first_derivative_lambda -= total_word_count * exp_over_doc_zeta[numpy.newaxis, :]
                assert first_derivative_lambda.shape == (1, self._number_of_topics);

            if self._diagonal_covariance_matrix:
                second_derivative_lambda = -1.0 / self._alpha_sigma
                second_derivative_lambda -= total_word_count * exp_over_doc_zeta
            else:
                second_derivative_lambda = -self._alpha_sigma_inv;
                assert second_derivative_lambda.shape == (self._number_of_topics, self._number_of_topics);
                second_derivative_lambda -= total_word_count * numpy.diag(exp_over_doc_zeta)
                assert second_derivative_lambda.shape == (self._number_of_topics, self._number_of_topics);

            if self._diagonal_covariance_matrix:
                if not numpy.all(second_derivative_lambda) > 0:
                    sys.stderr.write("Hessian matrix is not positive definite: %s\n" % second_derivative_lambda)
                    break;
            else:
                pass
                '''
                print "%s" % second_derivative_lambda;
                E_vector, V_matrix = scipy.linalg.eigh(second_derivative_lambda);
                while not numpy.all(E_vector>eigen_value_tolerance):
                    second_derivative_lambda += numpy.eye(self._number_of_topics);
                    E_vector, V_matrix = scipy.linalg.eigh(second_derivative_lambda);
                    print "%s" % E_vector
                '''

            if self._diagonal_covariance_matrix:
                step_change = first_derivative_lambda / second_derivative_lambda;
            else:
                # step_change = numpy.dot(first_derivative_lambda, numpy.linalg.pinv(second_derivative_lambda))[0, :]
                step_change = numpy.dot(first_derivative_lambda, scipy.linalg.pinv(second_derivative_lambda))[0, :]

            # step_change *= newton_method_step_size;
            step_change /= numpy.sqrt(numpy.sum(step_change ** 2));

            # if numpy.any(numpy.isnan(step_change)) or numpy.any(numpy.isinf(step_change)):
            # break;

            step_alpha = numpy.power(newton_method_decay_factor, newton_method_power_index);

            doc_lambda -= step_alpha * step_change;
            assert doc_lambda.shape == (self._number_of_topics,);

            # if numpy.all(numpy.abs(step_change) <= local_parameter_converge_threshold):
            # break;

            # print "update lambda to %s" % (doc_lambda)

        return doc_lambda;