Вложено для циклов в Python для Ising Model - PullRequest
0 голосов
/ 09 ноября 2018

В настоящее время я работаю над статистической механикой и пытаюсь применить к ней некоторое программирование, поскольку они так хорошо сочетаются друг с другом! Я работаю над поиском функции разбиения для конечного числа частиц. Однако ... функция разбиения определяется как сумма суммы! Я думаю, мы могли бы написать это как список списка, так что мы бы использовали вложенные циклы for, но я просто не могу понять, как это правильно написать.

Z = \ sum_ {s_1} ^ {s_N} e ^ (s_1s_2 + ... + s_ (N-1) s_N) - функция разбиения.

enter image description here

возможные значения s_i: -1, + 1.

Эффективно модель Изинга (1D) представляет собой цепочку с N точками на ней, и каждая точка может иметь s_i = -1 или +1. Энергия системы зависит от значений s_i, и каждая возможная комбинация называется состоянием. полная сумма этих состояний называется Z, функция разбиения.

Итак, для цепочки длиной N = 5 (следовательно, 2 ^ 5 = 32 возможных состояния), как бы я рассчитал этот Z? У меня действительно нет никакого кода, чтобы показать, но я знаю из формулы, результат должен быть что-то вроде e ^ (+ 1 + 1 + 1 + 1 + 1) + e ^ (- 1 + 1 + 1 + 1 + 1) + ... + е ^ (- 1-1-1-1-1). Вопрос в том ... как же я могу это делать? Я генерирую множество возможных состояний:

import itertools
counting=0
for state in itertools.product([1,-1],repeat=5):
    print(state)
    counting+=1
print('the total possible number of states is',counting).

но как я могу использовать это, чтобы получить значение для Z?

Ответы [ 2 ]

0 голосов
/ 09 ноября 2018

Я бы использовал функцию для расчета суммы для каждого состояния, а затем делал бы общую сумму:

import itertools
from math import exp

def each_state(products):
     for state in products:
         yield sum(state)


Z = sum(exp(x) for x in each_state(itertools.product([1,-1],repeat=5)))

Преимущество этого подхода состоит в том, что он соответствует духу itertools: не объединять все в память сразу. Таким образом, хотя решение numpy может быть быстрее, скажем, вы хотите вычислить Z для 1 миллиарда состояний, реализация numpy начнет сталкиваться с проблемами памяти, тогда как выражение генератора не будет:

from itertools import product
import numpy as np
from math import exp

# this will yield a single number, and product will yield
# each state one at a time, never aggregating the
# full set of objects into memory (even though it might seem slow)
x = sum(exp(sum(x)) for x in product([1,-1], repeat=50000000))


# On my 16GB MacBook, this process will be killed because
# we collect all of the states into memory
x = np.array(list(product([1, -1], repeat=50000000))
[1]    7743 killed     python

Общее правило гласит, что list(giant_iterable) не хватает места, тогда как for item in giant_iterable не хватит времени

0 голосов
/ 09 ноября 2018

Исходя из вашего описания проблемы, вы можете рассчитать ее, используя numpy следующим образом:

import itertools
import numpy as np

states = np.array([state for state in itertools.product([1,-1], repeat=5)])
print("There are %d states" % states.shape[0])  # 32 states

# calculate the sum for each state
sum_over_each_state = np.sum(states, axis=1)  
print(sum_over_each_state)

# calculate e^(sum(state)) for each state
exp_of_all_states = np.exp(sum_over_each_state)
print(exp_of_all_states)

# sum up all exponentials
Z = np.sum(exp_of_all_states)
print("Z:", Z)

Это дает Z = 279.96.

...