Exemplo n.º 1
0
def _minpoly_exp(ex, x):
    """
    Returns the minimal polynomial of ``exp(ex)``
    """
    c, a = ex.args[0].as_coeff_Mul()
    if a == I * pi:
        if c.is_rational:
            q = sympify(c.q)
            if c.p == 1 or c.p == -1:
                if q == 3:
                    return x**2 - x + 1
                if q == 4:
                    return x**4 + 1
                if q == 6:
                    return x**4 - x**2 + 1
                if q == 8:
                    return x**8 + 1
                if q == 9:
                    return x**6 - x**3 + 1
                if q == 10:
                    return x**8 - x**6 + x**4 - x**2 + 1
                if q.is_prime:
                    s = 0
                    for i in range(q):
                        s += (-x)**i
                    return s

            # x**(2*q) = product(factors)
            factors = [cyclotomic_poly(i, x) for i in divisors(2 * q)]
            mp = _choose_factor(factors, x, ex)
            return mp
        else:
            raise NotAlgebraic("%s does not seem to be an algebraic element" %
                               ex)
    raise NotAlgebraic("%s does not seem to be an algebraic element" % ex)
Exemplo n.º 2
0
def _minpoly_exp(ex, x):
    """
    Returns the minimal polynomial of ``exp(ex)``
    """
    c, a = ex.args[0].as_coeff_Mul()
    p = sympify(c.p)
    q = sympify(c.q)
    if a == I*pi:
        if c.is_rational:
            if c.p == 1 or c.p == -1:
                if q == 3:
                    return x**2 - x + 1
                if q == 4:
                    return x**4 + 1
                if q == 6:
                    return x**4 - x**2 + 1
                if q == 8:
                    return x**8 + 1
                if q == 9:
                    return x**6 - x**3 + 1
                if q == 10:
                    return x**8 - x**6 + x**4 - x**2 + 1
                if q.is_prime:
                    s = 0
                    for i in range(q):
                        s += (-x)**i
                    return s

            # x**(2*q) = product(factors)
            factors = [cyclotomic_poly(i, x) for i in divisors(2*q)]
            mp = _choose_factor(factors, x, ex)
            return mp
        else:
            raise NotAlgebraic("%s doesn't seem to be an algebraic element" % ex)
    raise NotAlgebraic("%s doesn't seem to be an algebraic element" % ex)
Exemplo n.º 3
0
    def torsion_points(self):
        """
        Return torsion points of curve over Rational number.

        Return point objects those are finite order.
        According to Nagell-Lutz theorem, torsion point p(x, y)
        x and y are integers, either y = 0 or y**2 is divisor
        of discriminent. According to Mazur's theorem, there are
        at most 15 points in torsion collection.

        Examples
        ========

        >>> from ec import EllipticCurve
        >>> e2 = EllipticCurve.minimal(-43, 166)
        >>> [i for i in e2.torsion_points()]
        [O, (3, 8), (3, -8), (-5, 16), (-5, -16), (11, 32), (11, -32)]

        """
        if self.characteristic > 0:
            raise ValueError("No torsion point for Finite Field.")
        yield InfinityPoint(self)
        for x in solve(self._eq.subs(y, 0)):
            if x.is_rational:
                yield self(x, 0)
        for i in divisors(self.discriminant, generator=True):
            j = int(i**.5)
            if j**2 == i:
                for x in solve(self._eq.subs(y, j)):
                    p = self(x, j)
                    if x.is_rational and p.order() != oo:
                        yield p
                        yield -p
Exemplo n.º 4
0
def singspec(elem, path='output.h5'):
    with pd.HDFStore(path) as store:
        N = len(store.sim)
        divs = divisors(N)[4:12]

    vals = np.zeros((len(divs), 3))
    for i in range(len(divs)):
        print(divs[i], flush=1)
        vals[i] = h_svd(elem, divs[i], path=path)

    fig = plt.figure(figsize=(8,8))
    fig.set_tight_layout(True)
    grid = gs.GridSpec(3, 1)

    first = plt.subplot(grid[0])
    first.semilogx(divs, vals[:,0])

    second = plt.subplot(grid[1])
    second.semilogx(divs, vals[:,1])

    third = plt.subplot(grid[2])
    third.semilogx(divs, vals[:,2])

    plt.show()
Exemplo n.º 5
0
def optimize_calc_options(nodes,
                          mpi_per_node,
                          omp_per_mpi,
                          use_omp,
                          mpi_omp_ratio,
                          fleurinpData=None,
                          kpts=None,
                          sacrifice_level=0.9,
                          only_even_MPI=False):
    """
    Makes a suggestion on parallelisation setup for a particular fleurinpData.
    Only the total number of k-points is analysed: the function suggests ideal k-point
    parallelisation + OMP parallelisation (if required). Note: the total number of used CPUs
    per node will not exceed mpi_per_node * omp_per_mpi.

    Sometimes perfect parallelisation is terms of idle CPUs is not what
    used wanted because it can harm MPI/OMP ratio. Thus the function first chooses first top
    parallelisations in terms of total CPUs used
    (bigger than sacrifice_level * maximal_number_CPUs_possible). Then a parallelisation which is
    the closest to the MPI/OMP ratio is chosen among them and returned.

    :param nodes: maximal number of nodes that can be used
    :param mpi_per_node: an input suggestion of MPI tasks per node
    :param omp_per_mpi: an input suggestion for OMP tasks per MPI process
    :param use_omp: False if OMP parallelisation is not needed
    :param mpi_omp_ratio: requested MPI/OMP ratio
    :param fleurinpData: FleurinpData to extract total number of kpts from
    :param kpts: the total number of kpts
    :param sacrifice_level: sets a level of performance sacrifice that a user can afford for better
                            MPI/OMP ratio.
    :parm only_even_MPI: if set to True, the function does not set MPI to an odd number (if possible)
    :returns nodes, MPI_tasks, OMP_per_MPI, message: first three are parallelisation info and
                                                     the last one is an exit message.
    """
    from sympy.ntheory.factor_ import divisors
    import numpy as np

    cpus_per_node = mpi_per_node * omp_per_mpi
    if fleurinpData:
        kpts = fleurinpData.get_nkpts()
    elif not kpts:
        raise ValueError('You must specify either kpts of fleurinpData')
    divisors_kpts = divisors(kpts)
    possible_nodes = [x for x in divisors_kpts if x <= nodes]
    suggestions = []
    for n_n in possible_nodes:
        advise_cpus = [x for x in divisors(kpts // n_n) if x <= cpus_per_node]
        for advised_cpu_per_node in advise_cpus:
            suggestions.append((n_n, advised_cpu_per_node))

    def add_omp(suggestions, only_even_MPI_1):
        """
        Also adds possibility of omp parallelisation
        """
        final_suggestion = []
        for suggestion in suggestions:
            if use_omp:
                omp = cpus_per_node // suggestion[1]
            else:
                omp = 1
            # here we drop parallelisations having odd number of MPIs
            if only_even_MPI_1 and suggestion[1] % 2 == 0 or not only_even_MPI_1:
                final_suggestion.append([suggestion[0], suggestion[1], omp])
        return final_suggestion

    # all possible suggestions taking into account omp
    suggestions_save = suggestions
    suggestions = np.array(add_omp(suggestions, only_even_MPI))
    if not len(suggestions):  # only odd MPI parallelisations possible, ignore only_even_MPI
        suggestions = np.array(add_omp(suggestions_save, False))

    best_resources = max(np.prod(suggestions, axis=1))
    top_suggestions = suggestions[np.prod(suggestions, axis=1) > sacrifice_level * best_resources]

    def best_criterion(suggestion):
        if use_omp:
            return -abs(suggestion[1] / suggestion[2] - mpi_omp_ratio)
        return (suggestion[0] * suggestion[1], -suggestion[0])

    best_suggestion = max(top_suggestions, key=best_criterion)

    message = ''

    if float(best_suggestion[1] * best_suggestion[2]) / cpus_per_node < 0.6:
        message = ('WARNING: Changed the number of MPIs per node from {} to {} and OMP per MPI '
                   'from {} to {}.'
                   'Changed the number of nodes from {} to {}. '
                   'Computational setup, needed for a given number k-points ({})'
                   ' provides less then 60% of node load.'
                   ''.format(mpi_per_node, best_suggestion[1], omp_per_mpi, best_suggestion[2], nodes,
                             best_suggestion[0], kpts))
        raise ValueError(message)
    elif best_suggestion[1] * best_suggestion[2] == cpus_per_node:
        if best_suggestion[0] != nodes:
            message = ('WARNING: Changed the number of nodes from {} to {}' ''.format(nodes, best_suggestion[0]))
        else:
            message = ('Computational setup is perfect! Nodes: {}, MPIs per node {}, OMP per MPI '
                       '{}. Number of k-points is {}'.format(best_suggestion[0], best_suggestion[1], best_suggestion[2],
                                                             kpts))
    else:
        message = ('WARNING: Changed the number of MPIs per node from {} to {} and OMP from {} to {}'
                   '. Changed the number of nodes from {} to {}. Number of k-points is {}.'
                   ''.format(mpi_per_node, best_suggestion[1], omp_per_mpi, best_suggestion[2], nodes,
                             best_suggestion[0], kpts))

    return int(best_suggestion[0]), int(best_suggestion[1]), int(best_suggestion[2]), message
Exemplo n.º 6
0
from sympy.ntheory.factor_ import divisors


def is_pandigital_product(a, b, c):
    s = str(a) + str(b) + str(c)
    l = list(s)
    l.sort()
    return ''.join(l) == '123456789'


panNums = set()
for n in range(1234, 9876):
    divs = divisors(n)
    for d in divs[:len(divs) // 2]:
        if is_pandigital_product(d, n // d, n):
            print('{} * {} = {}'.format(d, n // d, n))
            panNums.add(n)

print(sum(panNums))