Bilimsel Programlamaya Kolay Başlangıç – 4

Yazı dizimizin bir önceki bölümünde  numpy kullanımına basit bir giriş yapmıştık, şimdi ise daha ileri matematiksel yöntemleri içeren scipy‘a bir göz atalım. Yapmaya çalıştığımız “ivmenin nümerik integrasyonu” işi, aslında bir “ikinci derece diferansiyel denklem çözümü” ile eşdeğer. Konumun zamana göre ikinci türevi olan ivme diferansiyel denklemini analitik olarak çözebilseydik, konum ve hız vektörlerinin geçmiş ve gelecekteki tüm değerlerini bulabilirdik. Lakin bunu analitik olarak çözmeye hiç niyetimiz yok – işi bilgisayar yapabilecekken biz niye uğraşalım ki?

scipy bu tür diferansiyel denklemleri çözmek için bize integrate paketi altında solve_ivp adlı kütüphaneyi sunuyor. Bu kütüphane altındaki metodlarla diferansiyel denklemleri sayısal olarak kolayca çözebiliriz. Ancak öncelikle denklemleri bu yöntemlerin anlayacağı halde yazmamız gerek, diğer bir deyişle ikinci derece diferansiyel denklemi iki tane birinci derece diferansiyel denklem haline getirmemiz gerekiyor. Öncelikle kullanacağımız ara değişkenleri belirleyelim:

$ \vec{y_1} = \frac{d\vec{r}}{dt} = \dot{\vec{r}} $

$ \vec{y_2} = \vec{r} $

Şimdi de ikinci derece diferansiyel denklemimizi bu yeni değişkenler cinsinden yazalım:

$ \dot{\vec{y_2}} = \frac{d\vec{y_2}}{dt} = \vec{y_1} $

$ \dot{\vec{y_1}} = \frac{d\vec{y_1}}{dt} = – \frac{\mu}{(y_2)^3} \vec{y_2} $

Böylece ikinci derece diferansiyel denklemimiz iki tane birinci derece diferansiyel denkleme indirgendi ve scipy‘ın çözebileceği hale geldi.

Yukarıda olan biteni kod halinde yazmak zor değil:

In [25]:

Devamı...

 Bilimsel Programlamaya Kolay Başlangıç – 3

Bilimsel Programlama’ya Kolay Başlangıç serisinin ilk yazısında Hazırlık, Hesaplama ve Sonuçları Görselleştirme adımlarından bahsetmiş ve bunları serbest düşüş problemine uygulamıştık. İkinci yazıda ise Hesaplama adımından sonra Veri/Hata Analizi adımını eklemiş ve eğik atış problemini Euler sayısal metodu ile hesaplayarak hatamızı incelemiştik. Lakin tüm bunları Python’un kendi matematik kütüphanesi olan math ile gerçekleştirdik.

Serinin üçüncü yazısında ise math‘a oranla (genellikle) daha hızlı ve çok daha yetenekli olan numpy ve sonrasında da bunun üstüne bir kat daha çıkarak scipy kütüphanelerine terfi edeceğiz ve kolay yoldan bir ikinci derece diferansiyel denklem çözeceğiz. Bunun için Eğik Atış problemi yerine, nonlineer bir problem olan “iki cisim problemini”, yani Dünya’nın çevresindeki uyduların dinamiğini kullanacağız.

İki cisim problemi en genel haliyle kütle çekiminden kaynaklanan ivmeden ibaret:

$ \ddot{\vec{r}} = – \frac{\mu}{r^3} \vec{r} $

Burada $\vec{r}$ konum vektörünü, $r$ konum vektörünün büyüklüğünü ve $ \ddot{\vec{r}} $ konum vektörünün zamana göre ikinci türevini, ya da daha bilindik adıyla ivmeyi gösteriyor. $\mu$ ise pek tanıdık değil, ama aslında Dünya’nın kütleçekim sabitini gösteriyor ve $G M_{Dünya}$’ya, yani evrensel kütleçekimi sabiti ile Dünya’nın kütlesinin çarpımına eşit. Örneğin Ay’ın ya da bir uydunun, Dünya’nın çevresinde dönerken gelecekteki konum ve hızını bulabilmek için, başlangıçtaki konum ve hızı bu ivmenin integralini alarak ilerleteceğiz. İntegral lafını duyunca tüyleriniz diken diken olduysa korkmayın; integrali biz almayacağız, bilgisayar alacak.

Matematiğe gelmeden önce, işin kalbindeki veri yapısı olan ZamanKonumHız sınıfının numpy kullanan yeni sürümüne bakalım:

In [18]:

Devamı...

 Bilimsel Programlamaya Kolay Başlangıç – 2

Bilimsel Programlamaya Kolay Başlangıç serisinin ilk yazısında sadece grafikler için matplotlib kütüphanesini kullanarak serbest düşüş problemini modellemiş ve sonuçları grafiklerle görselleştirmiştik. Vesileyle, “fonksiyonları ne zaman nerede kullanmak gerekir” sorusuna da bir başlangıç yapmıştık.

İlk yazıda Bilimsel Programlama 3 adımdan oluşur dedik, ama aslında birçok problemde dört adımdan bahsetmek mümkün:

  1. Hazırlık (Sabitleri başlatma, gerekirse veri yapılarını oluşturma vb.)
  2. Hesaplama
  3. Veri Analizi (Hesaplama sonuçlarını gerçek veriler ya da başka bir modelle karşılaştırma, diğer bir deyişle Hata ya da Fark Analizi)
  4. Sonuçları Görselleştirme

Bu yazıda öncelikle eğik atış problemini çözeceğiz ve sayısal yöntemlerin ne kadar başarılı olduğuna bakacağız. Elimiz değmişken sınıf (class) yapılarının nasıl kullanıldığına dair de basit bir örnek yapmış olacağız.

Eğik atış problemi iki eksende çözülüyor, yatay eksen x ve düşey eksen y.

İki eksendeki konum değişimi şu şekilde gösterilebilir:

$t$ anında yatay eksendeki konum: $ r_x(t) = r_x(0) + v_x(0) t $

$t$ anında düşey eksendeki konum: $ r_y(t) = r_y(0) + v_y(0) t – \frac{1}{2} g t^2 $

İki eksendeki hız değişimi ise şu şekilde gösterilebilir:

$t$ anında yatay eksendeki hız: $ v_x(t) = v_x(0) $

$t$ anında düşey eksendeki hız: $ v_y(t) = v_y(0) – g t $

Parametreler ise şöyle:

$r_x(t), r_y(t) = $ x ve y ekseninde konum vektörü bileşenleri ($m$)

$v_x(t), v_x(t) = $ x ve y ekseninde hız vektörü bileşenleri ($m/s$)

$g = $ yerçekimi sabiti (9.81 $m/s^2$)

$t = $ zaman ($s$)

Formüllerin bize anlatmak istediği şey şu:

  1. Cisim yatay eksende başlanıç hızında gitmeye devam eder
  2. Cisim düşey eksende başlangıç hızında başlar, hızı yerçekimi ivmesiyle orantılı olarak düşey yönde değişir ve sonuçta düşmeye başlar.

“Bu kadar matematik yeter” diyorsanız, kodlama işine başlayalım o zaman. Öncelikle basit bir vektör sınıfı oluşturalım. Bu sınıf zaman, yatay ve düşey konum ile yatay ve düşey hız bileşenlerinden oluşuyor.

In [1]:

Devamı...

 Bilimsel Programlamaya Kolay Başlangıç – 1

Bilimsel Programlamaya Kolay Başlangıç gibi bir seri oluşturma fikri, öğrencilerin bir problemi çözmek için yaklaşım geliştirmekte ne kadar zorlandıklarını gördükten sonra kafamda oluşmaya başladı. Veri Defteri’nde belli bir konuyu açıklamayı hedefleyen birçok faydalı yazı var, ama benim amacım, programlamayı araç olarak kullanmak; seri boyunca gitgide karmaşıklaşan problemleri buna uygun programlama araçlarıyla çözmek.

Bilimsel Programlama denilince akla şu ara yapay zeka, makine öğrenmesi gibi afili konular geliyor, ama aslında bilimsel programlama bazen bundan çok daha fazlası ve genellikle de çok daha azı. Aslında istediğimiz şey, basit ya da karmaşık bir problemi bilgisayar aracılığıyla çözülebilir hale getirmek, problemi bilgisayara çözdürmek ve sonuçları anlayıp değerlendirmekten ibaret.

Bilimsel Programlama her disiplin için farklı şeyler ifade etse de, öğrencilerden araştırmacılara birçokları için temel birkaç adımdan oluşuyor:

  1. Hazırlık (Sabitleri başlatma, gerekirse veri yapılarını oluşturma vb.)
  2. Hesaplama
  3. Sonuçları Görselleştirme

Olan biteni daha net anlatabilmek için son derece basit, lise seviyesinde bir problemi ele alalım: Serbest Düşüş Hareketi.

Problemin matematiksel modeli bu kadarcık:

Konum değişimi:

$ h(t) = h(t_0) – \frac{1}{2} g t^2 $

Hız değişimi:

$ v(t) = v(t_0) – g t $

Parametreler ise şöyle:

$h = $ yükseklik ($m$)

$v = $ hız ($m/s$)

$g = $ kütleçekimi sabiti (Dünya için 9.81 $m/s^2$)

$t = $ zaman ($s$)

$h(t_0) = $ başlangıçtaki yükseklik ($m$)

$v(t_0) = $ başlangıçtaki hız ($m/s$)

Bu yazıda sadece yukarıdaki formül ile “gerçek” değerler üzerinden ilerleyeceğiz, sonraki yazıda ise yatay atış hareketi ve bunun sayısal yöntemlerle modellenmesi konusunda değineceğiz. Amacımız, başlangıçtan itibaren 10 saniye içinde düşen cismin yükseklik değişiminin grafiğini çizebilmek. Bunun için 1 saniye aralıkla yüksekliği hesaplayacağız.

İlk adım olarak, hazırlık aşamasında yerçekimi sabitini ve çıktı alacağımız zaman listesi ile daha sonra dolduracağımız konum ve hız listelerini oluşturuyoruz:

In [9]:

Devamı...

Python Programlamaya Giriş 23 – Modüller ve paketler

Her programlama dilinde olduğu gibi Python’da da tekrar tekrar kullanılabilen fonksiyon ve sınıfların bir kütüphane şeklinde ayrı dosyalarda saklanması ve yeni yazılan programlara entegre edilmesi için bir mekanizma vardır. Standart kütüphaneler, SciPy ve benzeri paketler, veya kendi kişisel fonksiyon kütüphaneniz bu modül sistemiyle inşa edilir.

Dizinin bütün yazılarına erişmek için Python Programlamaya Giriş kategorimize bakabilirsiniz.

Modüller

Python’da bir modül yaratmak için özel bir işleme gerek yoktur. Python kodu içeren, .py uzantılı herhangi bir dosya bir modül olabilir. Sözgelişi, aşağıdaki kodu basitmodul.py isimli bir dosyaya yazıp kaydettiğinizde, bir modül yaratmış olursunuz.

In [1]:

Devamı...

Python Programlamaya Giriş 22 – Hata yakalama, try/except

Hata yakalama (exception handling) beklenmedik durumlarda programınızın bir hata mesajı vermesi ve çalışmayı durdurması yerine, hataya kendi istediğimiz şekilde cevap vermesini sağlamanın bir yoludur. Hata yakalama Python programcılığının önemli bir parçasıdır, kaynak kodunu çok karışık hale getirmeden programınızın güvenilir bir şekilde çalışmasını sağlar.

Dizinin bütün yazılarına erişmek için Python Programlamaya Giriş kategorimize bakabilirsiniz.

Hatalı girdiyi yakalamak

Bir örnekle başlayalım: Etkileşimli çalışarak kullanıcıdan sayılar alan ve aldığı sayıların karesini ekrana basan bir program yazalım. Boş satır okuduğunda program sonlansın.

In [ ]:

Devamı...

Python Programlamaya Giriş 21 – Dinamik kod üretme

Python dinamik tabir edilen dillerden biridir; programdaki nesneleri önceden bildirmeniz gerekmez, program çalıştıkça işlenen komutlar o anda yeni nesneler üretir. Bu dinamiklik sayesinde, dize olarak verilmiş Python komutlarını da işleyebilir, hatta program yazan programlar yazabiliriz.

Bu işlemi yapmak için iki Python fonksiyonu vardır: eval() ve exec()

Dizinin bütün yazılarına erişmek için Python Programlamaya Giriş kategorimize bakabilirsiniz.

eval

Bu fonksiyon, Python komutları içeren bir dizeyi yorumlayıcıya gönderir ve sonucu geri verir.

In [1]:

Devamı...

Python Programlamaya Giriş 20 – Dosya Okuma ve Yazma

Yazı dizimizin bu bölümünde, dosya okuma ve yazma yöntemlerinden bahsedeceğiz. Önce herhangi bir özel şekilde yapılanmamış olan düz metin dosyalarını işlemeyi göreceğiz. Ardından csv modülüyle CSV biçiminde yapılanmış dosyaları okuyup yazmayı inceleyeceğiz. JSON, ZIP, PDF, Word, Excel, HTML dosyalarının işlenmesine kısaca değineceğiz. Son olarak, Python oturumunda yarattığımız nesneleri ikili (binary) formda dosyaya kaydetmemizi ve sonra dosyadan tekrar yüklememizi sağlayan pickle modülünün kullanımını özetleyeceğiz.

Dizinin bütün yazılarına erişmek için Python Programlamaya Giriş kategorimize bakabilirsiniz.

Genel dosya okuma/yazma

Dosya okumak

Öncelikle, IPython sihirleriyle deneme.txt isimli bir dosya yaratalım (Jupyter kullanmıyorsanız aşağıdaki metni bir metin editörüne kopyalayıp deneme.txt ismiyle çalışma dizininize kaydedebilirsiniz).

In [1]:

Devamı...

Python Programlamaya Giriş 14 – Sözlük Metodları

Python’daki veri tiplerini daha önce kısaca ele almıştık; bir önceki bölümde de liste tipine ait metodların kullanımını örneklerle incelemiştik. Bu yazıda sözlük tipine ait olan metodları örneklerle açıklıyoruz. Bundan sonraki bölümlerde dize ve küme tiplerine ait metodları inceleyeceğiz.

Sözlükler, listeler gibi, birden fazla elemanı bir araya toplayan yapılardır. Listelerden farkları sıralı nesne olmamalarıdır. Bir listenin indeksleri üzerinden doğal bir sırası varken, sözlüklerin elemanlarında doğal bir sıralama mevcut değildir.

Bir sözlük birleşmeli dizi (associative array) olarak anılan bir veri yapısıdır. Bu yapıdaki her eleman bir anahtar-değer (key-value) çiftinden oluşur. Belli bir değere ulaşmak için o değere ait tekil anahtarı kullanmak gerekir. Bu anahtar bir sayı, dize veya çokuz olabilir.

Devamı...

Python Programlamaya Giriş 19 – Liste kurma, sözlük kurma, üreteç ifadeler

Diyelim mevcut bir listedeki her elemanı tek tek işleyip, işlemin sonuçlarını yeni bir listede toplamak istiyorsunuz. Bunun için boş bir listeyle başlayıp, bir döngü içinde append() metoduyla listeyi adım adım büyütebiliriz. Bu yazıda Python’da bu işlemi daha hızlı verimli olarak yapmamızı sağlayan özel liste kurma yazımını göreceğiz. Liste kurma, genel olarak bir üreteç ifadesi örneğidir. Liste kurma gibi sözlük ve kümeleri de hızlıca kurmak için benzer bir yazım kullanırız.

Yazı dizimizin bütün yazılarına erişmek için Python Programlamaya Giriş kategorimize bakabilirsiniz.

Basit liste kurma

Basit bir örnekle başlayalım: Bir sayı listesi alalım, ve liste elemanlarının karelerinden oluşan yeni bir liste oluşturalım.

Şimdiye kadar gördüğümüz yöntemlerle bu işi yapmak için önce boş bir liste yaratırız, sonra bir for döngüsü içinde sayıları tek tek alırız, karelerini teker teker boş listeye ekleriz.

In [1]:

Devamı...