Ich würde normalerweise nicht halte ein totes Pferd zu schlagen, aber es kommt vor, dass mein nicht vektorisiert Ansatz Ihre andere Frage zu lösen, einen gewissen Wert hat, wenn die Dinge groß werden. Da ich die Koeffizientenmatrix tatsächlich einen Punkt nach dem anderen füllte, ist es sehr einfach, in ein COO-Sparse-Matrix-Format zu übersetzen, das effizient in CSC umgewandelt und gelöst werden kann. Die folgende tut es:
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)
Es ist natürlich viel ausführlicher, als es von vektorisiert Bauklötze, als TheodorosZelleke tut, aber eine interessante Sache passiert, wenn Sie Zeit beide Ansätze:
Erstens, und das ist (sehr) schön, skaliert die Zeit in beiden Lösungen linear, wie man es von der Sparse-Methode erwarten würde. Aber die Lösung, die ich in dieser Antwort gegeben habe, ist immer schneller, eher für größere n
s. Zum Spaß habe ich auch TheodorosZellekes dichteren Ansatz von der anderen Frage aus verfolgt, die diesen schönen Graphen zeigt, der die unterschiedliche Skalierung beider Arten von Lösungen zeigt, und wie sehr früh irgendwo um n = 75
die Lösung hier Ihre Wahl sein sollte:
ich weiß nicht genug über scipy.sparse
wirklich um herauszufinden, warum die Unterschiede zwischen den beiden spärlichen Ansätze, obwohl ich vermute stark von der Verwendung von LIL Format schwach besetzte Matrizen. Es kann einen sehr marginalen Leistungszuwachs geben, wenn auch eine Menge Kompaktheit im Code, indem TheodorosZellekes Antwort in ein COO-Format umgewandelt wird. Aber das ist eine Übung für das OP!
Sie nennen es, ein totes Pferd zu schlagen, aber ich nenne es faszinierend und immens hilfreich. Danke dafür! – lip1