Forum >> Programmazione Python >> Calcolo scientifico >> Sostituzione prima superdiagonale

Pagina: 1

Buongiorno amici pythoniani :)



oggi quesito numpy;




data la seguente matrice:




A = np.array([[1,2,3],[4,5,6],[7,8,9]])


esiste un comando numpy che consenta di fare il fill della prima superdiagonale? (quindi sostituire in un colpo l'array ([2,6]) ) ?

Grazie in anticipo, come sempre.




A presto :fingers-crossed: ;)


--- Ultima modifica di Kolmogorov Scale in data 2024-09-23 12:52:17 ---

--- Ultima modifica di Kolmogorov Scale in data 2024-09-23 12:52:34 ---
<< Somewhere, something incredible is waiting to be known >> [Carl Sagan]
Intendi qualcosa tipo questo?:

Python 3.12.3 (main, Jul 31 2024, 17:43:48) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license()" for more information.
import numpy as np
A = np.array([[1,2,3],[4,5,6],[7,8,9]])
A
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
np.diagonal(A, 1)
array([2, 6])

Non è farina del mio sacco, suggerimento ricevuto in questa pagina documentale, è sufficiente porre un ofset di una posizione rispetto alla diagonale ordinaria.




Ciao

Fatti non foste a viver come bruti...
Rileggendo il post mi son reso conto di aver travisato il quesito posto a @Kolmogorov Scale, che probabilmente non verteva sul come ottenere la super-diagonale bensì su come variarne i valori con metodi propri di numpy ... chiedo venia per la mia risposta fuori logo.

In merito ai metodi di numpy (eventualmente mi si corregga) dalle ricerche effettuate non sembra sia possibile essendo il parametro "offset" implementato in funzioni tipo fill_diagonal e simili, è un argomento su cui si discute in merito ma di la da venire.




Pur non essendo l'algebra lineare materia a me familiare, giusto per chiedere scusa della mia precedente cattiva interpretazione, ho implementato una piccola funzione per la sostituzione dei valori diagonali e/o super/sub-diagonali tramite una funzione manipolatrice od anche un iterabile, segue il codice :

import numpy as np
from typing import Any

def my_fill_diag(a: np.array,  val: Any, o: int=0, w: bool=True) -> None:
    ''' Emulazione di numpy.fill_diagonal con applicazione delle
        sostituzioni a super e sub diagonali.
        Parametri:
        - a   : array multidimensionale cui applicare le sostituzioni;
        - val : iterabile o funzione per la definizione delle sostituzioni;
        - o   : offset rispetto alla diagonale base, se positivo sarà
                applicato sulle colonne, se negativo sulle righe di "a",
                nel caso superi le colonne o le righe disponibili non
                sarà applicato;
        - w   : se vero il ciclo di sostituzione si interromperà in caso
                si raggiunga l'ultima colonna, altrimenti si riposiziona
                sulla prima e continua.
                In ogni caso la sostituzione termina raggiunta l'ultima
                riga.
        Nota: Qualora "val" sia un iterabile ed abbia dimensioni inferiori
              a quelle della diagonale i valori saranno riproposti
              ciclicamente.
    '''
    rows, cols = a.shape
    c = 0
    r = 0
    if o > 0 and o < cols:
        c = o
    elif o < 0 and abs(o) < rows:
        r = abs(o)
    if 'function' in repr(type(val)):
        while r < rows:
            a[r, c] = val(a[r, c])
            r += 1
            c += 1
            if c == cols:
                if w:
                    break
                else:
                    c = 0
    else:
        i = 0
        while i < len(val):
            a[r, c] = val
            r += 1
            c += 1
            if r == rows:
                break
            if c == cols:
                if w:
                    break
                else:
                    c = 0
            i += 1
            if i == len(val):
                i = 0

Nella doc-string della funzione ho cercato di farne comprendere i parametri ed il funzionamento, eventuali suggerimenti per migliorarla (anche come stesura e/o elasticità) sono ben accetti




Segue una sessione shell di test per esemplificarne l'uso :

Python 3.12.3 (main, Sep 11 2024, 14:17:37) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license()" for more information.
from prova_01 import my_fill_diag
import numpy as np
A = np.arange(1, 17).reshape(4, 4)
A
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12],
       [13, 14, 15, 16]])
def my_func(value):
    return value * 2

my_fill_diag(A, my_func, 1)
A
array([[ 1,  4,  3,  4],
       [ 5,  6, 14,  8],
       [ 9, 10, 11, 24],
       [13, 14, 15, 16]])
A = np.arange(1, 17).reshape(4, 4)
B = [100, 200]
A = np.arange(1, 17).reshape(4, 4)
my_fill_diag(A, B, 1, False)
A
array([[  1, 100,   3,   4],
       [  5,   6, 200,   8],
       [  9,  10,  11, 100],
       [200,  14,  15,  16]])
A = np.arange(1, 17).reshape(4, 4)
my_fill_diag(A, B, -1, False)
A
array([[  1,   2,   3,   4],
       [100,   6,   7,   8],
       [  9, 200,  11,  12],
       [ 13,  14, 100,  16]])

Spero possa essere utile a qualcuno e rinnovo le mie scuse per la precedente interpretazione.

I miei saluti

Fatti non foste a viver come bruti...
Rileggendo il post mi son reso conto di aver travisato il quesito posto a @Kolmogorov Scale, che probabilmente non verteva sul come ottenere la super-diagonale bensì su come variarne i valori con metodi propri di numpy ... chiedo venia per la mia risposta fuori logo.

In merito ai metodi di numpy (eventualmente mi si corregga) dalle ricerche effettuate non sembra sia possibile essendo il parametro "offset" implementato in funzioni tipo fill_diagonal e simili, è un argomento su cui si discute in merito ma di la da venire.




Pur non essendo l'algebra lineare materia a me familiare, giusto per chiedere scusa della mia precedente cattiva interpretazione, ho implementato una piccola funzione per la sostituzione dei valori diagonali e/o super/sub-diagonali tramite una funzione manipolatrice od anche un iterabile, segue il codice :

import numpy as np
from typing import Any

def my_fill_diag(a: np.array,  val: Any, o: int=0, w: bool=True) -> None:
    ''' Emulazione di numpy.fill_diagonal con applicazione delle
        sostituzioni a super e sub diagonali.
        Parametri:
        - a   : array multidimensionale cui applicare le sostituzioni;
        - val : iterabile o funzione per la definizione delle sostituzioni;
        - o   : offset rispetto alla diagonale base, se positivo sarà
                applicato sulle colonne, se negativo sulle righe di "a",
                nel caso superi le colonne o le righe disponibili non
                sarà applicato;
        - w   : se vero il ciclo di sostituzione si interromperà in caso
                si raggiunga l'ultima colonna, altrimenti si riposiziona
                sulla prima e continua.
                In ogni caso la sostituzione termina raggiunta l'ultima
                riga.
        Nota: Qualora "val" sia un iterabile ed abbia dimensioni inferiori
              a quelle della diagonale i valori saranno riproposti
              ciclicamente.
    '''
    rows, cols = a.shape
    c = 0
    r = 0
    if o > 0 and o < cols:
        c = o
    elif o < 0 and abs(o) < rows:
        r = abs(o)
    if 'function' in repr(type(val)):
        while r < rows:
            a[r, c] = val(a[r, c])
            r += 1
            c += 1
            if c == cols:
                if w:
                    break
                else:
                    c = 0
    else:
        i = 0
        while i < len(val):
            a[r, c] = val
            r += 1
            c += 1
            if r == rows:
                break
            if c == cols:
                if w:
                    break
                else:
                    c = 0
            i += 1
            if i == len(val):
                i = 0

Nella doc-string della funzione ho cercato di farne comprendere i parametri ed il funzionamento, eventuali suggerimenti per migliorarla (anche come stesura e/o elasticità) sono ben accetti




Segue una sessione shell di test per esemplificarne l'uso :

Python 3.12.3 (main, Sep 11 2024, 14:17:37) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license()" for more information.
from prova_01 import my_fill_diag
import numpy as np
A = np.arange(1, 17).reshape(4, 4)
A
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12],
       [13, 14, 15, 16]])
def my_func(value):
    return value * 2

my_fill_diag(A, my_func, 1)
A
array([[ 1,  4,  3,  4],
       [ 5,  6, 14,  8],
       [ 9, 10, 11, 24],
       [13, 14, 15, 16]])
A = np.arange(1, 17).reshape(4, 4)
B = [100, 200]
A = np.arange(1, 17).reshape(4, 4)
my_fill_diag(A, B, 1, False)
A
array([[  1, 100,   3,   4],
       [  5,   6, 200,   8],
       [  9,  10,  11, 100],
       [200,  14,  15,  16]])
A = np.arange(1, 17).reshape(4, 4)
my_fill_diag(A, B, -1, False)
A
array([[  1,   2,   3,   4],
       [100,   6,   7,   8],
       [  9, 200,  11,  12],
       [ 13,  14, 100,  16]])

Spero possa essere utile a qualcuno e rinnovo le mie scuse per la precedente interpretazione.

I miei saluti


Ciao pippo, scusami per il ritardo osceno ma sono stato sotto esami e ho dovuto staccarmi completamente dalla vita social.

Alla fine ho risolto nella maniera più semplice possibile: e cioè costruendo la mia Matrice come una somma tra una matrice identità più i singoli array-valori ottenuti dal calcolo

numerico, che andavano a riempire le superdiagonali della mia matrice di partenza.
<< Somewhere, something incredible is waiting to be known >> [Carl Sagan]


Pagina: 1



Esegui il login per scrivere una risposta.