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, То же самое с к.

Другие вопросы по тегам