실습 · 연습문제 2개
conjugate gradient 구현 conjugate-gradient
대칭 양의 정부호(SPD) 행렬 에 대한 선형시스템 를 conjugate gradient(CG)로 푼다. CG는 의 원소가 아니라 행렬–벡터 곱 만 쓴다.
, , 에서 시작해 다음을 반복한다.
함수 conjugate_gradient(matvec, b, tol=1e-10, max_iter=1000)를 완성한다.
matvec은 벡터v를 받아A @ v를 돌려주는 함수다. 행렬 자체는 주어지지 않는다.- 상대 잔차 가
tol이하가 되면 멈춘다. 시작할 때 이미 만족하면 반복하지 않는다. (x, n_iter)를 반환한다.n_iter는 수행한 반복(위 갱신) 횟수다.matvec은 반복마다 한 번만 호출한다(테스트가 호출 횟수를 센다). 를 변수에 담아 와 계산에 함께 쓴다.
정확한 산술에서 CG는 시스템을 최대 번 안에 푼다. 테스트는 결과의 정확도, 반복 수, matvec 호출 수를 확인한다.
CSR 형식의 행렬–벡터 곱 csr-matvec
CSR(compressed sparse row) 형식은 희소 행렬을 세 배열로 저장한다.
data: 0이 아닌 값들을 행 순서대로 이어 붙인 배열 (길이 nnz)indices: 각 값의 열 번호 (길이 nnz)indptr: 행 의 값이data[indptr[i]:indptr[i+1]]에 있음을 알려 주는 포인터 (길이 )
예를 들어
은 data = [4, 1, 2, 3], indices = [0, 2, 0, 1], indptr = [0, 2, 2, 4]다. 둘째 행은 비어 있어 indptr[1] == indptr[2]이다.
함수 csr_matvec(data, indices, indptr, x)를 완성해 를 반환한다.
- 행의 수는
len(indptr) - 1이다. 반환 shape은(m,)이다. scipy.sparse나 dense 행렬을 만들지 않고 세 배열만으로 계산한다.- 빈 행의 결과는 0이다.
힌트: 행 에 대해 data[indptr[i]:indptr[i+1]]와 x[indices[indptr[i]:indptr[i+1]]]의 내적을 구한다. 계산량은 nnz에 비례하고 과는 무관하다.