Problem z krojeniem Pythona / numpy

Mam problem z kilkoma numerami. Potrzebuję tablicy numpy, aby zachowywać się w nietypowy sposób, zwracając plasterek jako widok pociętych danych, a nie kopii. Oto przykład tego, co chcę zrobić:

Powiedzmy, że mamy prostą tablicę taką jak ta:

a = array([1, 0, 0, 0])

Chciałbym zaktualizować kolejne wpisy w tablicy (poruszając się od lewej do prawej) za pomocą poprzedniego wpisu z tablicy, używając składni takiej jak ta:

a[1:] = a[0:3]

Otrzymałoby to następujący wynik:

a = array([1, 1, 1, 1])

Lub coś w tym stylu:

a[1:] = 2*a[:3]
# a = [1,2,4,8]

Aby zilustrować dalej, chcę następujące zachowanie:

for i in range(len(a)):
    if i == 0 or i+1 == len(a): continue
    a[i+1] = a[i]

Z wyjątkiem tego, że chcę prędkości numpy.

Domyślnym zachowaniem numpy jest wykonanie kopii wycinka, więc to, co faktycznie otrzymuję, jest następujące:

a = array([1, 1, 0, 0])

Mam już tę tablicę jako podklasę ndarray, więc jeśli zajdzie taka potrzeba, mogę wprowadzić do niej dalsze zmiany, potrzebuję tylko, aby plasterek po prawej stronie był stale aktualizowany, ponieważ aktualizuje plasterek po lewej stronie.

Czy śnię czy ta magia jest możliwa?

Aktualizacja: To wszystko, ponieważ próbuję użyć iteracji Gaussa-Seidla do rozwiązania problemu algebry liniowej, mniej więcej. Jest to szczególny przypadek obejmujący funkcje harmoniczne, starałem się unikać wchodzenia w to, ponieważ tak naprawdę nie jest to konieczne i prawdopodobnie będzie mylić rzeczy dalej, ale tutaj idzie.

Algorytm jest następujący:

while not converged:
    for i in range(len(u[:,0])):
        for j in range(len(u[0,:])):
            # skip over boundary entries, i,j == 0 or len(u)
            u[i,j] = 0.25*(u[i-1,j] + u[i+1,j] + u[i, j-1] + u[i,j+1])

Dobrze? Ale możesz zrobić to na dwa sposoby, Jacobi wymaga aktualizacji każdego elementu swoimi sąsiadami bez uwzględniania aktualizacji, które już zrobiłeś do czasu cykli pętli, aby zrobić to w pętlach, skopiuj tablicę, a następnie zaktualizuj jedną tablicę ze skopiowanej tablicy. Jednak Gauss-Seidel używa informacji, które już zaktualizowałeś dla każdego z wpisów i-1 i j-1, a zatem nie ma potrzeby kopiowania, pętla powinna zasadniczo „wiedzieć”, ponieważ tablica została ponownie oceniona po każdej aktualizacji pojedynczego elementu . Oznacza to, że za każdym razem, gdy wywołujemy wpis taki jak u [i-1, j] lub u [i, j-1], informacja obliczona w poprzedniej pętli będzie tam dostępna.

Chcę zastąpić tę powolną i brzydką sytuację zagnieżdżonej pętli jedną, ładną, czystą linią kodu, używającą numerycznego krojenia:

u[1:-1,1:-1] = 0.25(u[:-2,1:-1] + u[2:,1:-1] + u[1:-1,:-2] + u[1:-1,2:])

Ale rezultatem jest iteracja Jacobiego, ponieważ kiedy bierzesz kawałek: u [:, - 2,1: -1] kopiujesz dane, a więc plasterek nie jest świadomy żadnych aktualizacji. Teraz numer jest wciąż zapętlony? Nie jest równoległy, tylko szybszy sposób na pętlę, która wygląda jak równoległa operacja w Pythonie. Chcę wykorzystać to zachowanie poprzez hakowanie numpy, aby zwrócić wskaźnik zamiast kopii, gdy biorę kawałek. Dobrze? Następnie za każdym razem, gdy pętla numpy, ten plasterek „zaktualizuje się” lub po prostu powieli wszystko, co wydarzyło się w aktualizacji. Aby to zrobić, potrzebuję plasterków po obu stronach tablicy, aby były wskaźnikami.

W każdym razie, jeśli jest tam naprawdę naprawdę sprytna osoba, która jest niesamowita, ale całkiem się pogodziłem z przekonaniem, że jedyną odpowiedzią jest zapętlenie w C.

questionAnswers(9)

yourAnswerToTheQuestion