Boethius’un kartlarında sadece asal sayılar varmış. Yani 2, 3, 5, 7, 11.
Confucius’un kartlarında da asal olmayan ve ortak bir asal çarpanı olan üç sayı varmış. Bunlar da 4, 6, 9, 10 ve 12 olabilir. 1’in asal çarpanı olmadığı için listede yok. 8 sayısı Anaximander’in kartlarında ve 2 sayısı da asal olduğundan Confucius’un kartlarında olamaz.
Bu bilgilere bakan Diogenes kimde hangi sayıların olduğunu bulabiliyor.
Şimdi bu bilgilere biraz daha bakalım. Boethius’un kartlarında üç tane asal olduğuna göre kalan iki asal Anaximander’de ve Diogenes’te olmalı, çünkü Confucius’ta hiç asal yok. Peki bu asalların dağılımı nasıl olmalı ki Diogenes kendi kartlarına baktığında kimde hangi sayıların olduğunu görebiliyor?
Dikkat edersek asallarla ilgili Boethius’tan başka bilgi veren yok. Yani eğer Anaximander’de asal sayı varsa, Diogenes hangi asal sayıların Boethius’ta hangi asal sayının veya asal sayıların Anaximander’de olduğunu bilemez. O zaman kalan iki asal sayı da Diogenes de olmalı. Bu şekilde Diogenes Boethius’un üç sayısını da bilebilir.
Şimdi kalan sayılara bakalım. 8 sayısı Anaximander’deydi. O zaman 1, 4, 6, 9, 10, 12 sayıları kaldı. 1 sayısı kimde olmalı?
1 sayısı eğer Diogenes’te olsa, o zaman Diogenes 4, 6, 9, 10 ve 12 sayılarının hangi üçünün Confucius’ta, hangi ikisinin de Anaximander’de olduğunu bulamaz. Olasılıklara bakalım:
Demek ki 1 sayısı Diogenes’te olamaz. 1 sayısı Anaximander’de.
Artık dağıtmamız gereken beş sayı kaldı. 4, 6, 9, 10, 12. Bu sayıların biri Anaximander’de, üçü Confucius’ta, sonuncusu da Diogenes’te. Hangi dağılımda Diogenes herkesin sayılarını bilebilir?
Bunun için şöyle bir tablo yapayım:
Anaximander
Confucius
Diogenes
10 ya da 9
(6, 9, 12) ya da (6, 10, 12)
4
9
4, 10, 12
6
12, 6, 4 ya da 10
(4, 6, 10) ya da (4, 10, 12) ya da (6, 10, 12) ya da (4, 6, 12)
9
4 ya da 9
(6, 9, 12) ya da ((4, 6, 12)
10
9
(4, 6, 10)
12
Bu tabloyu Diogenes sütunundan okumaya başlayalım. Eğer Diogenes’te 4, 9 ya da 10 sayılarından biri varsa kalan sayıların dağılımı birden fazla şekilde yapılabiliyor. Bu durumda Diogenes diğerlerinin sayılarını bilemez. Buna karşın Diogenes’in sayıları 6 ya da 12 ise kalan sayıların dağılımı tek şekilde yapılabiliyor. Bu dağılımların ikisinde de Anaximander 9 sayısına sahip oluyor.
Sonuçta Diogenes herkesin sayılarını biliyor ama biz problemi çözünce Diogenes’in hiçbir sayısını bilemiyoruz. Elindeki sayıları bilebileceğimiz tek kişi de Anaximander ve soruda da onun sayıları sorulmuş. 1, 8, 9.
Anaximander de diğerlerinin sayılarını bilemez, ne asal sayıların ne de asal olmayan sayıların dağılımı hakkında bir bilgiye sahip değil.
Boethius kalan iki asal sayının Diogenes’te olduğunu bulabilir ama Diogenes’in son sayısını bulamaz.
Aynı şekilde Confucius da Diogenes’in asal olmayan sayısını bilir ama asalların nasıl dağıldığını bulamaz.
Padişah vezir seçmek için üç çok zeki ve mantıklı aday bulur. Adaylara yapacağı testin kurallarını anlatır:
Elimde üçü kırmızı ikisi mavi beş tane şapka var. Üçünüz de birbirinizi görecek şekilde şu üç sandalyeye oturacaksınız ve gözleriniz kapatılacak. Sonra her birinizin başına bu şapkalardan biri konulacak. Ardından aynı anda gözleriniz açılacak. Birbirinizle iletişim yasak. Başındaki şapkanın rengini tahmin etmek isteyen ayağa kalkacak ve bu rengi söyleyecek. Bir tahmin hakkınız var. Şapkasının rengini bilen ilk kişi vezir olacak.
Sonra adayların gözleri kapatılır ve padişah hepsinin başına da kırmızı şapka koydurur. Bir süre sonra adaylardan biri benim başımdaki şapka kırmızı der ve vezir olur.
Vezir nasıl bir mantık yürüttü de şapkasının rengini bildi?
Bu bilmecenin çözümü şöyledir:
Adaylara A, B ve C diyelim. Diyelim ki A adayı şapkasının rengini bildi. O zaman A adayının yürüttüğü mantık aşağıdaki gibidir.
Eğer benim başımdaki şapka mavi olsaydı, o zaman B adayı bu mavi şapkayı görecekti ve kendi başındaki şapka da mavi olsaydı C adayının hemen ayağa kalkıp kendi şapkasının kırmızı olduğunu söyleyeceğini düşünecekti. C adayı hala ayağa kalkmadığına göre hem benim (A) hem de B adaylarının şapkası mavi olamaz. Bu durumda benim başımdaki şapka mavi olsa bu sefer B adayı kendi şapkasının renginin kırmızı olduğunu şimdiye kadar anlayacaktı ve ayağa kalkıp kırmızı diyecekti ama bunu da yapmadığına göre benim başımdaki şapka kırmızı olmalı.
Benim oldukça hoşuma giden bir mantık yürütme yöntemi. Kendisini diğerlerinin yerine koyarak problemi adım adım çözüyor. Bu cevapta aklıma dikkatimi çeken şey yürütülen mantığın bütün adaylardan bağımsız olmasıdır. Bu nedenle üç adayın da aynı anda kalkıp kendi şapkasının kırmızı olduğunu bilmesini beklerdim.
Çözümde dikkate değer başka noktalar da var yalnız. A adayı yorum yaparken kendisini başkalarının yerine koyuyor ve eğer diğer türlü olsaydı şimdiye kadar şöyle tepkiler verirlerdi diye mantık yürütüyor. Yani mantıkta belli olmayan bir zaman bilgisi ile diğer kişilerin de sahip olduğuna inandığı bilgileri kullanıyor. A adayı aslında B ve C adaylarının aynı bilgilere sahip olup olmadığını bilmiyor ama bunu, her adayın çok zeki ve mantıklı olduğu varsayımına dayanarak doğru kabul ediyor. Zaman da önemli bence. A adayı herkesin aynı bilgiye sahip olduğunu ne zaman kabul edebilir? Bir saniye sonra mı? Yüz milisaniye sonra mı?
Şimdi zamanın bu çözümlerde nasıl başa bela olabileceğine bakalım. Adaylar çok zeki ve hepsi de vezir olmak istiyor. O zaman yalan söyleyerek diğerlerini şaşırtmayı da deneyebilirler. İletişim yokken nasıl yalan söyleyecekler sorusunun cevabı da zamanda gizli.
Örneğin başlarındaki şapkalar mavi (A), kırmızı (B) ve kırmızı (C) olsun (mavi mavi kırmızıda başında kırmızı olan şapka olan adayın daha başka bir mantık yürütmesine gerek yok, dolayısıyla yalanlara karşı da güvenli durumdadır). B ve C adayları bir tane mavi ve bir tane kırmızı şapka gördüklerinden birbirlerine karşı eşit durumdadırlar. Çözmeleri gereken tek sorun ne kadar zaman sonra diğer adayın ikinci mavi şapkayı görmediğinden emin olabilirler? Bu soruya cevap vermek yukarıda da dediğim gibi kolay değil ama burada başka bir imkan daha var. Bir mavi ve bir kırmızı şapka göre adaylar gerçekten de diğerinin ne düşündüğünü hesaba katmak zorunda mı? Kendi kafasında kırmızı şapka olan bir aday kendi kafasında mavi şapka olma şansını doğrudan atlayabilir, çünkü öyle bir durumda diğer adayla zamana karşı bir yarışta olacak (kendi başındakinin mavi olduğunu bilebilmesi için önce diğer adayın kendi şapkasının kırmızı olduğunu bilmesi gerekiyor). Böyle bir şapka dağılımında bence B ve C adayları (bir kırmızı ve bir mavi şapka görenler) diğerinin düşünmesini beklemeden hemen kırmızı diye tahminde bulunabilirler. Bu stratejinin kaybettiği durum padişahın gerçekten de iki mavi ve bir kırmızı şapka koyduğu durum ama bu durumda kafasında kırmızı şapka olan zaten kazanacağından ilk bakışta kafasında mavi şapka olan adayların kaybettiği bir şey yok gibi görünüyor. Bu stratejinin varlığı diğer adayı da baskı altında tutacaktır, yani ona mantık yürütmek için pek zaman bırakmayabilir.
Peki üç kırmızı şapka durumunda zaman faktörü nasıl işleyebilir? Her aday iki kırmızı şapka gördüğünden herkes birbirine göre eşit durumda. Rakipleri kandırmanın tek yolu ugerektiğinden daha uzun süre düşünmek olduğundan burada da “yalan söylemek” pek işe yaramıyor gibi. Bir adayın düşünme süresi arttıkça diğerlerinin başında mavi şapka olma olasılığı azalıyor. Burada da mavi şapkayı doğru bilmek diğerlerinin bizden daha önce doğru cevabı vermesiyle olabileceğinden belki de işi yine şansa bırakmak daha iyi bir strateji olabilir. Yani iki kırmızı gören hemen kendi başındaki şapkanın da kırmızı olduğunu söyleyebilir.
Bu problemi düşünmeye başladığımda zamanla oynayarak rakipleri yanlış yönlendirmek mümkün olabilir diye düşünüyordum ama öyle bir yol bulamadım. Zaman faktörü yine de önemli, çünkü mantığı doğru yürütmek için herkesin belli bir anda ne kadar bilgiye sahip olduğunu bilmek lazım ve bunu bağladığımız tek faktör de zaman. Belli bir süre geçtiğinde bir aday hala şu tepkiyi vermemişse o zaman o aday diğer kişilerinn şapkaları hakkında şu bilgilere sahiptir ve ben de kendi bilgilerimi artık güncelleyebilirim ama o belli bir süre ne kadar olmalı? Ayrıca bu mantık yürütme de kısaca hala kaybetmediysem başımdaki şapkanın rengi şu olmalıdır şeklinde, yani bu mantık yürütme kuralları öğrendikten hemen sonra yapılabilir ve oyunu kazanmak için de ilk bilen olmak gerektiğinden kaybedilecek olasılıklar elenir ve doğrudan en iyimser tahmin yapılabilir.
Gerçek hayatta bu oyun değişik kombinasyonlarla ve zeki insanlarla oynansa acaba nasıl sonuçlar çıkardı? Daha da kötüsü zeki birisi daha yavaş düşünen birisine karşı kaybedebilir bile ama soruda herkesin süper olduğu verilmişti. Yine de ilginç bir deneme olurdu.
Tanya Khovanovna’nın sayfasında gördüğüm bir bilmece.
Üzerinde birden onikiye kadar sayıları yazılı olduğu oniki tane kartımız var. Bu kartla Anaximander, Boethius, Confucius ve Diogenes arasında eşit olarak paylaştırılıyor, yani her biri üç tane kart alıyor. Sonra sırayla aralarında şöyle bir konuşma geçiyor.
Anaximander: Benim kartların birinde 8 var.
Beothius: Kartlarımın hepsinde asal sayılar var.
Confucius: Benim sayılarımın hiçbiri asal değil. Ayrıca üçünün de ortak bir asal çarpanı var.
Diogenes: O zaman her birinizin hangi kartlara sahip olduğunu biliyorum.
Herkes doğruyu söylemişse Anaximander’in kartlarında hangi sayılar vardır?
Bu mekanizmada toplumda karşılaşmaların çoğunluğunun akrabalar arasında olduğu varsayılıyor.
Okuduğum makalede akrabalık şu şekilde programlanmış. Karşılıklı oyun oynayan kişilerin ortalama akrabalığına \(r \) denmiş. Bu sayı da 0 ile 1 arasında bir değere sahip. Bizim karşılaşmadaki kazancımız, rakibin oyundaki kazancı ile kendi kazancımızın \(r \) ile çarpımının toplamı oluyor. Toplam kazançlar da sabir kalsın diye toplamlar \(1 + r \) sayısına bölünüyor. Bu şartlar altında kazanç matrisi aşağıdaki hale geliyor:
\(M = \begin{bmatrix} R&&\frac{T + r \cdot S}{1 + r}\\\frac{S+ r \cdot T}{1+r}&&P \end{bmatrix} \)
Bunun neden böyle olduğunu çıkarmaya çalışayım şimdi. Orijinal oyunda kazanç matrisi şu şekilde:
\(M = \begin{bmatrix} R&&S\\T&&P \end{bmatrix} \)
Bu matrise göre iki işbirlikçi karşılaşırsa ikisi de R kazanır. Yukarıdaki kurala göre ise ikisi de \(R + r \cdot R \) kazanacak ama. Bu sayıyı da \(1 + r \) sayısına bölersek ikisi için kazanç $late R $ olur.
İşbirlikçi ihanetçiye karşı oynarsa, işbirlikçi S, ihanetçi de T kazanacak. Şimdi buna kuralı uygularsak, işbirlikçi \(T + r \cdot S \) kazanacak ama bunu da \(1 + r \) ile böleceğiz. Benzer şekilde ihanetçi de \(S + r \cdot T \) kazanacak ve bunu da \(1 + r \) ile böleceğiz. Böylece iki kazancın da toplamı \(\frac{S + r\cdot T}{1 + r} + \frac{T + r \cdot S}{1 + r} = \frac{S + r\cdot T + T + r \cdot S }{1+r} = \frac {(1 + r) S + (1 + r) T}{1 + r} = \frac{(1 + r)(S+T)}{1 + r} = S + T \) olur.
İki ihanetçinin karşılaşması da iki işbirlikçi karşılaşması gibi analiz edilebilir ve orada da ikisi de P kazanır.
Makale bu matris için kararlı stratejilerin şu şekilde hesaplandığını belirtiyor.
İşbirlikçi stratejinin kararlı olabilmesi için
\(r > r_c = \frac {T – R}{R – S} \)
ve ihanetçi stratejinin kararlı olması için de
\(r < r_d = \frac{P – S}{T-P} \) olması gerekiyor.
Bu sistemi de aynı şekilde programladım ve denemeler yaptım ama nedense makaledeki gibi sonuçlar elde edemedim. Sanırım ya programım yanlış, makaleyi yanlış anladım ya da bilmediğim başka bir şeyler var. Öncelikle benim beklentim şu şekildeydi: Akrabalığı artırdıkça işbirlikçilerin kararlı bir duruma gelmesini bekliyordum ama bazı matris türlerinde hiç olmadı.
Önce kullandığım programı buraya koyayım. Sonra birkaç çıktıya da bakarız.
import numpy as np
import matplotlib.pyplot as plt
strategies = np.array([[1, 0], [0, 1]])
R = 2
S = 5
T = 4
P = 2
r = 0.2
payoff = np.array([[R, (T + r*S)/(1 + r)], [(S + r*T)/(1 + r), P]])
number_of_iterations = 100
increment = 0.01
steady_states = np.array([[0, 0]])
for s1 in np.arange(0, 1.0, increment):
s2 = 1 - s1
species = np.array([s1, s2])
for i in range(0, number_of_iterations):
difference = (payoff.dot(species) - species.dot(payoff).dot(species))*species
species = species + difference
species = np.clip(species, 0, 1)
steady_states = np.append(steady_states, np.array([[s1, species[0]]]), axis = 0)
plt.plot(steady_states[:, 0], steady_states[:, 1])
plt.ylabel("işbirlikçi türün sondaki oranı")
plt.xlabel("işbirlikçi türün başlangıçtaki oranı")
plt.show()
r = 0.2 için simülasyon çıktısır = 1.0 için simülasyon çıktısı
Bu denemelerde beklediğim şekilde bir değişiklik göremediğim için biraz hayal kırıklığına uğradığımı söylemem lazım ama bu akrabalık seçilimi için tek model değil tabii ki. Belki diğer modeller beklediğim sonuçları verir ya da belki ben bir hata yapmışımdır da o hatayı bu sırada bulurum.
Doğrudan karşılıklılıkta birisine karlı vereceğimiz kararı, o kişinin bize geçmişte nasıl davrandığına bakarak veriyorduk. Dolaylı karşılıklılıkta bu kararı o birisinin geçmişte başkalarına nasıl davrandığına bakarak veriyoruz.
Oyuncular arasında tutsak ikilemindeki gibi oyunlar oynanıyor. Bu karşılaşmalar da diğer oyuncular tarafından izleniyor. Karşılaşmalarda işbirliğinin getirisi az. Buna karşın ihanetin kısa vadede getirisi fazlayken aynı zamanda kötü ün de kazandırıyor.
Karşılaşmaların oynanması şu şekilde. İhanet edenler kimle oynarsa oynasın ihanet ediyor. İşbirlikçiler işbirlikçilere karşı her zaman işbirliği yapıyor. İşbirlikçiler bir ihanetçiyi \(q \) ihtimalle tanıyor ve ihanetçiyle sadece \(1 – q \) ihtimalle işbirliği yapıyor. Bu şartlar altında payoff matrisi aşağıdaki şekle dönüşüyor.
Bir başkasının ününü bilme şansı \(q \) aşağıdaki eşitsizliği sağladığında doğrudan karşılıklılıkla aynı sonuçlar elde ediliyor.
\(q > \frac{T-R}{T-P} \)
Makaledeki bu sonuçları denemek için aşağıdaki python programını yazdım ve denemeler yaptım.
import numpy as np
import matplotlib.pyplot as plt
strategies = np.array([[1, 0], [0, 1]])
R = 5
S = 1
T = 7
P = 3
q = 0.51
prisoner_dilemma_payoff = np.array([[R, (1 - q)*S + q*P], [(1-q)*T + q*P, P]])
number_of_iterations = 100
payoff = prisoner_dilemma_payoff
increment = 0.01
steady_states = np.array([[0, 0]])
for s1 in np.arange(0, 1.0, increment):
s2 = 1 - s1
species = np.array([s1, s2])
for i in range(0, number_of_iterations):
difference = (strategies.dot(payoff).dot(species) - species.dot(payoff).dot(species))*species
species = species + difference
species = np.clip(species, 0, 1)
steady_states = np.append(steady_states, np.array([[s1, species[0]]]), axis = 0)
plt.plot(steady_states[:, 0], steady_states[:, 1])
plt.ylabel("1. türün sondaki oranı")
plt.xlabel("1. türün başlangıçtaki oranı")
plt.show()
Programdaki R, S, T ve P değerleri için yukarıdaki eşitsizlik aşağıdaki gibi oluyor.
\(q > \frac{7 – 5}{7 – 3} = \frac {2}{4} = 0.5 \)
Yani programdaki \(q = 0.51\) değeri için işbirlikçi stratejinin kararlı olduğu bir dağılım da olmasını bekliyordum. Programı çalıştırınca aşağıdaki sonucu aldım.
\(q = 0.51\)
Bu sonuç doğrudan karşılıklılıktaki simülasyonun aksine verilen eşitsizliğe uygun çıktı. \(q \) değeri yükseldikçe işbirliği daha etkili bir strateji olacak mı diye bir uç değeri de denedim.
\(q = 0.99 \)
Gerçekten de bu simülasyona göre ihanet stratejisi uygulayanlar popülasyonda tanındığı zaman toplum işbirliği stratejisini benimsemeye başlıyor.
Evrimsel oyun teorisi kitabında bir sonraki konu karşılıklılık konusuydu. Cevap aranan soru anladığım kadarıyla şöyleydi: Oyun teorisi karşımızdakine ihanet etmemiz gerekir derken, toplum için daha iyi çözümler olan kooperasyon stratejilerine gerçek hayatta hangi mekanizmalarla erişebiliyoruz?
Martin Nowak bu soruya cevap veren beş adet mekanizma bulmuş. Kitap bu konuya kısaca değindiğinden bu konuyu Christine Taylor ve Martin Nowak’ın “Transforming the dilemma” başlıklı makalesinden öğrenmeye karar verdim.
Makalede ilk mekanizma olarak doğrudan karşılıklılık mekanizmasından bahsediliyor. Toplumlarda ikilemlere dayalı oyunlar oynanırken sonsuz büyüklükte bir toplumda herkesin rastgele kişilerle oyunlar oynadığını varsaymıştık. Gerçek hayatta ise bu oyunlar değişik şekilde oynanıyor. Örneğin bu mekanizmada olduğu gibi aynı kişiler aynı oyunu birbirleriyle defalarca oynayabiliyor. Bu durumda ikisi de diğer oyuncunun daha önce hangi stratejileri kullandığını biliyor ve kendi stratejilerini buna göre güncelleyebiliyor.
Bu mekanizmada iki oyuncu arasındaki karşılaşmadan sonra \(\omega \) olasılıkla tekrar karşılaşma oluyor. Bu durumda iki oyuncu arasında ortalama karşılaşma sayısı da \(\frac{1}{1 – \omega} \) formülüyle hesaplanabilir. İki oyuncunun karşılaşma kuralları şöyle:
İki oyuncu da işbirlikçiyse o zaman ikisi de işbirlikçi kalır. İhanet stratejisini seçen her zaman ihanet stratejisini uygular. İşbirlikçi ihanet stratejisi kullanan oyuncuyla karşılaştığında ikinci karşılaşmadan itibaren ihanet stratejisi kullanmaya başlar.
Bu durumda payoff matrisi aşağıdaki şekle dönüşür:
Aşağıdaki programla \(\omega \) değişkeninin etkisini denemeye çalıştım. Aslında bu değişkenle matrisin elemanları ve dolayısıyla elemanlar arasındaki ilişkiler değişeceğinden bu ikilemin başka bir oyun tipine dönüşmesini beklemek çok normal. Aslında bunu daha iyi görmek için oyuncuların karşılaşmalarını tek tek simüle edip aynı sonuca yaklaştığını göstermek lazım ama bu denemeleri ilerideki yazılarda yapmak istiyorum. Makalede bu dönüşüm için bir eşitsizlik veriliyor:
\(\omega > \frac{T-R}{T-P} \)
Eğer eşitsizlik sağlanmıyorsa ihanet eden strateji her durumda popülasyonu domine ediyor. Eğer eşitsizlik sağlanıyorsa işbirlikçi strateji de evrimsel açıdan kararlı bir durum olabiliyor. \(\omega \) değeri büyüdükçe, yani oyuncular arasındaki karşılaşma sayısı arttıkça işbirlikçi strateji de daha dominant olmaya başlıyor. Bu sonuçları denemek için aşağıdaki python programını kullandım:
import numpy as np
import matplotlib.pyplot as plt
strategies = np.array([[1, 0], [0, 1]])
R = 5
S = 1
T = 7
P = 3
omega = 0.60
prisoner_dilemma_payoff = np.array([[R/(1-omega), S + (omega*P)/(1 - omega)], [T + (omega*P)/(1-omega), P/(1-omega)]])
number_of_iterations = 100
payoff = prisoner_dilemma_payoff
increment = 0.01
steady_states = np.array([[0, 0]])
for s1 in np.arange(0, 1.0, increment):
s2 = 1 - s1
species = np.array([s1, s2])
for i in range(0, number_of_iterations):
difference = (strategies.dot(payoff).dot(species) - species.dot(payoff).dot(species))*species
species = species + difference
species = np.clip(species, 0, 1)
steady_states = np.append(steady_states, np.array([[s1, species[0]]]), axis = 0)
plt.plot(steady_states[:, 0], steady_states[:, 1])
plt.ylabel("1. türün sondaki oranı")
plt.xlabel("1. türün başlangıçtaki oranı")
plt.show()
\(\omega = 0.6 \) değeri için aşağıdaki sonucu aldım
\(\omega = 0.6 \) değeri için işbirlikçi strateji belli bir yoğunluktan sonra kararlı bir strateji oluyor.
Programdaki R, S, T ve P değerlerini eşitsizlikte yerlerine koyduğumda
eşitsizliğini buluyoruz. Bu eşitsizliği sınıra yakın bir yerde denemek istedim.
\(\omega = 0.51\) değeri için şu grafiği elde ettim.
\(\omega = 0.51 \)
Eşitsizliğin söylediğinin aksine hiçbir durumda işbirlikçi stratejisi kararlı olamadı. Belki de programda küçük bir hata yapmışımdır. Bunu da incelemem lazım.
Eğer \(\omega \) değeri bire yaklaşırsa oyuncular arasında karşılaşma sayısı da artar. Bu durumda grafiğin nasıl olduğuna da bakmak istedim.
\(\omega = 0.99 \)
Gerçekten de hemen hemen her başlangıç durumu için işbirlikçi strateji kararlı bir strateji oldu.
Şirkette bazen yapmam gereken işler varken küçük değişikliklere ihtiyacım oluyor. Bugün de işi rölantide yaparken youtube’da video seyredeyim dedim. Geçen binyılın ikinci yarısında MIT’de verilen bir bilgisayar dersine takıldım. Bazı derslerde hocalar kendi tecrübelerinden, kendi bilgeliklerinden bahsettiği için bu dersleri arada seyrediyorum. O dersteki bir cümleleri benim için genelde bütün o anlattığı konudan daha faydalı olabiliyor.
Konuya giriş dersinde hoca karekök hesaplama için İskenderiyeli Heron’un kullandığı yöntemi örnek olarak kullandı. Karekök öğrenim ve meslek hayatım boyunca sürekli kullandığım bir fonksiyondu ve nasıl hesaplandığını hiç düşünmemiştim. Lisede bunu kağıt kalemle yapan arkadaşlar vardı ama kullandıkları yöntemi öğrenmeyi düşünmemiştim. Ben bunu hesaplamaya kalksam sonucu heralde tahmini kökün yakınlarında taylor serileri yardımıyla arardım.
İskenderiyeli Heron’un yöntemi çok daha basit görünüyor ama. Peki bu yöntem nasıl işliyor?
Karekökünü bulmak istediğimiz sayı 40 olsun. Önce bir başlangıç noktası seçelim. Mesela 1. Her adımda bu başlangıç sayısını aradığımız sayıya yaklaştırmaya çalışacağız, yani her adımda güncellediğimiz bu başlangıç sayısı bir sonraki adımın başlangıç sayısı olacak. En iyisi bu örneği hareket halinde görelim.
Aradığımız sayının karesi 40 ve başlangıç noktamız 1.
\(\frac{1 + \frac{40}{1}}{2} = 20.5 \)
yani başlangıç sayısı ile aradığımız sayının karesinin başlangıç sayısına bölümünün aritmetik ortalamasını hesapladık. Bu sonuç bir sonraki adımın başlangıç sayısı olacak.
\(\frac{20.5 + \frac{40}{20.5}}{2} = 11.2256 \)
Bu şekilde diğer adımları da hesaplamaya devam edelim.
Sadece dört ondalık basamak kullandığımdan bu noktadan sonra adımlarda bir değişiklik olmuyor. Peki bu bulduğumuz sonuç 40’ın karekökü mü?
\(6.3245² = 39.99930025 \)
Tabii ki değil ama oldukça yakın. Böyle basit bir yöntem için oldukça başarılı. Tabii ki bu yöntemle ilgili kafamda bazı sorular vardı. Birincisi neden çalışıyor?
Önce şunu bir kontrol edelim. Herhangi bir adımda bulduğumuz sayı verilen sayının karekökü ise bir sonraki adımın sonucu ne olur?
x sayısının karekökünü aradığımızı varsayalım. Yani bir adımda bulduğumuz sayı \(\sqrt{x} \) ise bir sonraki adım için hesabımız
Yani bu yöntem bir kere karekökü bulursa hep o noktada kalıyor. Peki şimdi ikinci soru: Bu yöntem her zaman kareköke yaklaşır mı?
Bunun da cevabı evet ve ispatı bu adreste mevcut. İspatta kullanılan adımlar kısaca şöyle. Her adımda elde ettiğimiz arasonuç sıfırdan büyüktür. İkinci adımdan itibaren elde ettiğimiz arasonuçlar aradığımız karekökten büyüktür ya da kareköke eşittir.İkinci adımdan sonra her adımda bulunan arasonuç bir önceki adımda bulunan arasonuçtan büyük değildir. Yani elde ettiğimiz dizi monoton azalan ve altta sınırlı bir dizi. Bu durumda bu dizinin limiti vardır ve bu yöntemde o limit verilen sayının kareköküdür.
Aslında ikinci soru birinci soruyu da içeriyor ama her zaman soruları doğru sırada soramayabiliyorum. O tarihlerde bu kadar basit ve güzel yöntemlerin biliniyor ve kullanılıyor olması gerçekten de etkileyici.
Evrimsel oyun teorisi konusunda okuduğum son kitapta nedense fitness generating function kısmını bir türlü anlayamadım. Teknik kitaplar her şeyi oldukça basit bir şekilde anlatmalarıyla meşhur değiller zaten. Bunun üzerine kitapta bahsedilen makalelere bakmaya başladım ve bu da bir yerde çıkmaz sokakla bitti. Akademisyen olmadığım için belli bir altyapımın olmadığının farkındayım ama bu altyapıyı sağlamanın kolay bir yolu da olmalıdır diye düşünüyordum. Neyse, aramaya devam edeceğim. Bu sırada yoluma Jun Tanimoto’nun Fundamentals of Evolutionary Game Theory and its Applications adlı kitabından devam etmeye karar verdim.
Kitap önce iki kişilik oyunları belli sınıflara ayırıp biraz teoriden bahsediyor. Benim hedefim kuru teori yerine bu oyunları, algoritmaları ve simülasyonlarını programlamak olduğundan hemen python denemelerine başladım.
Bu denemelerden bahsetmeden önce biraz notasyondan bahsetmem gerekecek. İki kişilik ve iki stratejili oyunlarla başladım. Buna 2×2 oyunlar da deniyor, payoff matrisimiz de 2×2 matris.
Oyuncular
Cooperation (C)
Defection (D)
Cooperation (C)
R, R
S, T
Defection (D)
T, S
P, P
Kısaca bu tabloyu kullanmayı anlatayım. Cooperation işbirliği stratejisi oluyor, Defection da ihanet. Her adımda seçilen iki kişi birbiriyle stratejilerine göre bir oyun oynuyor. Bütün oyun bu tabloda kodlanmış durumda ve seçilen stratejilere göre kazançları da R, S, T, P değerleriyle tanımlanıyor. Oyuncuların biri soldaki sütundaki stratejilerden birine sahip, diğeri de ilk satırdaki stratejilerden birini oynuyor. Bu durumda şu eşleşmeler mümkün:
Birinci oyuncu: Cooperation İkinci oyuncu: Cooperation
Birinci oyuncu: Cooperation İkinci oyuncu: Defection
Birinci oyuncu: Defection İkinci oyuncu: Cooperation
Birinci oyuncu: Defection İkinci oyuncu: Defection
Her eşleşme için tablodaki eşleşme hücresindeki değerler oyuncuların kazançlarını belirliyor. Bu durumda yukarıdaki eşleşmeler için sonuçlar şöyle olacak:
Birinci oyuncu: Cooperation İkinci oyuncu: Cooperation
Bu durumda kazançlar tablodaki R, R değerlerinin olduğu hücreden okunacak. Yani birinci oyuncunun kazancı R değeri kadar, ikinci oyuncunun kazancı da R değeri kadar olacak.
Birinci oyuncu: Cooperation İkinci oyuncu: Defection
Bu durumda kazançlar tablodaki S, T değerlerinin olduğu hücreden okunacak. Yani birinci oyuncunun kazancı S değeri kadar, ikinci oyuncunun kazancı da T değeri kadar olacak.
Birinci oyuncu: Defection İkinci oyuncu: Cooperation
Bu durumda kazançlar tablodaki T, S değerlerinin olduğu hücreden okunacak. Yani birinci oyuncunun kazancı T değeri kadar, ikinci oyuncunun kazancı da S değeri kadar olacak.
Birinci oyuncu: Defection İkinci oyuncu: Defection
Bu durumda kazançlar tablodaki P, P değerlerinin olduğu hücreden okunacak. Yani birinci oyuncunun kazancı P değeri kadar, ikinci oyuncunun kazancı da P değeri kadar olacak.
Programda kullanırken bu tabloyu kitapta da gösterildiği gibi aşağıdaki M matrisi haline getirdim.
\(M = \begin{bmatrix} R&&S\\T&&P \end{bmatrix} \)
Kitapta olası oyunları incelemek için şu iki değer de hesaplanıyor.
\(D_{g} = T - R \)
\(D_{r} = P - S \)
\(D_{g} \) terimi sıfırdan büyükse davranış risk alma ikilemine sahip oluyormuş. \(D_{r} \) terimi sıfırdan büyükse bu sefer de davranış riskten kaçma ikilemine sahip oluyormuş.
Önce bu sınıflamayı kısaca vereyim, ilerki yazılarda bu sınıflamalar üzerine biraz daha düşünmeye çalışırım.
Tutsak ikilemi: Burada hem \(D_{g} \) hem de \(D_{r} \) sıfırdan büyük
Tavuk: Bu tip oyunlarda \(D_{g} \) sıfırdan büyük ve \(D_{r} \) sıfırdan büyük değil.
Geyik avı: Bu tip oyunlarda sadece \(D_{r} \) sıfırdan büyük oluyor.
İkilemsiz tip: Bu tip oyunlarda ne \(D_{g} \) ne de \(D_{r} \) sıfırdan büyüktür.
Bu oyun türleri hakkında internette bir sürü bilgi bulunabilir. Bu nedenle kitapta verilen algoritma ve bu tipler için yazdığım programı göstereceğim. Son olarak da bu tiplerin sonuçlarını grafik üzerinden kısaca anlatmaya çalışacağım.
Seçilen oyuncunun stratejisi iki ihtimalden (Cooperation ya da Defection) biri olacak. Bunları da şu iki vektörle tanımlayalım:
\(\vec{e_{1}} = \begin{pmatrix}1\\0\end{pmatrix} \) Cooperation stratejisini oynayan bireyi simgelesin.
\(\vec{e_{2}} = \begin{pmatrix}0\\1\end{pmatrix} \) de Defection stratejisini oynayan bireyi simgelesin.
Stratejilerin nüfustaki oranları da aşağıdaki vektörle (Transpose edilmiş hali) verilsin.
Cooperation stratejisini kullanan bir bireyin rastgele seçilen başka bir bireye karşı beklenen kazancı şu şekilde veriliyor:
\(e_{1}^{T} \cdot M \cdot s \)
Aynı şekilde Defection stratejisini kullanan bir bireyin rastgele seçilen başka bir bireye karşı beklenen kazancı da şu şekilde olur:
\(e_{2}^{T} \cdot M \cdot s \)
Bireylerin çoğalma mekanizması da şu şekilde tanımlanıyor:
\(\frac{\overset {.}{s_{i}}}{s_{i}} = {e_{i}}^{T} \cdot M \cdot s – {s}^{T} \cdot M \cdot s \)
Burada \(\overset {.}{s_{1} \) terimi Cooperation stratejisini kullanan bireylerin oranının değişim miktarını gösteriyor. \(\overset {.}{s_{2} \) terimi de Defection stratejisini kullanan bireylerin oranının değişim miktarını gösteriyor. \(s_{1} \) ve \(s_{2} \) terimleri de bu iki stratejiyi kullanan bireylerin toplam nüfustaki oranları ve toplamları da haliyle bir olmak zorunda. Bu iki toplam hep sabit kaldığından birinin oranındaki artış ile diğer grubun oranındaki azalış da büyüklük olarak birbirine eşit olmak zorunda.
Sistemin dinamik davranışını incelemek için de aşağıdaki python programını yazdım. Program açıklamalarını kodun içine eklemeye çalıştım. İstenen oyun tipi simülasyonunu elde etmek için payoff değişkeni program başındaki tiplerden birine eşitlemek yeterli olacaktır.
import numpy as np
import matplotlib.pyplot as plt
strategies = np.array([[1, 0], [0, 1]]) #strateji vektörleri
prisoner_dilemma_payoff = np.array([[5, 1], [7, 3]]) #tutsak ikilemi oyun tipi
chicken_dilemma_payoff = np.array([[5, 1], [7, 0]]) #tavuk oyun tipi
stag_hunt_dilemma_payoff = np.array([[8, 1], [7, 3]]) #geyik avı oyun tipi
trivial_payoff = np.array([[7, 3], [5, 1]]) #ikilemsiz oyun tipi
number_of_iterations = 100 # her bir oyunun kaç jenerasyon boyunca oynanacağı
payoff = prisoner_dilemma_payoff # seçilen oyun tipi
increment = 0.01
steady_states = np.array([[0, 0]]) # oyun bittiğinde nüfusun hangi oranlardan oluştuğu
for s1 in np.arange(0, 1.0, increment): #0-1 aralığında değişik başlangıç konumları yaratılıyor
s2 = 1 - s1 # nüfus oranları toplamı 1 olmalı
species = np.array([s1, s2]) # ilk durum olarak türlerin oranı belirlenmiş oldu
for i in range(0, number_of_iterations): # bu şartlar için oyun belirlenen jenerasyon miktarı kadar oynanacak
difference = (strategies.dot(payoff).dot(species) - species.dot(payoff).dot(species))*species # strateji vektörlerinin değişim miktarları hesaplanıyor
species = species + difference # bu stratejileri kullanan bireylerin nüfustaki oranları güncelleniyor
species = np.clip(species, 0, 1) # nüfus oranlarının her zaman 0 ile 1 arasında olması sağlanıyor
steady_states = np.append(steady_states, np.array([[s1, species[0]]]), axis = 0) # oyunun sonunda elde edilen oranlar kayıtlara ekleniyor
#Alttaki kısımda da simülasyon sonuçları grafik olarak hazırlanıyor
plt.plot(steady_states[:, 0], steady_states[:, 1])
plt.ylabel("1. türün sondaki oranı")
plt.xlabel("1. türün başlangıçtaki oranı")
plt.show()
Tutsak ikilemi oyununda başlangıçta Cooperation stratejisini uygulayanların oranı ne olursa olsun oyunun sonunda nüfus tamamen Defection stratejili bireyler kalıyor.
Tavuk tipi oyunda dahemen hemen her nüfus dağılımı için iki stratejinin de temsil edildiği denge durumları meydana geldi.
Tavuk tipi oyunda kullandığım matris de \(M = \begin{bmatrix} 5&&1\\7&&0 \end{bmatrix} \) şeklindeydi.
Geyik avı tipi oyunda bir orana kadar hep Cooperation stratejisi kazanıyor, o orandan sonra ise Defection. İki stratejinin bir arada süregeldiği bir durum olmuyor.
İkilemsiz oyun tipinde de her dağılım için Cooperation stratejisi nüfusu ele geçiriyor.
Bu oyun tipinde de \(M = \begin{bmatrix} 7&&3\\5&&1 \end{bmatrix} \) matrisini kullandım.
Şimdilik bu yazıyı burada bitireyim. Amacım basit oyunların simülasyonlarını kolayca yapmanın bir yolunu bulmaktı ve şimdilik bu kitaptaki yöntemle çalışabiliyorum gibi gözüküyor. Umarım konular ilerledikçe buna yakın bir performans gösterebilirim.
Lojistik büyüme modeli aşağıdaki diferansiyel denklemle tanımlanıyor.
\(\frac{dx}{dt} = x \frac {r}{K}(K – x) \)
Burada \(x \) o anlık nüfusu verirken \(\frac{dx}{dt} \) terimi de bir sonraki an için nüfusun ne kadar değişeceğini belirtiyor. \(K – x \) ifadesi, nüfus \(K \) teriminden büyük olduğunda negatif , küçük olduğunda da pozitif oluyor. Yani nüfus bu terimden büyükken nüfusun değişimi negatif (azalma yonünde), küçükken de pozitif (artış yönünde) olmakta. Bu durumda bu sistemde nüfus K değerine ulaşma eğiliminde olmalı. \(\frac {r}{K} \) terimi de bu yaklaşmanın hızını kontrol ediyor.
Kendimce yaptığım bu analiz sonunda tahmin yapmam gerekirse denge noktasının \(x = K \) noktasında olduğunu söylerdim. Bunların matematiksel çıkarımını yapmadan sadece deneysel gözlemlerini yapmak istiyorum. Bunun için aşağıdaki programı nüfusun ilk değeri için \(x = K = 300\) noktasında başlattım. Beklentim sabit bir grafik elde etmek.
import numpy as np
import matplotlib.pyplot as plt
def h(r, K, x):
return r*(1 - x / K)
r = 0.021476
K = 300
x = K
populations = np.array([x])
for i in range(1, 1000):
x = x + x*h(r, K, x)
populations = np.append(populations, [x])
plt.plot(populations)
plt.ylabel("nüfus")
plt.xlabel("zaman")
plt.show()
Nüfus gerçekten de sabit kalıyor. Peki başlangıç nüfusunu bu değerden biraz uzaklaştırırsak ne olur?
import numpy as np
import matplotlib.pyplot as plt
def h(r, K, x):
return r*(1 - x / K)
r = 0.021476
K = 300
x = K + 10
populations = np.array([x])
for i in range(1, 1000):
x = x + x*h(r, K, x)
populations = np.append(populations, [x])
plt.plot(populations)
plt.ylabel("nüfus")
plt.xlabel("zaman")
plt.show()
Bu programda nüfusu \(x = K + 10\) değerinden başlattım.
Kafamdan yaptığım analizden de beklediğim gibi nüfus gerçekten de kararlı duruma dönmeye çalışıyor. Demek ki bu sistem asimptotik kararlılığa sahip. Elbette bu çıkarımı matematiksel ispatı vermeden yapamam ama bu yazılarda daha çok sezgisel çalışmayı düşünüyorum.
Evrimsel oyun teorisi kitabında şimdi de sistemlerde kararlılıklar konusuna giriş kısmına geldim. Nüfus konusunda kararlılıktan kastedilen şöyle bir şey. Sistemdeki nüfuslar kararlı bir durumdaysa, bu nüfuslarda yapılan ufak değişiklikler sonunda sistem yine bu kararlı olduğu durumdaki nüfuslara yakın sayılarda kalacak. Anladığım kadarıyla kararlı durumdaki sayılara dönmek zorunda değil. Bu farklı kararlılıkların da değişik isimleri var. Örneğin nüfuslar bir zaman sonra (çok uzun zaman da olsa) baştaki kararlı durumdaki sayılara dönüyorsa asimptotik kararlılık deniyor. Eğer baştaki sayılara dönmüyorlar ama her zaman yakınlarda kalıyorlarsa da Lyapunov kararlı deniyormuş.
Geçenlerde bir yazıda Lotka-Volterra modelini anlamaya çalışmıştım. Modelin denklemleri aşağıdaki gibiydi:
\(\frac{dx}{dt} = \alpha x – \beta x \cdot y \)
\(\frac{dy}{dt} = \delta x \cdot y – \gamma y \)
\(x \) ve \(y \) av ve avcı türlerinin nüfuslarıdır. \(\frac{dx}{dt}\) ve \(\frac{dy}{dt}\) değerleri de bu nüfusların her adımda ne kadar değiştiğini gösteriyor. Eğer kararlı bir durumdaysak bu değişimlerin 0 olmasını bekleriz, yani nüfusların sabit kaldığı noktalardayızdır. Nüfusların sabit kalacağı noktaların biri iki nüfusun da sıfır olduğu yerdir. İki tür de yok olduğundan yeni bireylerin oluşma şansı yoktur (normal şartlarda). Bu çok ilginç bir durum değil ama. Bunun yerine bu iki türün aynı anda kararlı bir şekilde varlığını sürdürebildiği bir çözüme bakmak istiyorum. Bunun için değişim terimlerinin sıfır olduğu diğer çözümlere bakacağım.
Önce x nüfusundaki değişikliğin sıfır olması için y nüfusunun kaç olması gerektiğini bulayım.
\(\frac{dx}{dt}= \alpha x – \beta x \cdot y = 0\)
\(\alpha x = \beta x \cdot y \)
\(\frac{\alpha}{\beta} \frac {x}{x} = y \)
\(y = \frac {\alpha}{\beta} \)
Şimdi aynı şekilde y nüfusundaki değişikliğin sıfır olması için x nüfusunun ne olması gerektiğine bakayım.
\(\frac{dy}{dt} = \delta x \cdot y – \gamma y = 0\)
\(\delta x \cdot y = \gamma y \)
\(x = \frac {\gamma}{\delta} \frac {y}{y} \)
\(x = \frac {\gamma}{\delta} \)
Bu eşitlikleri aşağıdaki programla denediğim zaman nüfusların gerçekten de sabir kaldığını gördüm.
from random import betavariate
import numpy as np
import matplotlib.pyplot as plt
alpha = 0.1
beta = 0.04
gamma = 0.04
delta = 0.01
x = gamma/delta
y = alpha/beta
populations = np.empty((0, 2), int)
populations = np.append(populations, np.array(
[[x, y]]), axis=0)
for i in range(1, 1000):
x = x + alpha*x - beta*x*y
if x < 0:
x = 0
y = y + delta*x*y - gamma*y
if y < 0:
y = 0
populations = np.append(populations, np.array(
[[x, y]]), axis=0)
f, (ax1, ax2) = plt.subplots(2)
line1, = ax1.plot(populations[:, 0], color="b")
line2, = ax2.plot(populations[:, 1], color="r")
ax1.set_ylabel("Av")
ax2.set_ylabel("Avcı")
ax2.set_xlabel("zaman")
plt.show()
Peki bu kararlı nüfusları azıcık değiştirirsem ne olur diye düşündüm.
from random import betavariate
import numpy as np
import matplotlib.pyplot as plt
alpha = 0.1
beta = 0.04
gamma = 0.04
delta = 0.01
x = gamma/delta + 0.01
y = alpha/beta - 0.01
populations = np.empty((0, 2), int)
populations = np.append(populations, np.array(
[[x, y]]), axis=0)
for i in range(1, 1000):
x = x + alpha*x - beta*x*y
if x < 0:
x = 0
y = y + delta*x*y - gamma*y
if y < 0:
y = 0
populations = np.append(populations, np.array(
[[x, y]]), axis=0)
f, (ax1, ax2) = plt.subplots(2)
line1, = ax1.plot(populations[:, 0], color="b")
line2, = ax2.plot(populations[:, 1], color="r")
ax1.set_ylabel("Av")
ax2.set_ylabel("Avcı")
ax2.set_xlabel("zaman")
plt.show()
Bu programda başlangıç nüfuslarını çok az değiştirdim ve sonuçta aşağıdaki nüfus değişim grafiğini elde ettim.
Burada da görüldüğü gibi nüfuslar kararlı nüfusların yakınlarında kalıyor ama kararlı nüfuslara dönmüyor. Demek ki bu sistemde asimptotik kararlılık değil de Lyapunov kararlılığı var. Bunu böyle pat diye söyledim ama dayanağım ne? Şimdiye kadar sadece tek bir deneme yaptım ve bu denemeyi sonsuza kadar bile götürmedim. Demek ki biraz da matematik yapmak gerekecek ama o da başka bir yazıda artık.