Banyak persoalan data berujung pada pencarian beberapa nilai sekaligus dari sekumpulan persamaan linear, misalnya menaksir harga satuan dari beberapa nota belanja atau menyeimbangkan aliran antar pos pembukuan. Topik ini membahas bentuk matriks , penyelesaiannya dengan np.linalg.solve, syarat matriks koefisiennya, verifikasi solusi dengan np.allclose, serta alasan solve lebih diutamakan daripada perhitungan invers. Setelah topik ini dipahami, sistem persamaan kecil maupun besar dapat diselesaikan dan diverifikasi dengan pola kode yang sama.
Bentuk matriks A x = b#
Sistem persamaan linear yang ringkas dapat ditulis ulang sebagai satu perkalian matriks. Vektor x memuat nilai-nilai yang dicari, matriks A memuat koefisien setiap persamaan pada barisnya masing-masing, sedangkan vektor b memuat sisi kanan setiap persamaan. Semua informasi sistem dengan demikian terangkum dalam dua array, dan penyelesaiannya menjadi urusan satu fungsi.
Contoh berikut memuat dua nota belanja. Nota pertama berisi dua pensil dan tiga buku dengan total 19000, sedangkan nota kedua berisi satu pensil dan dua buku dengan total 11000. Apabila menyatakan harga satu pensil dan menyatakan harga satu buku, sistemnya dituliskan sebagai berikut.
Bentuk di kanan adalah bentuk matriks yang diminta oleh NumPy, yaitu A sebagai array dua dimensi dan b sebagai array satu dimensi. Pemetaan dari persamaan ke matriks bersifat langsung, yaitu setiap baris A diambil dari koefisien satu persamaan dengan urutan yang sama seperti urutan angka pada b. Penulisan ini pula yang memungkinkan sistem dengan puluhan variabel diperlakukan dengan kode yang persis sama.
Menyelesaikan dengan linalg.solve#
Fungsi np.linalg.solve(A, b) mengembalikan vektor x yang memenuhi . Fungsi ini menuntut A berupa matriks persegi yang berperingkat penuh, yaitu banyaknya persamaan sama dengan banyaknya variabel dan tidak ada persamaan yang merupakan kelipatan atau gabungan dari persamaan lain.
import numpy as np
A = np.array([[2.0, 3.0],
[1.0, 2.0]])
b = np.array([19000.0, 11000.0])
x = np.linalg.solve(A, b)
print(x)[5000. 3000.]Hasilnya menyatakan harga satu pensil bernilai 5000 dan satu buku bernilai 3000. Nilai tersebut dapat dicek dengan substitusi, yaitu untuk nota pertama. Pengecekan semacam ini sebaiknya dilakukan oleh kode, bukan oleh mata, karena perhitungan pecahan pada komputer dibulatkan di setiap langkahnya.
import numpy as np
A = np.array([[2.0, 3.0],
[1.0, 2.0]])
b = np.array([19000.0, 11000.0])
x = np.linalg.solve(A, b)
print(np.round(A @ x, 6))
print(np.allclose(A @ x, b))[19000. 11000.]
TruePola verifikasinya adalah menghitung A @ x lalu membandingkannya dengan b menggunakan np.allclose, yaitu fungsi perbandingan pecahan yang menoleransi selisih pembulatan sekecil apa pun dalam batas wajar. Pembanding == tidak digunakan untuk tujuan ini, dan alasannya dibahas pada bagian Kesalahan umum.
Sistem dengan tiga variabel#
API yang sama berlaku tanpa perubahan untuk sistem yang lebih besar. Setiap baris pada A mewakili satu persamaan, sedangkan setiap kolomnya mewakili satu variabel, sehingga sistem tiga persamaan tiga variabel ditulis sebagai matriks 3x3 dengan vektor hasil sepanjang tiga. Syaratnya tetap, yaitu A persegi dan berperingkat penuh, sedangkan b mengikuti banyaknya baris A.
import numpy as np
A = np.array([[1.0, 2.0, 1.0],
[2.0, 1.0, 1.0],
[1.0, 1.0, 2.0]])
b = np.array([9.0, 8.0, 7.0])
x = np.linalg.solve(A, b)
print(x)
print(np.allclose(A @ x, b))[2. 3. 1.]
TrueKode di atas sama persis dengan versi dua variabel, hanya bentuk operandnya yang berubah, sehingga penambahan variabel tidak menambah kerumitan kode. Banyaknya persamaan juga dapat lebih banyak daripada variabelnya, tetapi kasus itu tidak lagi cocok untuk solve karena sistemnya tidak menentukan satu solusi tunggal. NumPy menyediakan np.linalg.lstsq untuk kasus berlebih tersebut, yaitu pencarian solusi yang meminimalkan jumlah kuadrat sisanya, dan pembahasannya berada di luar lingkup topik ini. Nilai pada A dan b ditulis dengan tanda desimal agar perhitungan berjalan pada dtype float64, mengikuti kebiasaan yang sama seperti sistem dua variabel pada bagian sebelumnya.
Matriks singular dan error LinAlgError#
Matriks koefisien disebut singular apabila salah satu barisnya merupakan kelipatan baris lain, sehingga sistemnya kehilangan informasi dan tidak memiliki solusi tunggal. Fungsi solve menolak kasus ini dengan LinAlgError, seperti pada matriks yang baris keduanya dua kali baris pertamanya berikut.
import numpy as np
A = np.array([[1.0, 2.0],
[2.0, 4.0]])
b = np.array([3.0, 6.0])
try:
x = np.linalg.solve(A, b)
print(x)
except Exception as e:
print(f"{type(e).__name__}: {e}")LinAlgError: Singular matrixPesan Singular matrix menegaskan bahwa masalahnya ada pada A, bukan pada b, sehingga mengubah nilai b tidak akan pernah memperbaiki kasus ini. Pada matriks contoh, persamaan keduanya hanyalah dua kali persamaan pertamanya, sehingga kedua persamaan itu sesungguhnya menyatakan satu hal yang sama. Kode yang menerima matriks dari data eksternal sebaiknya membungkus pemanggilan solve dengan try dan except, karena singularitas sering baru terlihat saat eksekusi dan error ini mudah ditangani secara terprogram.
Mengapa solve, bukan invers#
Cara lain yang secara matematis setara adalah menghitung invers dengan np.linalg.inv, lalu mengalikannya dengan b, karena . Keluaran kedua cara ini sama untuk sistem yang kecil dan sehat.
import numpy as np
A = np.array([[2.0, 3.0],
[1.0, 2.0]])
b = np.array([19000.0, 11000.0])
x_solve = np.linalg.solve(A, b)
x_inv = np.linalg.inv(A) @ b
print(np.round(x_solve, 6))
print(np.round(x_inv, 6))
print(np.allclose(x_solve, x_inv))[5000. 3000.]
[5000. 3000.]
TrueMeskipun hasilnya sama, solve tetap menjadi pilihan utama. Secara internal, solve memfaktorkan A dengan dekomposisi LU, lalu menyelesaikan dua sistem segitiga, sedangkan jalur invers membentuk matriks invers secara penuh terlebih dahulu sebelum mengalikannya. Jalur pertama memerlukan operasi aritmetika yang lebih sedikit dan mengakumulasi kesalahan pembulatan yang lebih kecil, terutama pada matriks besar atau matriks yang mendekati singular. Karena itu, kebiasaan yang dianjurkan adalah menggunakan solve untuk semua persoalan dan menyisakan inv untuk kasus yang benar-benar membutuhkan matriks inversnya sendiri.
Kesalahan umum#
Kesalahan pertama adalah memverifikasi solusi dengan ==. Perbandingan persis pada pecahan bergantung pada hasil pembulatan tahap akhir, sehingga sistem yang sama dapat lolos atau gagal bergantung pada angkanya.
import numpy as np
A = np.array([[2.5, 1.5],
[1.5, 3.5]])
b = np.array([7.0, 8.0])
x = np.linalg.solve(A, b)
print(np.round(x, 6))
print(A @ x == b)
print(np.allclose(A @ x, b))[1.923077 1.461538]
[False False]
TrueSolusi pada contoh itu sudah benar, tetapi A @ x == b tetap bernilai False karena sisa pembulatan, sedangkan np.allclose menilai keduanya sama dengan tepat. Perbaikannya adalah menjadikan np.allclose sebagai pembanding baku untuk semua hasil pecahan.
Kesalahan kedua adalah menghitung np.linalg.inv terlebih dahulu padahal tujuan akhirnya adalah nilai x. Kebiasaan ini membebani perhitungan dengan operasi yang tidak diperlukan dan menambah peluang kesalahan pembulatan, sehingga pemanggilannya diganti langsung dengan np.linalg.solve.
Kesalahan ketiga adalah membiarkan LinAlgError tidak ditangani pada data yang berasal dari luar. Sistem yang disusun dari data pengukuran dapat saja memiliki baris ganda, dan program yang membungkus solve dengan try serta except dapat melaporkan persoalannya dengan rapi, alih-alih berhenti mendadak.
Ringkasan#
- Sistem persamaan linear ditulis sebagai , yaitu matriks koefisien persegi
A, vektor variabelx, dan vektor sisi kananb. np.linalg.solve(A, b)mengembalikan solusi tunggal apabilaAberperingkat penuh, dan memunculkanLinAlgErrorberupaSingular matrixapabila tidak.- Solusi diverifikasi dengan menghitung
A @ xlalu membandingkannya denganbmenggunakannp.allclose, bukan==. solvediutamakan daripadainvkarena memerlukan operasi lebih sedikit dan mengakumulasi kesalahan pembulatan yang lebih kecil.
Referensi#
- numpy.linalg.solve — NumPy — Dokumentasi resmi fungsi penyelesaian sistem persamaan linear beserta syarat matriksnya.
- numpy.linalg.inv — NumPy
— Dokumentasi resmi perhitungan invers yang dibandingkan dengan
solvepada topik ini.