8  Komputasi Eksak dan Simbolik

8.1 Tujuan belajar

Setelah menyelesaikan unit ini, pembaca dapat:

  • membedakan ekspresi simbolik dari nilai hasil substitusi;
  • memakai Fraction dan SymPy untuk mempertahankan hasil eksak;
  • menyatakan asumsi dan domain sebelum menyederhanakan ekspresi;
  • memeriksa ekuivalensi aljabar tanpa menghapus pembatasan domain;
  • memfaktorkan dan menyelesaikan persamaan sederhana secara eksak;
  • menjelaskan batas antara hasil sistem aljabar komputer dan bukti matematis;
  • menghasilkan rekaman simbolik kanonis yang dapat dibandingkan byte demi byte; dan
  • memakai SageMath lokal untuk ZZ, QQ, RR, SR, parent dan coercion, gelang polinom, faktorisasi, penyelesaian eksak, serta konversi pendekatan yang dinyatakan.

Prasyarat lokal: Unit 1 dan Unit 2, operasi polinomial, persamaan kuadrat, dan pengertian domain fungsi. Jalur pertama memakai pustaka standar Python dan SymPy; lab SageMath 9.5 lokal merupakan bagian wajib unit. Tidak diperlukan kalkulus atau aljabar linear.

8.2 Ekspresi bukan nilai

Ekspresi

p(x)=x21 p(x)=x^2-1

memuat simbol bebas xx. Ia belum mempunyai satu nilai numerik. Substitusi x=3x=3 menghasilkan nilai eksak 88, tetapi tidak mengubah ekspresi asal menjadi bilangan.

import sympy as sp

x = sp.Symbol("x")
p = x**2 - 1
(p, p.free_symbols, p.subs(x, 3))
Daftar 8.1
(x**2 - 1, {x}, 8)

Perbedaan ini penting bagi notebook yang dijalankan tidak berurutan. Nama x dalam kode dapat menunjuk objek Python, sedangkan simbol SymPy bernama x merupakan bagian dari pohon ekspresi. Tampilkan dan simpan pohon yang sebenarnya dipakai, bukan hanya hasil terakhir di layar.

Untuk bilangan rasional kecil, pustaka standar sudah cukup:

from fractions import Fraction

Fraction(1, 10) + Fraction(2, 10)
Daftar 8.2
Fraction(3, 10)

Fraction(3, 10) dan sp.Rational(3, 10) sama-sama mempertahankan nilai rasional eksak. Pilih batas antarpustaka secara eksplisit; jangan mengubahnya menjadi float hanya untuk memperoleh keluaran yang tampak lebih pendek.

8.3 Asumsi dan domain adalah bagian dari soal

Tanpa keterangan tanda, rumus x2=x\sqrt{x^2}=x tidak benar untuk setiap bilangan real. Jika xx real, hasil yang benar ialah |x||x|. Jika x>0x>0, barulah hasilnya xx.

x_real = sp.Symbol("x", real=True)
x_positive = sp.Symbol("x", positive=True)

(
    sp.simplify(sp.sqrt(x_real**2)),
    sp.simplify(sp.sqrt(x_positive**2)),
)
Daftar 8.3
(Abs(x), x)

Nama cetak kedua simbol sama, tetapi asumsi internalnya berbeda. Oleh sebab itu, sebuah rekaman komputasi simbolik harus menyimpan definisi simbol atau pernyataan domain yang menyertainya.

Domain juga harus dipertahankan ketika faktor dibatalkan. Untuk

r(x)=x21x1, r(x)=\frac{x^2-1}{x-1},

SymPy memperoleh x+1x+1 setelah pembatalan. Kedua rumus memberi nilai sama pada domain bersama, yaitu x1x\ne1. Namun, keduanya bukan fungsi yang sama jika domain asal ikut menjadi bagian definisi: rumus asal tidak terdefinisi pada x=1x=1, sedangkan x+1x+1 bernilai 22 di sana.

8.4 Kesamaan struktur dan ekuivalensi

Operator == pada dua ekspresi SymPy terutama membandingkan struktur kanonisnya. Ia bukan pertanyaan universal “apakah kedua rumus ini mempunyai nilai sama bagi semua masukan yang sah?”. Contohnya, ekspresi (x+1)2(x+1)^2 dan x2+2x+1x^2+2x+1 mempunyai struktur berbeda tetapi merupakan polinom yang sama.

left = (x + 1) ** 2
right = x**2 + 2*x + 1

structurally_equal = left == right
polynomial_identity = sp.expand(left - right) == 0
(structurally_equal, polynomial_identity)
Daftar 8.4
(False, True)

Prosedur pemeriksaan harus sesuai dengan kelas ekspresi. Ekspansi selisih cocok untuk identitas polinomial. simplify(left-right) == 0 berguna sebagai pemeriksaan lain, tetapi bukan pengganti pencatatan domain, cabang akar, asumsi, atau titik singular.

8.5 Faktorisasi dan penyelesaian eksak

Komputasi simbolik mempertahankan akar dan faktor tanpa pendekatan desimal.

x = sp.Symbol("x")
polynomial = x**4 - 1
factored = sp.factor(polynomial)
(factored, sp.expand(factored) == polynomial)
Daftar 8.5
((x - 1)*(x + 1)*(x**2 + 1), True)

Faktorisasi yang diharapkan ialah

(x1)(x+1)(x2+1). (x-1)(x+1)(x^2+1).

Pemeriksaan dengan expand menguji bahwa hasil tersebut kembali menjadi polinom masukan. Untuk persamaan x2=2x^2=2, domain solusi harus dinyatakan:

x = sp.Symbol("x", real=True)
solutions = sp.solveset(sp.Eq(x**2, 2), x, domain=sp.S.Reals)
solutions
Daftar 8.6

{2,2}\displaystyle \left\{- \sqrt{2}, \sqrt{2}\right\}

Hasil real eksaknya adalah {2,2}\{-\sqrt{2},\sqrt{2}\}. Substitusi setiap kandidat ke x22x^2-2 harus memberikan residual eksak nol. Jika domain diubah, bentuk atau jumlah solusi dapat berubah; karena itu, jangan menyimpan daftar akar tanpa persamaan dan domainnya.

8.6 Hasil simbolik dan bukti

Keluaran sistem aljabar komputer mempunyai beberapa peran yang berbeda:

  • kandidat: solve mengusulkan nilai yang kemudian dapat diperiksa;
  • sertifikat lokal: ekspansi kembali atau substitusi residual memeriksa hubungan tertentu;
  • eksperimen: banyak contoh dapat menguji sebuah dugaan; dan
  • bukti: argumen menjelaskan mengapa klaim berlaku pada seluruh domain.

Faktorisasi x41x^4-1 dapat diperiksa langsung dengan distributivitas. Namun, keberhasilan satu perintah tidak membuktikan bahwa setiap keluaran algoritme untuk setiap masukan pasti benar. Klaim lebih luas juga bergantung pada spesifikasi algoritme dan kebenaran implementasinya. Dalam tulisan matematis, nyatakan tepatnya hubungan mana yang diperiksa komputer dan langkah umum mana yang dibuktikan secara matematis.

8.7 Keluaran kanonis

Tampilan dua dimensi yang nyaman dibaca dapat berubah karena lebar terminal, pengaturan printer, atau versi pustaka. Unit ini memakai sympy.srepr untuk merekam pohon ekspresi dan JSON dengan kunci terurut, inden tetap, UTF-8, serta akhir baris LF. Versi SymPy ikut disimpan karena bentuk kanonis pustaka dapat berubah antarrilis.

Jalankan skrip dari akar proyek:

python source/code/unit05_symbolic.py --output output/unit05-results.json

Medan core_sha256 mengikat rekaman inti sebelum medan hash ditambahkan. Menjalankan perintah yang sama pada lingkungan yang sama harus menghasilkan byte identik. Hash bukan bukti kebenaran matematika; ia membuktikan bahwa dua urutan byte sama.

8.8 Lab SageMath lokal wajib

SageMath menyatukan banyak struktur matematika dalam satu sistem yang memakai sintaks Python. Dalam unit ini, Sage bukan layanan web dan bukan potongan opsional. Lab dijalankan lokal dengan SageMath 9.5 yang dibekukan di WSL Ubuntu 22.04. SageCell atau layanan jarak jauh tidak memenuhi persyaratan karena runtime, ketersediaan jaringan, dan byte hasilnya tidak berada di bawah kendali eksperimen lokal.

Jika profil itu belum tersedia, ikuti panduan penyiapan lokal dan jalankan verifikasi lock sebelum lab. Perbedaan versi harus dicatat; jangan menyebut profil yang berbeda sebagai lingkungan rilis yang identik.

Dari akar proyek pada PowerShell, jalankan:

wsl.exe -d Ubuntu-22.04 -- /usr/bin/sage -python source/code/unit05_sage_lab.py --output output/unit05-sage-results.json
wsl.exe -d Ubuntu-22.04 -- /usr/bin/sage -python tests/test_unit05_sage.py

Perintah pertama menulis JSON deterministik ke jalur relatif yang diberikan. Perintah kedua menjalankan seluruh tes lab di runtime yang sama. Blok Sage di pembaca ini sengaja berupa pagar python biasa, bukan blok Quarto {python}. Karena itu, build Windows tidak mencoba mengimpor Sage melalui kernel Python biasa.

8.8.1 Parent menentukan tempat objek hidup

Sage menanyakan parent() suatu objek, bukan hanya tipe implementasi Python. Empat parent inti lab ini adalah:

Nama Parent matematika Peran
ZZ gelang bilangan bulat aritmetika bulat eksak
QQ lapangan bilangan rasional pembagian rasional eksak
RR lapangan real 53 bit pendekatan titik-mengambang
SR gelang simbolik ekspresi dan persamaan simbolik
from sage.all import QQ, RR, SR, ZZ

bilangan_bulat = ZZ(6)
rasional = QQ(1) / 3
pendekatan = RR(rasional)
simbolik = SR(rasional)

print(bilangan_bulat.parent())
print(rasional.parent())
print(pendekatan.parent())
print(simbolik.parent())

Nilai cetak saja tidak cukup. 1/3 dalam QQ merupakan nilai eksak, sedangkan nilai dalam RR adalah pendekatan pada presisi parent-nya.

8.8.2 Coercion harus dapat dijelaskan

Coercion adalah konversi kanonis yang dipilih Sage ketika operasi mencampurkan parent. Misalnya, ZZ(6) + QQ(1)/3 hidup di QQ karena ada peta kanonis dari ZZ ke QQ. Lab memeriksa peta ZZ ke QQ, QQ ke RR, dan QQ ke SR secara eksplisit.

from sage.all import QQ, RR, SR, ZZ

assert QQ.has_coerce_map_from(ZZ)
assert RR.has_coerce_map_from(QQ)
assert SR.has_coerce_map_from(QQ)
campuran = ZZ(6) + QQ(1) / 3
assert campuran.parent() is QQ

Coercion yang tersedia tidak berarti semua perubahan representasi tanpa kerugian. Pemetaan QQ ke RR mengubah rasional eksak menjadi pendekatan. Karena itu, kode ilmiah harus menuliskan titik konversinya.

8.8.3 Gelang polinom dan faktorisasi eksak

Parent polinom menyimpan gelang koefisien. PolynomialRing(QQ, "x") menyatakan polinom satu variabel dengan koefisien rasional. Ini lebih spesifik daripada sekadar ekspresi simbolik yang kebetulan tampak seperti polinom.

from sage.all import PolynomialRing, QQ

R = PolynomialRing(QQ, "x")
x = R.gen()
p = x**4 - 1
faktor = p.factor()

assert p.parent() is R
assert R.base_ring() is QQ
assert faktor.prod() == p
print(faktor)

Faktorisasi tepatnya (x1)(x+1)(x2+1)(x-1)(x+1)(x^2+1). Pemeriksaan prod() mengalikan faktor di dalam parent yang sama dan membandingkannya dengan polinom asal.

8.8.4 Penyelesaian dalam SR dan residual eksak

Untuk persamaan simbolik, domain dan parent masih harus dicatat. Lab memakai SR, meminta solusi berbentuk kamus, lalu mensubstitusikan setiap kandidat ke residual.

from sage.all import SR, solve

y = SR.var("y")
solusi = solve(y**2 == 2, y, solution_dict=True)
nilai = [baris[y] for baris in solusi]
assert all((akar**2 - 2).simplify_full() == 0 for akar in nilai)

Residual nol memeriksa dua kandidat yang dikembalikan. Ia tidak sendirinya membuktikan bahwa tidak ada solusi lain pada domain berbeda.

8.8.5 Konversi pendekatan harus eksplisit

Jangan mengubah objek eksak menjadi desimal hanya agar tampilannya pendek. Pertahankan objek asal dan tuliskan parent tujuan:

from sage.all import QQ, RR

eksak = QQ(1) / 3
hampiran = RR(eksak)
assert eksak.parent() is QQ
assert hampiran.parent() is RR
print(eksak, hampiran, RR.precision())

RR(eksak) adalah keputusan representasi yang dapat ditemukan dalam sumber. Rekaman lab menyimpan nilai eksak, teks konversi, nilai pendekatan, parent, dan presisi 53 bit.

8.8.6 Rekaman Sage yang dapat diaudit

unit05-sage-results.json mencatat SageMath 9.5, keharusan eksekusi lokal, parent, peta coercion, gelang polinom, faktor, solusi, residual, konversi ke RR, dan core_sha256. Semua objek diubah menjadi bentuk JSON yang ditentukan sebelum serialisasi. Dua eksekusi dengan runtime yang sama harus menghasilkan byte sama.

Skrip menolak versi selain 9.5. Pembatasan ini bukan klaim bahwa versi lain salah; ia mengikat bukti kerja pada runtime yang benar-benar diuji. Hasil SageMath tetap bukan pengganti bukti umum. Parent dan residual menjelaskan apa yang diperiksa oleh komputasi; argumen matematika menjelaskan mengapa klaim berlaku pada domainnya.

8.9 Latihan

8.9.1 Latihan 1 - ekspresi dan nilai

Bentuk ekspresi q(t)=t32tq(t)=t^3-2t di SymPy. Sebutkan simbol bebasnya, lalu evaluasi pada t=1/2t=1/2 secara eksak.

Gunakan Symbol, Rational, atribut free_symbols, dan subs.

Kode t=sp.Symbol("t"); q=t**3-2*t menghasilkan simbol bebas {t}. Substitusi q.subs(t, sp.Rational(1,2)) memberi 1/81=7/81/8-1=-7/8. Ekspresi q tetap memuat t; -7/8 adalah nilai pada satu masukan, bukan pengganti ekspresi asal.

8.9.2 Latihan 2 - asumsi yang hilang

Seorang pembaca menyederhanakan z2\sqrt{z^2} menjadi zz untuk semua bilangan real. Berikan contoh penyangkal dan tuliskan hasil umum yang benar.

Coba satu bilangan real negatif.

Ambil z=3z=-3. Maka z2=9=3\sqrt{z^2}=\sqrt{9}=3, sedangkan z=3z=-3, sehingga penyederhanaan itu gagal. Untuk zz real, bentuk umum yang benar ialah z2=|z|\sqrt{z^2}=|z|. Bentuk zz sah jika ditambahkan asumsi z0z\ge0, dan khusus simbol SymPy positif dapat dideklarasikan dengan positive=True.

8.9.3 Latihan 3 - ekuivalensi dan domain

Bandingkan (u24)/(u2)(u^2-4)/(u-2) dengan u+2u+2. Nyatakan pada himpunan mana nilainya sama dan jelaskan mengapa domain kedua fungsi tidak otomatis sama.

Faktorkan pembilang dan periksa penyebut sebelum membatalkan faktor.

Karena u24=(u2)(u+2)u^2-4=(u-2)(u+2), kedua rumus memberi nilai sama untuk setiap u2u\ne2. Rumus pecahan tidak terdefinisi pada u=2u=2, sementara u+2u+2 bernilai 44. Jadi keduanya setara pada domain bersama, tetapi bukan fungsi dengan domain yang sama kecuali pembatasan u2u\ne2 dipertahankan.

8.9.4 Latihan 4 - faktor, akar, dan pemeriksaan

Faktorkan v3vv^3-v, cari semua akar realnya secara eksak, lalu tuliskan dua pemeriksaan yang dapat dilakukan tanpa mempercayai tampilan keluaran.

Keluarkan faktor v, kemudian faktorkan selisih kuadrat.

v3v=v(v21)=v(v1)(v+1)v^3-v=v(v^2-1)=v(v-1)(v+1), sehingga akar realnya ialah (1,0,1)(-1,0,1). Pemeriksaan pertama: ekspansi v*(v-1)*(v+1) harus kembali ke v**3-v. Pemeriksaan kedua: substitusi setiap akar ke polinom harus memberi residual eksak nol. Kedua pemeriksaan ini mengikat klaim lokal yang jelas.

8.9.5 Latihan 5 - artefak simbolik yang stabil

Mengapa menyimpan hanya tangkapan layar keluaran pretty print tidak cukup untuk eksperimen simbolik yang dapat direproduksi? Sebutkan sedikitnya empat unsur rekaman yang lebih baik.

Pikirkan pohon ekspresi, asumsi, domain, versi, dan byte keluaran.

Tangkapan layar dapat kehilangan struktur, mudah berubah karena tata letak, dan tidak dapat dievaluasi ulang. Rekaman yang lebih baik memuat (1) pohon ekspresi kanonis, (2) asumsi simbol, (3) domain masalah, (4) versi SymPy atau SageMath, (5) masukan dan metode, serta (6) JSON atau format teks dengan aturan urutan dan akhir baris yang tetap. Hash kemudian dapat membandingkan byte, sedangkan residual atau ekspansi memeriksa klaim matematis tertentu.

8.9.6 Latihan Sage 1 - parent, coercion, dan faktor

Di SageMath 9.5 lokal, bentuk ZZ(5), QQ(2)/3, dan jumlah keduanya. Catat parent setiap objek dan jelaskan coercion yang terjadi. Lalu buat gelang QQ[z], faktorkan z41z^4-1, dan periksa bahwa hasil kali faktor kembali ke polinom asal.

Gunakan parent(), QQ.has_coerce_map_from(ZZ), PolynomialRing(QQ, "z"), serta metode factor() dan prod().

PentingPemeriksaan mandiri

Jalankan blok ini hanya melalui /usr/bin/sage -python, bukan kernel Quarto Windows.

from sage.all import PolynomialRing, QQ, ZZ

a = ZZ(5)
b = QQ(2) / 3
c = a + b
Rz = PolynomialRing(QQ, "z")
z = Rz.gen()
pz = z**4 - 1
fz = pz.factor()

assert a.parent() is ZZ
assert b.parent() is QQ
assert c.parent() is QQ
assert QQ.has_coerce_map_from(ZZ)
assert Rz.base_ring() is QQ
assert fz.prod() == pz
from sage.all import PolynomialRing, QQ, ZZ

bilangan_bulat = ZZ(5)
bilangan_rasional = QQ(2) / 3
hasil_campuran = bilangan_bulat + bilangan_rasional

assert str(bilangan_bulat.parent()) == "Integer Ring"
assert str(bilangan_rasional.parent()) == "Rational Field"
assert hasil_campuran == QQ(17) / 3
assert hasil_campuran.parent() is QQ

gelang = PolynomialRing(QQ, "z")
z = gelang.gen()
polinom = z**4 - 1
faktorisasi = polinom.factor()
assert faktorisasi.prod() == polinom
assert {str(faktor) for faktor, _ in faktorisasi} == {
    "z - 1",
    "z + 1",
    "z^2 + 1",
}

Sage memakai peta kanonis ZZ ke QQ, sehingga hasil penjumlahan hidup di QQ dan tetap eksak. Polinom hidup di QQ[z]; mengalikan faktor di parent yang sama memberi sertifikat lokal bagi faktorisasi tersebut.

8.9.7 Latihan Sage 2 - solusi eksak dan pendekatan

Selesaikan w2=5w^2=5 di SR, periksa residual setiap solusi secara eksak, lalu ubah akar positif secara eksplisit ke RR. Simpan nilai eksak, parent asal, nilai pendekatan, parent tujuan, dan presisinya. Jelaskan apa yang dibuktikan residual dan apa yang tidak.

Gunakan solve(..., solution_dict=True), simplify_full(), dan RR(akar). Jangan mengganti objek SR sebelum residual eksak diperiksa.

PentingPemeriksaan mandiri
from sage.all import RR, SR, solve

w = SR.var("w")
baris_solusi = solve(w**2 == 5, w, solution_dict=True)
akar = [baris[w] for baris in baris_solusi]

assert {str(nilai) for nilai in akar} == {"-sqrt(5)", "sqrt(5)"}
assert all((nilai**2 - 5).simplify_full() == 0 for nilai in akar)

akar_positif = next(nilai for nilai in akar if nilai > 0)
hampiran = RR(akar_positif)
assert akar_positif.parent() is SR
assert hampiran.parent() is RR
assert RR.precision() == 53
from sage.all import RR, SR, solve

w = SR.var("w")
solusi = solve(w**2 == 5, w, solution_dict=True)
nilai_eksak = sorted((baris[w] for baris in solusi), key=str)
residual_nol = [
    bool((nilai**2 - 5).simplify_full() == 0)
    for nilai in nilai_eksak
]

akar_positif = next(nilai for nilai in nilai_eksak if nilai > 0)
nilai_hampiran = RR(akar_positif)
rekaman = {
    "exact": str(akar_positif),
    "exact_parent": str(akar_positif.parent()),
    "approximate": str(nilai_hampiran),
    "approximate_parent": str(nilai_hampiran.parent()),
    "precision_bits": RR.precision(),
}

assert residual_nol == [True, True]
assert rekaman["exact"] == "sqrt(5)"
assert rekaman["exact_parent"] == "Symbolic Ring"
assert rekaman["approximate_parent"].startswith("Real Field")
assert rekaman["precision_bits"] == 53

Residual eksak memeriksa bahwa dua kandidat memenuhi persamaan. Konversi RR(akar_positif) menghasilkan pendekatan 53 bit tanpa menghapus rekaman objek eksak. Pemeriksaan ini tidak membuktikan kelengkapan algoritme solve untuk semua persamaan atau semua domain.

8.10 Ringkasan

  • Ekspresi simbolik menyatakan struktur; substitusi menghasilkan nilai pada masukan tertentu.
  • Aritmetika eksak mempertahankan hubungan rasional dan aljabar tanpa pembulatan desimal.
  • Asumsi serta domain menentukan penyederhanaan mana yang sah.
  • Kesamaan struktur, ekuivalensi pada domain bersama, dan kesamaan fungsi merupakan tiga pertanyaan berbeda.
  • Faktorisasi, ekspansi kembali, penyelesaian eksak, dan residual saling melengkapi sebagai pemeriksaan lokal.
  • Keluaran sistem aljabar komputer adalah bukti kerja yang harus dibatasi klaimnya, bukan pengganti otomatis bagi bukti umum.
  • Representasi kanonis, versi pustaka, dan hash membuat artefak dapat dibandingkan.
  • Lab SageMath 9.5 lokal wajib memakai ZZ, QQ, RR, SR, parent dan coercion, gelang polinom, faktorisasi, penyelesaian, residual, serta konversi pendekatan eksplisit; layanan jarak jauh tidak menggantikannya.