//  [python]
def newton_method_nu_square(self,
                                doc_lambda,
                                doc_nu_square,
                                doc_zeta_factor,
                                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);

        newton_method_power_index = 0;
        for newton_method_iteration_index in range(newton_method_iteration):
            # print doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis]
            # exp_over_doc_zeta = 1.0 / numpy.sum(numpy.exp(doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis]), axis=1);
            # print 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(-scipy.special.logsumexp(doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1));
            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.clip(exp_over_doc_zeta, -10, +10);
            exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

            if self._diagonal_covariance_matrix:
                first_derivative_nu_square = -0.5 / self._alpha_sigma;
            else:
                first_derivative_nu_square = -0.5 * numpy.diag(self._alpha_sigma_inv);
            first_derivative_nu_square += 0.5 / doc_nu_square;
            # first_derivative_nu_square -= 0.5 * (total_word_count / doc_zeta) * numpy.exp(doc_lambda+0.5*doc_nu_square)
            first_derivative_nu_square -= 0.5 * total_word_count * exp_over_doc_zeta;

            second_derivative_nu_square = -0.5 / (doc_nu_square ** 2);
            # second_derivative_nu_square += -0.25 * (total_word_count / doc_zeta) * numpy.exp(doc_lambda+0.5*doc_nu_square);
            second_derivative_nu_square += -0.25 * total_word_count * exp_over_doc_zeta;

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

            step_change = first_derivative_nu_square / second_derivative_nu_square;

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

            step_alpha = numpy.power(newton_method_decay_factor, newton_method_power_index);
            while numpy.any(doc_nu_square <= step_alpha * step_change):
                newton_method_power_index += 1;
                step_alpha = numpy.power(newton_method_decay_factor, newton_method_power_index);

            doc_nu_square -= step_alpha * step_change;

            assert numpy.all(doc_nu_square > 0), (
            doc_nu_square, step_change, first_derivative_nu_square, second_derivative_nu_square);

        return doc_nu_square;