Turing makinelerinin simüle edebileceği küçük bir C benzeri dil


11

Öğrencileri, turing makinelerinin yeterince genel bir hesaplama modeli olduğuna 'ikna etmeye' yardımcı olan küçük bir dil arıyorum. Yani, alıştıkları dillere benzeyen bir dil, ancak bir turing makinesinde simüle edilmesi de kolaydır.

Papadimitriou bu iş için RAM makineleri kullanıyor, ancak garip bir şeyi (turing makinesi olarak) başka bir tuhaf şeyle (temel olarak bir montaj dili) karşılaştırmanın birçok öğrenci için çok ikna edici olmayacağından korkuyorum.

Herhangi bir öneri en hoş olurdu (özellikle önerilen bazı literatürle geldiyse)


7
Bilgisayarların başlangıçta montaj dilinde programlanmasının bir nedeni var ... derleyiciler veya tercümanlar yazmak önemsiz değil . Ve Turing makineleri için derleyiciler veya tercümanlar yazmak muhtemelen daha zordur.
Peter Shor

PS ile biraz aynı fikirde olmamalı, TM derleyicisi örneğin faktoring örneklerini SAT veya diğer neredeyse lisansüstü alıştırmalara dönüştürmekten çok daha zor değildir. ayrıca bkz . web üzerindeki en iyi turing makinesi simülatörleri . örnek kaynak koduyla (üst düzey dil için) ruby ​​ile yazılmış bir Turing makinesi derleyicisine bir örnek. ne yazık ki orada daha cilalı olanlar gibi görünmüyor. harika bir açık kaynak projesi yapar.
vzn

2
@OmarShehab, Bir düzenleme soruyu ilk sayfaya yönlendirir. Düzenleme soruyu önemli ölçüde iyileştirmediğinde lütfen eski soruyu düzenlemeyin. Ayrıca, ilk sayfada olmayan çok sayıda soruyu düzenlemek, yeni soruları ilk sayfadan çıkardığı için iyi değildir. Teşekkürler.
Kaveh

@kaveh anlaşıldı.
Omar Shehab

Yanıtlar:


15
  • Öğrencileriniz herhangi bir fonksiyonel programlama yaptıysa, bildiğim en güzel yaklaşım, türlenmemiş lambda hesabı ile başlamak ve daha sonra SKI birleştiricilerine çevirmek için braket soyutlama teoremini kullanmaktır . Daha sonra, Turing makinelerinin kısmi bir kombine cebir oluşturduğunu ve böylece SKI birleştiricilerini yorumlayabildiğini göstermek için ve u t m teoremlerini kullanabilirsiniz .smnutm

    Bunun mümkün olan en basit yaklaşım olduğundan şüpheliyim, ancak hesaplanabilirlikteki en temel teoremlerden bazılarına nasıl dayantığını seviyorum (ki bu başka nedenlerle de örtmek isteyebilirsiniz).

    Görünüşe göre Andrej Bauer birkaç ay önce Mathoverflow'da benzer bir soruyu yanıtladı .

  • C benzeri bir dile ayarlanmışsanız, yolunuz çok daha kaba olacaktır, çünkü oldukça karmaşık bir semantiğe sahiptirler -

    1. Turing makinelerinin bir yığını ve yığını aynı anda simüle edebileceğini göster ve
    2. Değişkenlerin bir yığınla nasıl uygulanabileceğini gösterin ve
    3. Yordam çağrılarının bir yığınla uygulanabileceğini gösterin.

    Dürüst olmak gerekirse, derleyici sınıfının içeriğinin çoğu budur.


7

Yüksek Lisans Teorisi profesörüm, tek bantlı bir Turing makinesinin çok bantlı bir Turing makinesi uygulayabildiğini kanıtlayarak başladı. Bu, değişken bildirimi yönetir: bir programın altı değişken bildirimi varsa, yedi bantlı bir Turing makinesine (her değişken için bir bant ve aritmetik ve eşitlik kontrolü gibi görevleri yerine getirmeye yardımcı olmak için bir "kayıt" bandı üzerine kolayca uygulanabilir bantlar). Daha sonra temel FOR ve WHILE döngülerinin nasıl uygulanacağını gösterdi ve bu noktada Turing-complete C benzeri bir dile sahiptik. Zaten tatmin edici buldum.


6

Şu anda Turing makinelerinin genel bir hesaplama modeli olduğuna kendimi nasıl ikna edeceğimi düşünüyorum. Kilise Turing tezinin, bazı standart ders kitaplarında, örneğin Sipser'de standart muamelenin çok eksiksiz olmadığını kabul ediyorum. İşte Turing makinelerinden daha tanınabilir bir programlama diline nasıl geçebileceğimin bir taslağı.

Özyinelemesiz tanımlı işlevler ve alt yordamlar içeren ve adlandırılmış boole rasgele değişkenleri ve genel boole ifadeleri olan ve artırılabilen veya azaltılabilen bir tamsayı dizi işaretçisine sahip tek bir sınırsız boole dizisi olan ifve whileifadeleriyle blok yapılı bir programlama dili düşünün veya . İşaretçi başlangıçta sıfırdır ve dizi başlangıçta sıfırdır. Bu nedenle, bu bilgisayar dili C benzeri veya Python benzeri olabilir, ancak veri türlerinde çok sınırlıdır. Aslında, o kadar sınırlılar ki, işaretçiyi bir boole ifadesinde kullanmanın bir yolumuz bile yok . Varsayalımtape[n]nn++n--ntapentapeyalnızca sağa sınırsızsa, nnegatifse bir işaretçi alt akışı "sistem hatası" bildirebiliriz . Ayrıca, dilimizin exitbir argümanla birlikte bir boole cevabı çıkarmak için bir ifadesi vardır.

O zaman ilk nokta, bu programlama dilinin bir Turing makinesi için iyi bir şartname dilidir. Bant dizisi hariç, kodun yalnızca son derece olası durumları olduğunu kolayca görebilirsiniz: Bildirilen tüm değişkenlerinin durumu ve geçerli yürütme satırı ve alt rutin yığını. İkincisinin yalnızca sınırlı bir durumu vardır, çünkü özyinelemeli işlevlere izin verilmez. Bu tür bir koddan "gerçek" bir Turing makinesi oluşturan bir "derleyici" hayal edebilirsiniz, ancak bunun ayrıntıları önemli değildir. Mesele şu ki, oldukça iyi sözdizimine sahip, ancak çok ilkel veri türlerine sahip bir programlama dilimiz var.

Yapının geri kalanı, bunu sınırlı kütüphane fonksiyonları ve ön derleme aşamaları listesi ile daha yaşanabilir bir programlama diline dönüştürmektir. Aşağıdaki gibi devam edebiliriz:

  1. Bir ön derleyici ile, boole veri tipini ASCII gibi daha büyük ama sonlu bir sembol alfabesine genişletebiliriz. Bunun tapebu daha büyük alfabedeki değerleri aldığını varsayabiliriz . İşaretçinin taşmasını önlemek için bandın başında bir işaretleyici ve TM'nin yanlışlıkla bantta sonsuzluğa kaymasını önlemek için bandın sonunda hareketli bir işaretleyici bırakabiliriz. Semboller ve boolean ifve whileifadeleri için dönüşümler arasında isteğe bağlı ikili işlemler gerçekleştirebiliriz . (Aslında ifile uygulanabilir whilemevcut olmasaydı, hem de.)

  2. kkbenbenk

  3. Bir bandı sembol değerli "bellek", diğer bandı işaretsiz, tamsayı değerli "kayıt" veya "değişken" olarak adlandırıyoruz. Tam sayıları sonlandırma işaretçileri olan küçük endian ikili dosyasında saklarız. İlk olarak bir sicilin bir kopyasını ve bir sicilin ikili azalmasını uygularız. Bunu bellek işaretçisinin artması ve azalmasıyla birleştirerek, sembol belleğine rasgele erişim araması uygulayabiliriz. Tamsayıların ikili toplanmasını ve çarpılmasını hesaplamak için fonksiyonlar da yazabiliriz. Bitsel işlemlerle ikili bir ekleme işlevi ve sola kaydırma ile 2 ile çarpma işlevi yazmak zor değildir. (Ya da gerçekten sağa kaydırma, çünkü küçük endian.) Bu ilkellerle, uzun çarpma algoritmasını kullanarak iki kaydı çoğaltmak için bir işlev yazabiliriz.

  4. Formülü kullanarak bellek bandını bir boyutlu sembol dizisinden symbol[n]iki boyutlu sembol dizisine yeniden düzenleyebiliriz . Şimdi, tek boyutlu, rasgele erişimli, tamsayı değerli bir bellek elde etmek için, bir sonlandırma simgesiyle ikili olarak işaretsiz bir tamsayıyı ifade etmek için belleğin her bir satırını kullanabiliriz . Bellekten bir tamsayı yazmacına okuma ve bir yazmaçtan belleğe yazma uygulayabiliriz. Artık birçok özellik fonksiyonlarla uygulanabilir: İmzalı ve kayan nokta aritmetiği, sembol dizeleri, vb.symbol[x,y]n = (x+y)*(x+y) + ymemory[x]

  5. Sadece bir temel tesis kesinlikle ön derleyici yani özyinelemeli fonksiyonlar gerektirir. Bu, yorumlanmış dilleri uygulamak için yaygın olarak kullanılan bir teknikle yapılabilir. Her bir üst düzey, özyinelemeli işleve bir ad dizesi atarız ve düşük düzeyli kodu while, normal parametrelerle bir çağrı yığını tutan tek bir büyük döngü halinde düzenleriz: çağrı noktası, çağrılan işlev ve bağımsız değişkenler listesi.

Bu noktada, yapı, üst düzey bir programlama dilinin, daha fazla işlevselliğin CS teorisinden ziyade programlama dilleri ve derleyicileri konusu olduğu yeterli özelliklerine sahiptir. Bu gelişmiş dilde bir Turing makinesi simülatörü yazmak da kolaydır. Dil için kendi kendine derleyici yazmak tam olarak kolay değil, ama kesinlikle standarttır. Tabii ki bu C benzeri veya Python benzeri dilde bir koddan dış TM oluşturmak için bir dış derleyiciye ihtiyacınız vardır, ancak bu herhangi bir bilgisayar dilinde yapılabilir.

Bu kabataslak uygulamanın sadece özyinelemeli işlev sınıfı için mantıkçıların Church-Turing tezini değil, aynı zamanda deterministik hesaplama için geçerli olduğu gibi genişletilmiş (yani polinom) Church-Turing tezini de desteklediğini unutmayın. Başka bir deyişle, polinom yükü vardır. Aslında, bize bir RAM makinesi veya (benim favorim) bir ağaç kaseti TM verilirse, RAM belleğiyle seri hesaplama için polilogaritmik yüke indirgenebilir.


5

LLVM derleyicisi, yeni bir mimariyi oldukça basit bir şekilde "takmayı" sağlar. Onlar bu çağrı yeni bir arka uç yazma ve vermek detaylı talimatlar ve örnekler bunu nasıl için. Bir RAM Turing makinesini hedeflemek istemiyorsanız, rastgele erişim belleği ile ilgili olarak bazı çemberlerden atlamak zorunda kalacağınızdan şüpheleniyorum, ancak LLVM'nin üretmesine neden olan bir dizi proje gördüğüm için kesinlikle yapılabilir. VHDL veya diğer çok farklı makine dilleri.

Bu, bir Turing makinesi için son teknoloji optimizasyon derleyicisine (birçok yönden LLVM, GCC'den daha gelişmiş) sahip olmanın ilginç bir etkisi olacaktır.


1

Ben cs teorisinde değilim ama yararlı olabilecek bir şey var. Başka bir yaklaşım aldım. Doğrudan C'nin küçük bir alt kümesiyle programlanabilen basit bir işlemci tasarladım. Montaj kodu YOK, sadece C benzeri kod var. Turing makine simülatörünüzü tasarlamak için kullandığım aynı aracı kullanabilir ve bu işlemciyi değiştirebilirsiniz. Bu işlemciyi tasarlamak, simüle etmek ve test etmek 4 gün sürdü, birkaç talimat! Kullandığım araçlar, gerçek VHDL sentezlenebilir kodu oluşturmamı bile sağladı. Gerçek çalışan bir işlemcidir.

Program şöyle görünür: C Benzeri Montaj Programı Örneği

İşte bu Araçları kullanan işlemcinin bir resmi: İşlemci Devresi

"Novakod Studio" Araçları Üst Düzey Dil Donanım Tanımlama Dili kullanır. Örnek olarak, program sayacının kodu: psC - Paralel ve senkron C - kod örneği Yeterli konuşmak, eğer ilgilenen varsa, benimle iletişime geçmek için genel bilgiler: https://repertoire.uqac.ca/Fiche.aspx?id=JjstNzsH0&link=1

Luc


adresleme, adresleri bulmak için sabit bir bit sayısı kullanıyor mu?
vzn

Evet, ancak bellek boyutunu değiştirmek kolaydır (int DataMemory [SIZE]. Dil değişken uzunluk tamsayısını (int: 10) destekler, ancak FPGA'yı hedeflediği için dizi statik ve boyut sabittir.
Luc Morin

1

GMB kullanıcısı tarafından temsil edilen fikri burada almaya ne dersiniz (Bir bantla Turing makinesi, N bantlarını tek bir banda araya getirerek ve bu bantlardan herhangi birini bir kerede N konum atlayarak bir Turing makinesini simüle edebilir. N bantlı makine uygulayabilir ...) ve basit bir RAM makinesi uygulayan bir Turing makine programı yazabilir. RAM makinesi aslında mevcut LLVM veya GCC arka ucuna sahip basit, gerçek bir CPU olabilir. Daha sonra GCC / LLVM, bu CPU için bir C programının çapraz derlenmesi ve RAM makinesini simüle eden Turing makine programı, simüle edilmiş RAM makinesinin GCC / LLVM çıkışını yürütmesini sağlayarak RAM makinesi simülasyonunu çalıştırır. Turing makinesi uygulaması, küçük bir C dosyasına uyan çok basit bir C kodu olabilir.

RAM makinesi ile ilgili olarak, 32bit CPU'nun 8bit mikrodenetleyici tarafından simüle edildiği ve simüle edilmiş 32bit CPU'nun Linux'u başlattığı bir demo projesi var. Cehennem kadar yavaş, ama yazar Dmitry Grinberg'e göre işe yaradı. Belki de Zylin CPU (GitHub kullanıcısı zylin) simüle edilebilir RAM makinesi için uygun bir seçim olabilir. Başka bir RAМ makinesi adayı, Niklaus Wirth'in ProjectOberon dot com'su olabilir .

(Metnimdeki "nokta" ve "com", sadece 2015_10_21 hesabımı cstheory.stackexchange'e kaydettirmem ve web uygulamasının acemi kullanıcılar için 2'den fazla bağlantıya izin vermemesinden kaynaklanıyor diğer stackexchange hesaplarımdan aptal olabileceğimi otomatik olarak görebiliyorlar, ancak trol değilim.)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.