nie będę normalnie zachować pokonując martwego konia, ale zdarza się, że mój non-wektorowy podejście do rozwiązywania inne pytanie, ma pewne zasługi, gdy sprawy być wielkim. Ponieważ faktycznie wypełniałem macierz współczynników po jednym elemencie na raz, bardzo łatwo jest przetłumaczyć na rzadki format macierzy COO, który można skutecznie przekształcić w CSC i rozwiązać. Dodaje się robi:
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)
Jest oczywiście dużo bardziej gadatliwy niż budowanie go od vectorized bloków, tak jak TheodorosZelleke, ale ciekawa rzecz dzieje się, gdy czas obu podejść:
Po pierwsze, a to jest (bardzo) miłe, czas skaluje się liniowo w obu rozwiązaniach, tak jak można by się spodziewać, stosując rzadkie podejście. Ale rozwiązanie, które dałem w tej odpowiedzi, jest zawsze szybsze, bardziej dla większych n
s. Dla samej zabawy, odmieniłem także gęste podejście TheodorosZelleke'a z drugiego pytania, które daje ten przyjemny wykres pokazujący różne skalowanie obu typów rozwiązań i jak bardzo wcześnie, gdzieś w okolicach n = 75
, rozwiązanie tutaj powinno być twoim wyborem:
nie wiem wystarczająco dużo o scipy.sparse
aby naprawdę zrozumieć, dlaczego różnice między tymi dwoma podejściami rzadkie, chociaż podejrzewam, że ciężko z wykorzystaniem formatu LIL rozrzedzony matryc. Może pojawić się niewielki wzrost wydajności, pomimo dużej zwartości kodu, poprzez przekształcenie odpowiedzi TheodorosZelleke na format COO. Ale to jest pozostawione jako ćwiczenie dla OP!
Nazywasz to biciem martwego konia, ale ja to nazywam fascynującym i ogromnie pomocnym. Dzięki za zrobienie tego! – lip1