Python - создание массива, в котором элементы являются функцией переменного параметра, без создания массива каждый раз
TLDR: Как я могу сгенерировать массив, элементы которого зависят от некоторого произвольного (плавающего) значения k, без необходимости проходить через чрезвычайно дорогостоящий процесс создания массива с нуля каждый раз, когда я изменяю значение k.
То, чего я хочу достичь, будет выглядеть так:
Я генерирую огромный гамильтониан в атомном базисе двумерной решетки (N x N numpy массив). Заполнение этого массива требует многократного сравнения позиций (xyz) атомных сайтов для каждого из различных типов соединений, которые я хочу включить, и становится очень дорогостоящим по мере увеличения размера системы. (обычно N > 16 000 сайтов).
Элементы этого массива имеют зависимость от некоторой другой переменной типа float, k (в физическом контексте программы это квантовое число, которое я хочу повторить). Мне нужно вычислить этот массив много раз для диапазона 1000 k-значений.
то есть сгенерировать массив из 256 000 000 элементов 1000 раз...
В настоящее время мне приходится создавать массив каждый раз, когда я перехожу на новое значение k, которое, очевидно, очень неэффективно. Базовая структура этого выглядит (в общем) как:
class Device():
def __init__(self, xyz, energy, ... other input parameters ...):
self.xyz = xyz # N x 3 array of positions
self.energy = energy # Length N list of energies
# + A range of other parameters that define the device
# -------- OTHER OPERATIONS ON THE DEVICE -------- #
def get_H(self, k):
""" Get the Hamiltonian for a given k - value """
# Initialise the N x N array
h = np.zeros((len(self.xyz), len(self.xyz)))
# - Fill THE HAMILTONIAN BY COMPARING ALL ATOMIC POSITIONS IN self.xyz - #
return h
что требует, чтобы я каждый раз вызывал весь процесс строительства.
Я хочу знать, есть ли способ сгенерировать этот массив один раз, когда k оставлен в качестве свободного параметра, который затем можно заполнить позже. т.е. вернуть массив, который является функцией от k. Приоритет состоит в том, чтобы создавать массив только один раз, поскольку тестирование показывает, что это занимает значительную часть моего общего времени выполнения.
Ниже приведен минимальный (нерабочий) пример того, чего я хочу достичь, воздействуя на тестовый массив. Я хочу сделать гамильтониан объектной переменной, а не методом, который должен выполняться каждый раз, но с некоторой зависимостью от k (я понимаю, что это будет синтаксически катастрофическим, но, надеюсь, будет хорошим началом для ответа).
class Test_device():
def __init__():
self.get_H = self.make_H()
def make_H(self):
h = np.linspace(1,9,9).reshape((3,3)) # Test array
# The below clearly will not work because k is not defined, but this is
# where I want to achieve this
h[1,1] += k # Give some k-dependence to the middle element of the array
def ham(k, h = h):
# Somehow set the value of k in h
return h
return ham
Который я бы тогда получил доступ через
device = Test_device()
device.get_H(k = k_value)
Заранее спасибо!
2 ответа
На раздумья не думаю np.fromfunction()
это то, что вы хотите. Скорее попробуйте:
import numpy as np
class Test_device(object):
def __init__(self, h_shape):
self.h_shape = h_shape
# Create array once
self.h = np.linspace(1, h_shape[0] ** 2, h_shape[1] ** 2).reshape(self.h_shape)
def get_H(self, k, locn=(1, 1)):
self.h[locn] += k # Give some k-dependence to the middle element of the array
# Somehow set the value of k in h
pass
В дальнейшем следует инициализировать устройство один раз (с учетом предполагаемой формы для h
). Затем выберите k
(и местоположение locn
, если ты хочешь). Затем позвоните get_H
метод device
, k
никогда не приписывается device
, но может быть, если вам нравится для ссылки с self.k=k
(как говорится в eatmeinadanish).
Тогда вы можете получить доступ device.h
всякий раз, когда вам нравится.
h_shape = (3, 3)
device = Test_device(h_shape)
k = 1.3
locn = (1, 1)
device.get_H(k, locn=locn)
print device.h
Я не уверен, что это поможет вам в конце концов, будь то, что вы на самом деле намеревались, и заметьте, что это на самом деле мало что добавляет к ответу memeinadanish.
Это не рабочий пример, но...
class Test_device():
def __init__(self, h):
self.k = 0
self.h = h
def get_H(self):
self.h = np.linspace(1,9,9).reshape((3,3)) # Test array
# The below clearly will not work because k is not defined, but this is
# where I want to achieve this
self.h[1,1] += self.k # Give some k-dependence to the middle element of the array
def ham(self):
# Somehow set the value of k in h
return self.h
Вы можете сделать что-то вроде этого:
device = Test_Device(10)
device.get_H()
device.h = 12
device.get_H()
h = device.ham()
Вы можете изменить h или k в любое время, просто изменив значение внутри класса, как device.h = 14
, То же самое с к.