Io normalmente non tenere battere un cavallo morto, ma succede che il mio approccio non vettorializzare per risolvere il vostro altra domanda, ha qualche merito, quando le cose diventa grande. Poiché in realtà stavo compilando la matrice dei coefficienti un elemento alla volta, è molto facile tradurre in un formato a matrice sparsa COO, che può essere efficientemente trasformato in CSC e risolto. Di seguito lo fa:
import scipy.sparse
def sps_solve(n) :
# Solution vector is [N[0], N[1], ..., N[n - 2], M[1], M[2], ..., M[n - 1]]
n_pos = lambda p : p
m_pos = lambda p : p + n - 2
data = []
row = []
col = []
# p = 0
# n * N[0] + (1 - n) * M[n-1] = n
row += [n_pos(0), n_pos(0)]
col += [n_pos(0), m_pos(n - 1)]
data += [n, 1 - n]
for p in xrange(1, n - 1) :
# n * M[p] + (1 + p - n) * M[n - 1] - 2 * N[p - 1] +
# (1 - p) * M[p - 1] = n
row += [m_pos(p)] * (4 if p > 1 else 3)
col += ([m_pos(p), m_pos(n - 1), n_pos(p - 1)] +
([m_pos(p - 1)] if p > 1 else []))
data += [n, 1 + p - n , -2] + ([1 - p] if p > 1 else [])
# n * N[p] + (1 + p -n) * M[n - 1] - p * N[p - 1] = n
row += [n_pos(p)] * 3
col += [n_pos(p), m_pos(n - 1), n_pos(p - 1)]
data += [n, 1 + p - n, -p]
if n > 2 :
# p = n - 1
# n * M[n - 1] - 2 * N[n - 2] + (2 - n) * M[n - 2] = n
row += [m_pos(n-1)] * 3
col += [m_pos(n - 1), n_pos(n - 2), m_pos(n - 2)]
data += [n, -2, 2 - n]
else :
# p = 1
# n * M[1] - 2 * N[0] = n
row += [m_pos(n - 1)] * 2
col += [m_pos(n - 1), n_pos(n - 2)]
data += [n, -2]
coeff_mat = scipy.sparse.coo_matrix((data, (row, col))).tocsc()
return scipy.sparse.linalg.spsolve(coeff_mat,
np.ones(2 * (n - 1)) * n)
Naturalmente è molto più dettagliato che costruire da blocchi vettoriale, come fa TheodorosZelleke, ma una cosa interessante accade quando il tempo entrambi gli approcci:
Innanzitutto, e questo è (molto) bello, il tempo scala in modo lineare in entrambe le soluzioni, come ci si aspetterebbe dall'utilizzo dell'approccio sparse. Ma la soluzione che ho dato in questa risposta è sempre più veloce, soprattutto per i più grandi n
s. Solo per il gusto di farlo, ho anche cronometrato l'approccio denso di TheodorosZelleke dall'altra domanda, che dà questo bel grafico che mostra il diverso ridimensionamento di entrambi i tipi di soluzioni, e quanto molto presto, da qualche parte intorno a n = 75
, la soluzione qui dovrebbe essere la vostra scelta:
non so abbastanza di scipy.sparse
per capire davvero il motivo per cui le differenze tra i due approcci sparse, anche se ho il sospetto fortemente l'uso di formato LIL matrici sparse. Ci può essere un guadagno di guadagno molto marginale, anche se molta compattezza nel codice, trasformando la risposta di TheodorosZelleke in formato COO. Ma questo è lasciato come esercizio per l'OP!
Lo chiami battere un cavallo morto ma io lo chiamo affascinante e immensamente utile. Grazie per averlo fatto! – lip1