Passa al contenuto principale

Funzioni su strutture di algebra lineare

Introduzione​

Notazione di vettori, matrici e tensori​

Nel modulo Math le strutture multidimensionali non servono solo per i calcoli, ma possono essere anche il tipo di risultato di funzioni che non restituiscono un solo valore scalare. Un esempio sono le funzioni per stringhe che cercano determinati schemi in un testo. Tutte le posizioni e le lunghezze dei riscontri vengono allora restituite in una matrice.

In linea di principio, nel modulo Math vettori, matrici e tensori possono essere creati con la sintassi [ ... ]. Sono ammessi tutti i tipi di dati numerici, ma non <str>. Come elementi si possono usare espressioni, costanti o anche il contenuto di altre variabili. Il tipo di dati della struttura è sempre quello in cui tutti gli elementi possono essere rappresentati nel modo migliore.

Esempi:

num = 3.14159; // example for a variable as source
vec = [1, -2, false, num, 5];     // data type is <dbl> to represent num
mat = [ [ 1.1, num ] // 1st row
, [-num, 2.2 ] // 2nd row
, [ 3.1, 3.2 ] ]; // 3rd row
ten = [ [ [ 111, num, 113 ] // 1st matrix, first row
, [ 121, 122, 123 ] ] // second row
, [ [ 211, 212, 213 ] // 2nd matrix, first row
, [ 221, 222, num ] ] // second row
, [ [ 311, 312, 313 ] // 3rd matrix, first row
, [ 321, num, 323 ] ] // second row
, [ [ num, 412, 413 ] // 4th matrix, first row
, [ 421, 422, 423 ] ] ]; // second row

Se i sottoelementi (righe di una matrice, matrici di un tensore) hanno tutti la stessa dimensione, la dimensione della struttura è determinata solo dal numero di elementi e di sottoelementi. Nell'esempio, vec ha 5 elementi (a seconda dell'uso, in riga o in colonna), mat ha 3 righe e 2 colonne e ten ha 4 sezioni di matrice con 2 righe e 3 colonne ciascuna. Le differenze di dimensione vengono segnalate come errore durante la traduzione; non avviene alcun riempimento automatico (padding).

Accesso ai singoli elementi​

Un elemento di un vettore, di una matrice o di un tensore viene indirizzato anch'esso con la sintassi [ ... ], dove gli indici - come di consueto nei linguaggi di programmazione - partono sempre da 0. Gli indici possono provenire anche da variabili o da calcoli.

v_num = vec[3]; // liest das 4. Element des Vektors
m_num = mat[0, 1]; // liest in der 1. Zeile das 2. Element
t_422 = ten[3, 1, 1]; // liest aus der 4. Matrix, 2. Zeile, 2. Spalte

Operazioni elementari su oggetti multidimensionali​

Le operazioni seguenti sono implementate direttamente nella consueta notazione di formula:

  • Il confronto == e != è possibile su oggetti multidimensionali, purché entrambi gli operandi abbiano la stessa dimensione.

  • L'addizione e la sottrazione di oggetti multidimensionali sono possibili, purché entrambi gli operandi abbiano la stessa dimensione.

    M_Sum = M_1 + M_2;
    M_Dif = M_1 - M_2;
  • Moltiplicazione di un oggetto multidimensionale per uno scalare numerico. Il risultato è un oggetto con le stesse dimensioni, in cui ogni singolo elemento è scalato di conseguenza. Vale la proprietà commutativa.

    M_Scaled_0 = M_Base * 2.56;
    M_Scaled_1 = 2.56 * M_Base;
    • Divisione di un oggetto multidimensionale per uno scalare numerico. Il risultato è un oggetto con le stesse dimensioni, in cui ogni singolo elemento è scalato di conseguenza. La divisione per una matrice o per un vettore non è ammessa.
    M_Scaled_2 = M_Base / 2.56;
  • La moltiplicazione di due oggetti multidimensionali è possibile se il numero di colonne del primo operando coincide con il numero di righe del secondo. Il risultato è un oggetto multidimensionale con il numero di righe del primo e il numero di colonne del secondo operando. Qui un vettore non distingue tra righe e colonne: come primo operando viene interpretato come vettore riga e come secondo operando come vettore colonna. Ciò copre sicuramente il 95% delle interpretazioni tipiche nelle applicazioni tecniche, senza dover ricorrere a una funzione di trasposizione.

    M_mult = M_1 * M_2;
    V_row = V_1 * M; // V_1 interpreted as row-vector
    V_col = M * V_2; // v_2 interpreted as column-vector
    ScalarProduct = V_1 * V_2; // by definition
    CrossProduct = Cross(V_1, V_2); // := V_1 x V_2

Assegnazione di un vettore, di una matrice o di un tensore​

Una variabile può in linea di principio essere scritta o creata in un solo punto dell'insieme di formule. Ciò vale di conseguenza anche per vettori, matrici e tensori.

Esiste tuttavia la possibilità di scrivere indirettamente singoli elementi della struttura all'interno di questa assegnazione. In tal caso l'accesso indicizzato a un elemento deve trovarsi nel testo della formula dopo la vera e propria assegnazione della struttura, in modo che il compilatore possa integrare l'assegnazione dell'elemento nell'assegnazione dell'intera struttura.

I riferimenti circolari non sono ammessi.

M_spare = Matrix(3, 3); // erzeugt zunächst eine 3x3 Matrix mit 0
M_spare[0,1] = 101; // ergänzt die erste Zuweisung für Element [0,1]
M_spare[1,2] = 202;       // ergänzt die erste Zuweisung für Element [1,2] 
M_spare[2,0] = 303;       // ergänzt die erste Zuweisung für Element [2,0] 

Ogni volta che la matrice M_spare viene utilizzata, ha ora il seguente contenuto:

MSpare=[010100020230300]M_{\rm{Spare}} = \left[ \begin{array}{ccc} 0&101&0\\ 0&0&202\\ 303&0&0 \end{array} \right]

Questa notazione migliora la leggibilità del testo della formula, in particolare per matrici o vettori sparsi.

u_long = Vector(50, 3.14);           // create a very long vector
u_long[ 3] = -3.14;
u_long[25] = -3.14;
u_long[44] = u_long[10] + u_long[11];    // not allowed !!!

Per l'aggiornamento nel tempo del vettore, tutte le sorgenti di dati sono equivalenti. Il valore dell'intero vettore cambia quindi ogni volta che cambia almeno un elemento. Non esiste uno "stato intermedio" in cui l'assegnazione degli elementi non sia ancora avvenuta o sia avvenuta solo in parte.

Esportazione di parti di un oggetto multidimensionale​

Per estrarre una determinata parte da un oggetto multidimensionale si possono usare le funzioni GetCol(), GetRow() o GetSlice(). Così da una matrice si può esportare una determinata riga o colonna, oppure da un tensore con più sezioni di matrice una singola matrice. GetSub() consente l'esportazione di un intervallo qualsiasi, definito in ogni dimensione da un intervallo di indici di righe/colonne/sezioni.

Funzioni​

Costruzione di vettori "Vector"​

Le funzioni seguenti possono essere usate per costruire un vettore

u = Vector(size); // Mit 0 initialisierter Vektor der Dimension size x 1
u = Vector(size, v); // Mit v initialisierter Vektor der Dimension size x 1

L'orientamento del vettore come vettore riga o colonna non è definito e viene interpretato nel modo migliore a seconda dell'uso.

Vettore unitario "Normalize"​

Con la funzione Normalize() si determina un vettore unitario per il vettore dato.

e⃗=v⃗∣∣v⃗∣∣\vec{e}=\frac{\vec{v}}{||\vec{v}||}

Se il modulo del vettore è zero, viene restituito un vettore nullo oppure il valore sostitutivo v⃗0\vec{v}_0, in modo da non bloccare i successivi passaggi di calcolo.

ev1 = Normalize(v);
ev2 = Normalize(v, v0);

Costruzione di matrici "Matrix"​

Le funzioni seguenti possono essere usate per costruire una matrice

A = Matrix(rows, columns); // Mit 0 initialisierte Matrix der Dimensionen rows x columns
B = Matrix(rows, columns, v); // Mit v initialisierte Matrix der Dimensionen rows x columns

Matrice identità "MIdent"​

La funzione seguente restituisce una matrice identità di dimensioni size x size

I = MIdent(size);
I=[10⋯001⋱⋮⋮⋱⋱00⋯01]I = \left[ {\begin{array}{cccc} 1&0& \cdots &0\\ 0&1& \ddots & \vdots \\ \vdots & \ddots & \ddots &0\\ 0& \cdots &0&1 \end{array}} \right]

Matrice di rotazione "MRot"​

È possibile definire matrici di rotazione dei tipi seguenti

R_2 = MRot(alpha); // 2D-Rotationsmatrix um den Winkel alpha gegen den Uhrzeigersinn
R_3 = MRot(alpha, axis); // 3D-Rotationsmatrix um die mit axis bezeichnete Achse: x:0, y:1, z:2
M_3ypr = MRotYPR(y,p,r); // 3D-Rotationsmatrix, die eine durch Yaw, Pitch und Roll
// beschriebene Rotation beschreibt
M_3euler = MRotEuler(a,b,g); // 3D-Rotationsmatrix, die eine durch a, b, g beschriebene
// Euler-Rotation beschreibt

Con

  • cα=cos(α)c\alpha = cos(\alpha) e

  • sα=sin(α)s\alpha = sin(\alpha) si ha

MRot(α)=[cα−sαsαcα]MRot(\alpha) = \left[ {\begin{array}{cc} c\alpha & -s\alpha\\ s\alpha & c\alpha \end{array}} \right] MRot(α,0)=[1.00.00.00.0cα−sα0.0sαcα]MRot(\alpha, 0) = \left[ {\begin{array}{ccc} 1.0 & 0.0 & 0.0 \\ 0.0 & c\alpha & -s\alpha\\ 0.0 & s\alpha & c\alpha \end{array}} \right] MRot(α,1)=[cα0.0sα0.01.00.0−sα0.0cα]MRot(\alpha, 1) = \left[ {\begin{array}{ccc} c\alpha & 0.0 & s\alpha \\ 0.0 & 1.0 & 0.0\\ -s\alpha & 0.0 & c\alpha \end{array}} \right] MRot(α,2)=[cα−sα0.0sαcα0.00.00.01.0]MRot(\alpha, 2) = \left[ {\begin{array}{ccc} c\alpha & -s\alpha & 0.0 \\ s\alpha & c\alpha & 0.0\\ 0.0 & 0.0 & 1.0 \end{array}} \right]

Vedere anche: Matrice di rotazione – Wikipedia

Con

  • cψ=cos(ψ)c\psi=cos(\psi), sψ=sin(ψ)s\psi=sin(\psi) (Yaw),
  • cθ=cos(θ)c\theta=cos(\theta), sθ=sin(θ)s\theta=sin(\theta) (Pitch) e
  • cϕ=cos(ϕ)c\phi=cos(\phi), sϕ=sin(ϕ)s\phi=sin(\phi) (Roll) si ha
MRotYPR(ψ,θ,ϕ)=[cθ⋅cψsϕ⋅sθ⋅cψ−cϕ⋅sψcϕ⋅sθ⋅cψ+sϕ⋅sψcθ⋅sψsϕ⋅sθ⋅sψ+cϕ⋅cψcϕ⋅sθ⋅sψ−sϕ⋅cψ−sθsϕ⋅cθcϕ⋅cθ]\rm{MRotYPR}(\psi,\theta,\phi) = \left[ {\begin{array}{ccc} c\theta \cdot c\psi & s\phi \cdot s\theta \cdot c\psi - c\phi \cdot s\psi & c\phi \cdot s\theta \cdot c\psi + s\phi \cdot s\psi \\ c\theta \cdot s\psi & s\phi \cdot s\theta \cdot s\psi + c\phi \cdot c\psi & c\phi \cdot s\theta \cdot s\psi - s\phi \cdot c\psi \\ - s\theta & s\phi \cdot c\theta & c\phi \cdot c\theta \end{array}} \right]

Vedere anche: Angoli di Eulero

Con

  • cα=cos(α)c\alpha=cos(\alpha), sα=sin(α)s\alpha=sin(\alpha) (input Z-axis),
  • cβ=cos(β)c\beta=cos(\beta), sβ=sin(β)s\beta=sin(\beta) (node line, rotated X-axis) e
  • cγ=cos(γ)c\gamma=cos(\gamma), sγ=sin(γ)s\gamma=sin(\gamma) (output Z-axis) si ha
MRotEuler(α,β,γ)=[cα⋅cγ−sα⋅cβ⋅sγ−cα⋅sγ−sα⋅cβ⋅cγsα⋅sβsα⋅cγ+cα⋅cβ⋅sγ−sα⋅sγ+cα⋅cβ⋅cγ−cα⋅sβsβ⋅sγsβ⋅cγcβ]\rm{MRotEuler}(\alpha,\beta,\gamma) = \left[ {\begin{array}{ccc} c\alpha \cdot c\gamma - s\alpha \cdot c\beta \cdot s\gamma& - c\alpha \cdot s\gamma - s\alpha \cdot c\beta \cdot c\gamma& s\alpha \cdot s\beta \\ s\alpha \cdot c\gamma + c\alpha \cdot c\beta \cdot s\gamma& - s\alpha \cdot s\gamma + c\alpha \cdot c\beta \cdot c\gamma& - c\alpha \cdot s\beta \\ s\beta \cdot s\gamma & s\beta \cdot c\gamma & c\beta \end{array}} \right]

Vedere anche: Angoli di Eulero

Costruzione di tensori "Tensor"​

Per costruire un tensore con slices sezioni di dimensione rows x columns si utilizza

T = Tensor(slices, rows, columns);

Proprietà di vettori, matrici e tensori​

Verifica del tipo di una variabile "isScalar", "isVector", "isMatrix", "isTensor"​

Le funzioni seguenti restituiscono true se la variabile possiede la struttura interrogata. Ciò può essere utile quando una funzione, ad es. sFind(), restituisce o uno scalare (-1, non trovato) o una matrice di risultati e l'elaborazione successiva dipende da questo.

test1 = isScalar(var);
test2 = isVector(var);
test3 = isMatrix(var);
test4 = isTensor(var);

Interrogazione delle dimensioni di un oggetto "SizeOf"​

L'interrogazione delle dimensioni di un oggetto restituisce un vettore delle dimensioni, ad es.

VectorSize = SizeOf(v); // => [ 1, size ]
MatrixSize = SizeOf(M); // => [ 2, columns, rows]
TensorSize = SizeOf(T); // => [ 3, columns, rows, slices ]

Il primo componente indica il numero di dimensioni, i successivi il numero di elementi nella rispettiva dimensione.

Funzioni di accesso "GetCol", "GetRow", "GetSlice", "GetSub"​

suggerimento

Queste funzioni servono a ritagliare parti da un oggetto multidimensionale, in modo che di regola ne risulti nuovamente un oggetto multidimensionale. Per l'accesso a un singolo elemento è più efficace utilizzare la sintassi con indici.

La sezione di un oggetto multidimensionale in corrispondenza di un indice di colonna columnIndex può essere eseguita come segue

v1 = GetCol(D, columnIndex);
v2 = GetCol(D, {...}); // Konfiguration verpflichtend!
// Konfiguration für alle Varianten
vx = GetCol(..., { col: <uint> // verpflichtend, falls kein columnIndex
, rBeg: <uint>
, rEnd: <uint>
, sBeg: <uint>
, sEnd: <uint>
});

Per un vettore il risultato è un singolo elemento, per una matrice un vettore e per un tensore una matrice in corrispondenza dell'indice di colonna indicato. Per strutture di ordine superiore, gli intervalli copiati possono inoltre essere limitati tramite l'oggetto di configurazione.

ProprietàValoreDescrizione
col<uint>Indice di colonna per il piano di sezione
rBeg<uint>Indicazione facoltativa dell'intervallo per le righe
rEnd<uint>Indicazione facoltativa dell'intervallo per le righe
sBeg<uint>Indicazione facoltativa dell'intervallo per le sezioni
sEnd<uint>Indicazione facoltativa dell'intervallo per le sezioni

La sezione di un oggetto multidimensionale in corrispondenza di un indice di riga può essere eseguita come segue

v1 = GetRow(D, rowIndex);
v2 = GetRow(D, {...});               // Konfiguration verpflichtend!
// Konfiguration für alle Varianten
vx = GetRow(..., { cBeg: <uint>
, cEnd: <uint>
, row: <uint> // verpflichtend, falls kein rowIndex
, sBeg: <uint>
, sEnd: <uint>
});

Per un vettore il risultato è un singolo elemento, per una matrice un vettore e per un tensore una matrice in corrispondenza dell'indice di riga indicato. Per strutture di ordine superiore, gli intervalli copiati possono inoltre essere limitati tramite l'oggetto di configurazione.

ProprietàValoreDescrizione
row<uint>Indice di riga per il piano di sezione
cBeg<uint>Indicazione facoltativa dell'intervallo per le colonne
cEnd<uint>Indicazione facoltativa dell'intervallo per le colonne
sBeg<uint>Indicazione facoltativa dell'intervallo per le sezioni
sEnd<uint>Indicazione facoltativa dell'intervallo per le sezioni

La sezione di un oggetto multidimensionale in corrispondenza di un indice di sezione può essere eseguita come segue

v1 = GetSlice(D, sliceIndex);
v2 = GetSlice(D, {...});                // Konfiguration verpflichtend!
// Konfiguration für alle Varianten
vx = GetSlice(..., { cBeg: <uint>
, cEnd: <uint>
, rBeg: <uint>
, rEnd: <uint>
, slice:<uint> // verpflichtend, falls kein sliceIndex
});

Per un vettore il risultato è un singolo elemento, per una matrice un vettore e per un tensore una matrice in corrispondenza dell'indice di sezione indicato. Per strutture di ordine superiore, gli intervalli copiati possono inoltre essere limitati tramite l'oggetto di configurazione.

ProprietàValoreDescrizione
slice<uint>Indice di sezione per il piano di sezione
cBeg<uint>Indicazione facoltativa dell'intervallo per le colonne
cEnd<uint>Indicazione facoltativa dell'intervallo per le colonne
rBeg<uint>Indicazione facoltativa dell'intervallo per le righe
rEnd<uint>Indicazione facoltativa dell'intervallo per le righe

L'estrazione di una sottostruttura di dati da una struttura di dati avviene come segue

D1 = GetSub(D, { cBeg: <uint>
, cEnd: <uint>
, rBeg: <uint>
, rEnd: <uint>
, sBeg: <uint>
, sEnd: <uint>
});
ProprietàValoreDescrizione
cBeg<uint>Indicazione facoltativa dell'intervallo per le colonne
cEnd<uint>Indicazione facoltativa dell'intervallo per le colonne
rBeg<uint>Indicazione facoltativa dell'intervallo per le righe
rEnd<uint>Indicazione facoltativa dell'intervallo per le righe
sBeg<uint>Indicazione facoltativa dell'intervallo per le sezioni
sEnd<uint>Indicazione facoltativa dell'intervallo per le sezioni

Funzioni di elaborazione​

Trasposizione "Trans"​

La trasposizione di una matrice M x N restituisce una matrice N x M in cui righe e colonne sono scambiate e viene calcolata come segue

A_t = Trans(A);
A=[a11a12⋯a1N⋮⋱⋱⋮aM1aM2⋯aMN],AT=[a11⋯aM1a12⋱aM2⋮⋱⋮a1N⋯aMN]A = \left[\begin{array}{cccc} {{a_{11}}}&{{a_{12}}}& \cdots &{{a_{1N}}}\\ \vdots & \ddots & \ddots & \vdots \\ {{a_{M1}}}&{{a_{M2}}}& \cdots &{{a_{MN}}} \end{array}\right],A^T = \left[ \begin{array}{ccc} {{a_{11}}}& \cdots &{{a_{M1}}}\\ {{a_{12}}}& \ddots &{{a_{M2}}}\\ \vdots & \ddots & \vdots \\ {{a_{1N}}}& \cdots &{{a_{MN}}} \end{array}\right]

Prodotto vettoriale "Cross"​

Il prodotto vettoriale di due vettori u e v di lunghezza 2 o 3 restituisce un vettore perpendicolare ad essi, con modulo pari all'area del parallelogramma definito dai due vettori, e viene calcolato come segue

w = Cross(u, v);
w⃗=[uxuyuz]×[vxvyvz]=[uyvz−uzvyuzvx−uxvzuxvy−uyvx]\vec{w}=\left[ {\begin{array}{c} {{u_x}}\\ {{u_y}}\\ {{u_z}} \end{array}} \right] \times \left[ {\begin{array}{c} {{v_x}}\\ {{v_y}}\\ {{v_z}} \end{array}} \right] = \left[ {\begin{array}{c} {{u_y}{v_z} - {u_z}{v_y}}\\ {{u_z}{v_x} - {u_x}{v_z}}\\ {{u_x}{v_y} - {u_y}{v_x}} \end{array}} \right]

Decomposizione LU "LUDecomp"​

La decomposizione LU di una matrice M restituisce una matrice triangolare inferiore L e una matrice triangolare superiore U sotto forma di tensore con due sezioni e può essere eseguita come segue

T = LUDecomp(M);
L = GetSlice(T, 0);
U = GetSlice(T, 1);

Determinante "Det"​

Il determinante d di una matrice quadrata M può essere calcolato come segue

d = Det(M);

Lunghezza del vettore "Length"​

Calcolo della lunghezza di un vettore, vedere anche abs(...)

len = Length(v);
len=v02+v12+...+vn−12len = \sqrt{v_0^2 + v_1^2 + ... + v_{n-1}^2}