0Pricing
R Academy · Lezione

Risoluzione di sistemi lineari con solve()

Trovi soluzioni per i sistemi Ax = b e calcoli le inverse delle matrici

Risoluzione di sistemi lineari con solve() è una lezione R Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento R Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso R Academy include 4 lezioni in totale.

Sistemi lineari: Ax = b

Un sistema di equazioni lineari può essere scritto come Ax = b, dove A è una matrice di coefficienti, x è il vettore delle incognite e b è il termine noto. Risolvere analiticamente rispetto a x significa calcolare x = A⁻¹b.

# System of equations:
# 2x + y = 5
# x + 3y = 7

# Matrix form: A %*% x = b
A <- matrix(c(2, 1,
              1, 3), nrow = 2, byrow = TRUE)
b <- c(5, 7)

# What are A and b?
print(A)
print(b)
cat('We want to find x such that A %*% x = b')

solve(A, b): la soluzione diretta

solve(A, b) risolve Ax = b rispetto a x. Internamente utilizza la decomposizione LU, che è numericamente più stabile ed efficiente rispetto al calcolo esplicito di A⁻¹ seguito dalla moltiplicazione per b.

A <- matrix(c(2, 1,
              1, 3), nrow = 2, byrow = TRUE)
b <- c(5, 7)

# Solve Ax = b
x <- solve(A, b)
print(x)  # x[1] = ?, x[2] = ?

# Verify: A %*% x should equal b
residual <- A %*% x - b
print(residual)  # Should be near zero

# Manual check:
# 2*(8/5) + (9/5) = 16/5 + 9/5 = 25/5 = 5 ✓
# 1*(8/5) + 3*(9/5) = 8/5 + 27/5 = 35/5 = 7 ✓

solve(A): l'inversa della matrice

La chiamata a solve(A) con un solo argomento restituisce l'inversa di A: A⁻¹ tale che A %*% A⁻¹ = I. Eviti di usarla per risolvere Ax=b: utilizzi direttamente solve(A,b) (è più veloce e stabile).

A <- matrix(c(4, 3,
              3, 2), nrow = 2, byrow = TRUE)

# Compute inverse
A_inv <- solve(A)
print(A_inv)

# Verify: A %*% A_inv = I
A %*% A_inv  # Should be identity matrix
round(A %*% A_inv, 10)

# Also A_inv %*% A = I
round(A_inv %*% A, 10)

# det(A) != 0 required for invertibility
det(A)  # -1 (nonzero, so invertible)

Verifica della soluzione

Verifichi sempre la soluzione calcolando A %*% x - b. A causa dell'aritmetica in virgola mobile, il residuo non sarà esattamente zero, ma dovrebbe essere vicino all'epsilon di macchina (~1e-15). Utilizzi norm() per ottenere un'unica magnitudine del residuo.

A <- matrix(c(3, -1, 2,
              1,  4, 0,
             -2,  1, 5), nrow = 3, byrow = TRUE)
b <- c(1, 2, 3)

# Solve
x <- solve(A, b)
cat('Solution x:\n'); print(x)

# Residual check
residual <- A %*% x - b
cat('Residual vector:\n'); print(residual)

# Residual norm (should be near 0)
resid_norm <- sqrt(sum(residual^2))
cat('Residual norm:', resid_norm, '\n')
# Expected: something like 2e-16

Numero di condizionamento: kappa()

Il numero di condizionamento di A misura quanto la soluzione sia sensibile alle perturbazioni in b. Un numero di condizionamento elevato significa che piccoli errori in b causano grandi errori in x: il sistema è mal condizionato.

# Well-conditioned matrix
A_good <- matrix(c(2, 1, 1, 3), nrow = 2, byrow = TRUE)
kappa(A_good)  # Small -> good

# Ill-conditioned (nearly singular) matrix
A_bad <- matrix(c(1.000, 1.001,
                  1.001, 1.002), nrow = 2, byrow = TRUE)
kappa(A_bad)  # Very large -> bad!

# Rule of thumb: kappa > 1/machine_epsilon is trouble
.Machine$double.eps  # ~2.2e-16

# For A_bad: you lose about log10(kappa) digits of precision
cat('Digits lost:', log10(kappa(A_bad)), '\n')

backsolve() per matrici triangolari superiori

backsolve(R, b) risolve Rx = b quando R è triangolare superiore, utilizzando la sostituzione all'indietro. È molto più veloce di solve() per i sistemi triangolari: O(n²) invece di O(n³).

# Upper triangular system: Rx = b
# 2x + 3y + z = 14
#      5y + 2z = 13
#           4z = 8
R <- matrix(c(2, 3, 1,
              0, 5, 2,
              0, 0, 4), nrow = 3, byrow = TRUE)
b <- c(14, 13, 8)

# Solve using back-substitution
x <- backsolve(R, b)
print(x)  # z=2, y=(13-4)/5=9/5, x=(14-3*9/5-2)/2

# Verify
all.equal(as.vector(R %*% x), b)  # TRUE

# Compare with general solve
x_general <- solve(R, b)
all.equal(x, x_general)  # TRUE (same result)

forwardsolve() per matrici triangolari inferiori

forwardsolve(L, b) risolve Lx = b quando L è triangolare inferiore, utilizzando la sostituzione in avanti. Completa backsolve() e, insieme, costituisce la base dei risolutori basati sulla decomposizione LU.

# Lower triangular system: Lx = b
# 3x            = 6
# 2x + 4y       = 10
# x  + 2y + 5z  = 16
L <- matrix(c(3, 0, 0,
              2, 4, 0,
              1, 2, 5), nrow = 3, byrow = TRUE)
b <- c(6, 10, 16)

# Solve using forward-substitution
x <- forwardsolve(L, b)
print(x)  # x=2, y=(10-4)/4=1.5, z=(16-2-3)/5=2.2

# Verify
all.equal(as.vector(L %*% x), b)  # TRUE

# Use case: solving L*U*x = b
# forwardsolve(L, b) -> y, then backsolve(U, y) -> x

Più termini noti

solve(A, B), dove B è una matrice, risolve simultaneamente AX = B per tutte le colonne di B. È più efficiente che chiamare solve(A, b) separatamente per ogni colonna.

A <- matrix(c(2, 1,
              1, 3), nrow = 2, byrow = TRUE)

# Solve for two right-hand sides simultaneously
B <- matrix(c(5, 7,   # first system
              3, 1),  # second system
            nrow = 2, byrow = TRUE)

# X[:,1] solves Ax = B[:,1]
# X[:,2] solves Ax = B[:,2]
X <- solve(A, B)
print(X)

# Verify both solutions
A %*% X  # Should equal B
all.equal(A %*% X, B)  # TRUE

Rilevamento delle matrici singolari

La chiamata a solve(A) su una matrice singolare genera un errore. Controlli det(A) o rcond(A) (il reciproco del numero di condizionamento) prima di risolvere il sistema. Utilizzi tryCatch() per scrivere codice robusto.

# Singular matrix (rows are linearly dependent)
S <- matrix(c(1, 2,
              2, 4), nrow = 2, byrow = TRUE)
det(S)     # 0 -> singular
kappa(S)   # Inf

# Safe solve with tryCatch
safe_solve <- function(A, b) {
  tryCatch(
    solve(A, b),
    error = function(e) {
      cat('Matrix is singular or nearly so:\n')
      cat(e$message, '\n')
      return(NULL)
    }
  )
}

result <- safe_solve(S, c(1, 2))
print(result)  # NULL

Minimi quadrati con solve()

Per i sistemi sovradeterminati (con più equazioni che incognite) non esiste una soluzione esatta. La soluzione ai minimi quadrati minimizza ||Ax - b||². Risolve le equazioni normali: A'Ax = A'b.

# Overdetermined: 4 equations, 2 unknowns (y = a + b*x)
set.seed(1)
x_vals <- c(1, 2, 3, 4)
y_vals <- c(2.1, 4.0, 5.9, 8.2)  # approx y = 0 + 2x
A <- cbind(1, x_vals)  # Design matrix (4x2)
b <- y_vals

# Normal equations: (A'A) beta = A'b
AtA <- crossprod(A)
Atb <- crossprod(A, b)
beta_ols <- solve(AtA, Atb)
print(beta_ols)  # Intercept ~0.1, slope ~2.0

# Residual sum of squares
y_hat <- A %*% beta_ols
rss <- sum((b - y_hat)^2)
cat('RSS:', rss)

Utilizzo di qr.solve() per la stabilità

qr.solve(A, b) è numericamente più stabile di solve() per i sistemi mal condizionati o sovradeterminati. Utilizza la decomposizione QR anziché LU. lm() la utilizza internamente.

# For overdetermined system, qr.solve is preferred
x_vals <- c(1, 2, 3, 4, 5)
y_vals <- c(1.9, 4.1, 6.0, 7.8, 10.1)
A <- cbind(1, x_vals)
b <- y_vals

# qr.solve handles overdetermined systems directly
beta_qr <- qr.solve(A, b)
print(beta_qr)  # intercept, slope

# Equivalent to:
beta_lm <- coef(lm(y_vals ~ x_vals))
all.equal(beta_qr, beta_lm, check.names = FALSE)  # TRUE

# For well-determined square systems, solve() is fine
# For overdetermined or ill-conditioned: use qr.solve()

Verifica rapida

Verifichi la Sua comprensione della risoluzione dei sistemi lineari in R.

Riepilogo: risoluzione dei sistemi lineari

Punti fondamentali: solve(A, b) risolve direttamente Ax=b (ed è l'approccio consigliato). solve(A) calcola A⁻¹ (lo eviti per risolvere sistemi). backsolve(R,b) e forwardsolve(L,b) sono veloci per i sistemi triangolari. kappa(A) misura il condizionamento: valori elevati indicano soluzioni instabili. Per i sistemi sovradeterminati utilizzi qr.solve(). Verifichi sempre il risultato con A %*% x - b.

# Summary of solve() functions:
A <- matrix(c(3, 1, 1, 2), nrow = 2)
b <- c(9, 8)

# Solve Ax = b
x <- solve(A, b)
print(x)  # c(2, 3)

# Check conditioning
kappa(A)  # Small -> well-conditioned

# Verify
max(abs(A %*% x - b))  # Near zero

# For triangular systems:
R <- matrix(c(2, 3, 0, 4), nrow = 2, byrow = TRUE)
backsolve(R, c(8, 4))  # x=c(1, 1)

# For least squares (overdetermined):
# qr.solve(design_matrix, y)

Domande Frequenti

La lezione «Risoluzione di sistemi lineari con solve()» è gratuita?

Sì — il testo completo di «Risoluzione di sistemi lineari con solve()» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso R Academy, passa a CoddyKit PRO. Il corso R Academy include 4 lezioni in totale.

Cosa imparerò in «Risoluzione di sistemi lineari con solve()»?

Trovi soluzioni per i sistemi Ax = b e calcoli le inverse delle matrici Eserciti R Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare R Academy?

Non è richiesta alcuna esperienza precedente. R Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «Risoluzione di sistemi lineari con solve()»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione R Academy?

Sì. Ogni lezione R Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Moltiplicazione di matrici e determinanti
  2. Risoluzione di sistemi lineari con solve()
  3. Autovalori e autovettori
  4. Decomposizioni SVD, QR e di Cholesky
← Torna a R Academy