TEORİDEN UYGULAMAYA · PYTHON EŞLİKÇİSİ

Genel İkinci Derece Denklem ve Sınıflandırma

Prof. Dr. Zühal Küçükarslan Yüzbaşı · Prof. Dr. Bahadır Yüzbaşı

Bölüm 16 · v1.0 · Türkçe

Bu bölümün laboratuvarı, kitaptaki örnekleri yeniden üretmek ve sayısal sonuçları incelemek için hazırlanmıştır. Matematiksel tanımlar, ispatlar ve sorular kitapta yer alır.

Laboratuvarı indir (.py) Tam Python paketi (.zip)

Laboratuvar kodu

"""Bölüm 16: genel ikinci derece denklem ve sınıflandırma laboratuvarı.

Uygulama, döndürülmüş eliptik bir CAD açıklığının sentetik geometrisidir.
Ölçüm verisi, konik uydurma, üretim toleransı veya kabul kararı içermez.
"""

from __future__ import annotations

import numpy as np

from agbook import (
    canonical_array_sha256,
    quadratic_conic_diagnostics,
    quadratic_conic_residuals,
    rotation_matrix_2d,
    transform_quadratic_conic,
)


def main() -> None:
    length_unit = "mm"
    center_mm = np.array([120.0, 80.0])
    semi_axes_mm = np.array([45.0, 20.0])
    major_axis_angle_deg = 32.0
    rotation = rotation_matrix_2d(np.deg2rad(major_axis_angle_deg))

    canonical_coefficients = np.array(
        [
            1.0 / semi_axes_mm[0] ** 2,
            0.0,
            1.0 / semi_axes_mm[1] ** 2,
            0.0,
            0.0,
            -1.0,
        ]
    )
    coefficients_mm = transform_quadratic_conic(
        canonical_coefficients,
        rotation.T,
        -rotation.T @ center_mm,
    )
    diagnosis_mm = quadratic_conic_diagnostics(
        coefficients_mm,
        coordinate_scale=100.0,
        relative_tolerance=1e-12,
    )

    parameters = np.linspace(0.0, 2.0 * np.pi, 25, endpoint=False)
    local_points_mm = np.column_stack(
        [
            semi_axes_mm[0] * np.cos(parameters),
            semi_axes_mm[1] * np.sin(parameters),
        ]
    )
    global_points_mm = local_points_mm @ rotation.T + center_mm
    residuals_mm = quadratic_conic_residuals(
        coefficients_mm,
        global_points_mm,
        coordinate_scale=100.0,
    )

    coefficients_m = coefficients_mm * np.array(
        [1e6, 1e6, 1e6, 1e3, 1e3, 1.0]
    )
    diagnosis_m = quadratic_conic_diagnostics(
        coefficients_m,
        coordinate_scale=0.1,
        relative_tolerance=1e-12,
    )
    residuals_m = quadratic_conic_residuals(
        coefficients_m,
        global_points_mm / 1000.0,
        coordinate_scale=0.1,
    )

    scaled_diagnosis = quadratic_conic_diagnostics(
        -17.0 * coefficients_mm,
        coordinate_scale=100.0,
        relative_tolerance=1e-12,
    )
    major_projector = np.outer(diagnosis_mm.principal_directions[:, 0], diagnosis_mm.principal_directions[:, 0])
    expected_major_projector = np.outer(rotation[:, 0], rotation[:, 0])

    np.testing.assert_allclose(diagnosis_mm.center, center_mm, atol=3e-13)
    np.testing.assert_allclose(diagnosis_mm.semi_axes, semi_axes_mm, atol=3e-13)
    np.testing.assert_allclose(major_projector, expected_major_projector, atol=3e-13)
    np.testing.assert_allclose(diagnosis_m.center, center_mm / 1000.0, atol=3e-15)
    np.testing.assert_allclose(diagnosis_m.semi_axes, semi_axes_mm / 1000.0, atol=3e-15)
    np.testing.assert_allclose(
        diagnosis_m.normalized_coefficients,
        diagnosis_mm.normalized_coefficients,
        atol=3e-15,
    )
    np.testing.assert_allclose(residuals_m, residuals_mm, atol=3e-15)
    np.testing.assert_allclose(scaled_diagnosis.center, diagnosis_mm.center, atol=3e-13)
    np.testing.assert_allclose(scaled_diagnosis.semi_axes, diagnosis_mm.semi_axes, atol=3e-13)
    assert diagnosis_mm.locus_type == diagnosis_m.locus_type == "ellipse"
    assert scaled_diagnosis.locus_type == "ellipse"
    assert not diagnosis_mm.numerically_ambiguous
    assert np.max(np.abs(residuals_mm)) < 2e-15

    near_boundary = quadratic_conic_diagnostics(
        [1.0, 0.0, 1e-14, 0.0, 0.0, -1.0],
        relative_tolerance=1e-12,
    )
    signature_values = np.concatenate(
        [
            center_mm,
            semi_axes_mm,
            np.array([major_axis_angle_deg]),
            rotation.ravel(),
            canonical_coefficients,
            coefficients_mm,
            diagnosis_mm.normalized_coefficients,
            diagnosis_mm.eigenvalues,
            diagnosis_mm.center,
            diagnosis_mm.semi_axes,
            diagnosis_mm.principal_directions.ravel(),
            parameters,
            global_points_mm.ravel(),
            residuals_mm,
            coefficients_m,
            diagnosis_m.normalized_coefficients,
        ]
    )

    print("uzunluk_birimi:", length_unit)
    print("model: sentetik_dondurulmus_eliptik_cad_acikligi")
    print("olculmus_veri_mi: False")
    print("konik_uydurma_yapildi_mi: False")
    print("uretim_kabul_hesabi_mi: False")
    print("genel_katsayilar_A_B_C_D_E_F0:", coefficients_mm)
    print("sinif:", diagnosis_mm.locus_type)
    print("Q_ranki:", diagnosis_mm.quadratic_rank)
    print("H_ranki:", diagnosis_mm.homogeneous_rank)
    print("atalet_pozitif_negatif_sifir:", diagnosis_mm.inertia)
    print("geri_kazanilan_merkez_mm:", diagnosis_mm.center)
    print("geri_kazanilan_yari_eksenler_mm:", diagnosis_mm.semi_axes)
    print("geri_kazanilan_ana_eksen_acisi_derece:", f"{np.rad2deg(diagnosis_mm.orientation_radians):.6f}")
    print("en_buyuk_boyutsuz_artik:", f"{np.max(np.abs(residuals_mm)):.3e}")
    print("katsayi_carpani_altinda_sinif_korundu_mu:", scaled_diagnosis.locus_type == diagnosis_mm.locus_type)
    print("metre_milimetre_tanisi_korundu_mu:", bool(np.allclose(diagnosis_m.normalized_coefficients, diagnosis_mm.normalized_coefficients, atol=3e-15)))
    print("yakin_rank_kaybi_adayi:", near_boundary.locus_type)
    print("yakin_rank_karari_belirsiz_isaretli_mi:", near_boundary.numerically_ambiguous)
    print("bilimsel_imza:", canonical_array_sha256(signature_values))


if __name__ == "__main__":
    main()
Doğrulama çalıştırmasının çıktısı
uzunluk_birimi: mm
model: sentetik_dondurulmus_eliptik_cad_acikligi
olculmus_veri_mi: False
konik_uydurma_yapildi_mi: False
uretim_kabul_hesabi_mi: False
genel_katsayilar_A_B_C_D_E_F0: [ 1.05718944e-03 -1.80313620e-03  1.93663772e-03 -1.09474568e-01
 -9.34856914e-02  9.30790176e+00]
sinif: ellipse
Q_ranki: 2
H_ranki: 3
atalet_pozitif_negatif_sifir: (2, 0, 0)
geri_kazanilan_merkez_mm: [120.  80.]
geri_kazanilan_yari_eksenler_mm: [45. 20.]
geri_kazanilan_ana_eksen_acisi_derece: 32.000000
en_buyuk_boyutsuz_artik: 7.772e-16
katsayi_carpani_altinda_sinif_korundu_mu: True
metre_milimetre_tanisi_korundu_mu: True
yakin_rank_kaybi_adayi: parallel_lines
yakin_rank_karari_belirsiz_isaretli_mi: True
bilimsel_imza: 3b9232b03b4e6f19b30c8607293f7429af149e7639e6d21a1af7237d5cfd3537
Metindeki Python kodları

Kod dosyasını indir

# Kitaptaki kod blokları; bu dosya içinde sırayla çalıştırılır.
# --- 1. Altı katsayıdan genel konik tanısı ---
import numpy as np
from agbook import (
    quadratic_conic_diagnostics,
    quadratic_conic_residuals,
    rotation_matrix_2d,
    transform_quadratic_conic,
)

center = np.array([120.0, 80.0])       # mm
axes = np.array([45.0, 20.0])          # mm
angle = np.deg2rad(32.0)
R = rotation_matrix_2d(angle)

canonical = np.array([
    1 / axes[0]**2, 0.0, 1 / axes[1]**2,
    0.0, 0.0, -1.0,
])
coefficients = transform_quadratic_conic(
    canonical, R.T, -R.T @ center
)
diagnosis = quadratic_conic_diagnostics(
    coefficients,
    coordinate_scale=100.0,
    relative_tolerance=1e-12,
)

t = np.linspace(0.0, 2*np.pi, 25, endpoint=False)
local = np.column_stack([
    axes[0] * np.cos(t), axes[1] * np.sin(t)
])
points = local @ R.T + center
residuals = quadratic_conic_residuals(
    coefficients, points, coordinate_scale=100.0
)

print(diagnosis.locus_type)
print(diagnosis.center)
print(diagnosis.semi_axes)
print(np.rad2deg(diagnosis.orientation_radians))
print(np.max(np.abs(residuals)))

Kaydedilen çıktı

1. Altı katsayıdan genel konik tanısı
ellipse
[120.  80.]
[45. 20.]
32.0
7.771561172376096e-16
Çözümlerdeki Python kodları

Kod dosyasını indir

# Kitaptaki kod blokları; bu dosya içinde sırayla çalıştırılır.
# --- 1. Afin ve homojen matris özdeşliği ---
import numpy as np
from agbook import quadratic_conic_matrices

cases = [
    [1, 0, 1, 0, 0, -1],
    [1, 0, -1, 0, 0, -1],
    [1, 2, 1, -4, 4, 0],
    [0, 0, 0, 6, 8, -10],
    [3, -8, 2, 6, -10, -7],
]
X = np.array([1.25, -0.75])
Xh = np.r_[X, 1.0]
for c in cases:
    A, B, C, D, E, F0 = c
    raw = A*X[0]**2 + B*X[0]*X[1] + C*X[1]**2 \
          + D*X[0] + E*X[1] + F0
    Q, g, H = quadratic_conic_matrices(c)
    np.testing.assert_allclose(X @ Q @ X + 2*g @ X + F0, raw)
    np.testing.assert_allclose(Xh @ H @ Xh, raw)

# --- 2. Tam katalog için küçük sınıflandırma tablosu ---
from agbook import quadratic_conic_diagnostics

cases = {
    "ellipse": [1/9, 0, 1/4, 0, 0, -1],
    "hyperbola": [1/9, 0, -1/4, 0, 0, -1],
    "parabola": [1, 0, 0, 0, -4, 0],
    "point": [1, 0, 1, 0, 0, 0],
    "intersecting_lines": [1, 0, -1, 0, 0, 0],
    "parallel_lines": [1, 0, 0, 0, 0, -4],
    "double_line": [1, 0, 0, -4, 0, 4],
    "line": [0, 0, 0, 2, -4, 6],
    "empty": [1, 0, 1, 0, 0, 1],
    "plane": [0, 0, 0, 0, 0, 0],
}
for expected, coefficients in cases.items():
    result = quadratic_conic_diagnostics(coefficients)
    assert result.locus_type == expected
    print(expected, result.quadratic_rank, result.homogeneous_rank)

# --- 3. Dönme ve öteleme kovaryansı ---
import numpy as np
from agbook import (
    quadratic_conic_diagnostics,
    quadratic_conic_residuals,
    rotation_matrix_2d,
    transform_quadratic_conic,
)

R = rotation_matrix_2d(np.deg2rad(37.0))
center = np.array([4.0, -2.0])
canonical = np.array([1/25, 0, 1/9, 0, 0, -1])
general = transform_quadratic_conic(
    canonical, R.T, -R.T @ center
)
result = quadratic_conic_diagnostics(
    general, coordinate_scale=5.0, relative_tolerance=1e-12
)
canonical_result = quadratic_conic_diagnostics(
    canonical, coordinate_scale=5.0, relative_tolerance=1e-12
)
np.testing.assert_allclose(result.center, center, atol=1e-12)
np.testing.assert_allclose(result.semi_axes, [5, 3], atol=1e-12)

Y = np.array([[0.0, 0.0], [1.0, -3.0], [2.0, 1.0]])
X = Y @ R.T + center
old = quadratic_conic_residuals(general, X, coordinate_scale=5.0)
new = quadratic_conic_residuals(canonical, Y, coordinate_scale=5.0)
np.testing.assert_allclose(
    old * result.normalization_factor,
    new * canonical_result.normalization_factor,
    atol=1e-12,
)

# --- 4. Yakın rank sınırını açık eşikle raporlama ---
from agbook import quadratic_conic_diagnostics

c = [1.0, 0.0, 1e-14, 0.0, 0.0, -1.0]
exact_float = quadratic_conic_diagnostics(c, relative_tolerance=0.0)
thresholded = quadratic_conic_diagnostics(c, relative_tolerance=1e-12)

print(exact_float.locus_type, exact_float.quadratic_rank,
      exact_float.numerically_ambiguous)
print(thresholded.locus_type, thresholded.quadratic_rank,
      thresholded.numerically_ambiguous)

Kaydedilen çıktı

1. Afin ve homojen matris özdeşliği

2. Tam katalog için küçük sınıflandırma tablosu
ellipse 2 3
hyperbola 2 3
parabola 1 3
point 2 2
intersecting_lines 2 2
parallel_lines 1 2
double_line 1 1
line 0 2
empty 2 3
plane 0 0

3. Dönme ve öteleme kovaryansı

4. Yakın rank sınırını açık eşikle raporlama
ellipse 2 False
parallel_lines 1 True

Çalıştırma rehberi

Önce tam Python paketini indirin ve arşivi açın. Aşağıdaki komutları arşivin üst klasöründen başlatın. İlk kurulum internet bağlantısı ve Python 3.12 veya 3.13 gerektirir. Bağımlılıklar sabittir; sistem Python'unu değiştirmemek için ayrı sanal ortam kullanılır.

macOS / Linux
cd analitik-geometri-python-v1.0
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[dev]"
python labs/bolum_16_genel_ikinci_derece.py
python -m pytest
Windows PowerShell
cd analitik-geometri-python-v1.0
py -3.13 -m venv .venv
.venv\Scripts\python.exe -m pip install -e ".[dev]"
.venv\Scripts\python.exe labs/bolum_16_genel_ikinci_derece.py
.venv\Scripts\python.exe -m pytest

Laboratuvar dosyaları agbook yardımcı paketini kullanır; tek bir dosyayı indirmek paketi kurmanın yerini tutmaz. Metin/çözüm kodları kendi dosyaları içinde sırayla çalıştırılır; gizli bir notebook oturumu gerekmez. Son ondalık basamaklar platforma göre değişebilir.