Soru Mathematica: sembolik programlama nedir?


Ben Stephen Wolfram'ın büyük bir hayranıyım, ama kesinlikle kendi boynuzunu çekmekten çekinmiyor. Birçok referansta Mathematica'yı farklı bir sembolik programlama paradigması olarak ifade ediyor. Ben bir Mathematica kullanıcısı değilim.

Sorularım: bu sembolik programlama nedir? Ve fonksiyonel dillerle (Haskell gibi) nasıl karşılaştırılır?


76
2017-12-13 16:28


Menşei




Cevaplar:


Mathematica'nın sembolik programlamasını, arama ve değiştirme kurallarını belirterek programladığınız bir arama ve değiştirme sistemi olarak düşünebilirsiniz.

Örneğin, aşağıdaki kuralı belirtebilirsiniz

area := Pi*radius^2;

Bir dahaki sefere kullan areaile değiştirilecek Pi*radius^2. Şimdi, yeni kuralı tanımladığınızı varsayalım.

radius:=5

Şimdi, ne zaman istersen radius, yeniden yazılacak 5. Değerlendirirsen area yeniden yazılacak Pi*radius^2 hangi için kural yeniden yazma tetikler radius ve alacaksın Pi*5^2 bir ara sonuç olarak. Bu yeni form, için dahili bir yeniden yazma kuralını tetikleyecektir. ^ operasyon böylece ifade yeniden yazılacak Pi*25. Bu noktada, yeniden yazma geçerli kurallar olmadığından durur.

İşlevsel programlamayı, değiştirme kurallarınızı işlev olarak kullanarak taklit edebilirsiniz. Örneğin, ekleyen bir işlev tanımlamak isterseniz

add[a_,b_]:=a+b

şimdi add[x,y] yeniden yazılır x+y. Sadece a, b için başvurmak için eklemek isterseniz, bunun yerine

add[a_?NumericQ, b_?NumericQ] := a + b

Şimdi, add[2,3] yeniden yazılır 2+3 kuralınızı kullanarak ve sonra 5 için yerleşik kural kullanma +, buna karşılık add[test1,test2] değişmeden kalır.

İşte bir interaktif ikame kuralı örneği

a := ChoiceDialog["Pick one", {1, 2, 3, 4}]
a+1

İşte, a ile değiştirilir ChoiceDialogDaha sonra, kullanıcı, açılan miktardaki iletişim kutusu üzerinde seçtiği numarayla değiştirilir; +. İşte, ChoiceDialog "Select ChoiceDialog [bazı şeyleri] kullanıcı tarafından tıklatılan düğmenin değeriyle değiştir" satırları boyunca yerleşik bir değiştirme kuralı olarak.

Kurallar, üretebilmek için kural yeniden yazmanın içinden geçmesi gereken koşullar kullanılarak tanımlanabilir. True veya False. Örneğin, yeni bir denklem çözme yöntemini icat ettiğinizi varsayalım, ancak yalnızca yönteminizin son sonucu olumlu olduğunda işe yaradığını düşünüyorsunuz. Aşağıdaki kuralı yapabilirsin

 solve[x + 5 == b_] := (result = b - 5; result /; result > 0)

İşte, solve[x+5==20] 15 ile değiştirilir, ama solve[x + 5 == -20] değişmez çünkü geçerli kural yoktur. Bu kuralın uygulanmasını engelleyen koşul şu: /;result>0. Değerlendirici, esas olarak, kural uygulamasının çıkıp çıkmayacağına karar vermek için potansiyel kural uygulamasının çıktısını arar.

Mathematica'nın değerlendiricisi, her örüntüyü açgözlülükle o sembol için geçerli olan kurallardan biriyle yeniden yazar. Bazen daha iyi bir kontrole sahip olmak istersiniz ve bu durumda kendi kurallarınızı tanımlayabilir ve bunları manuel olarak uygulayabilirsiniz.

myrules={area->Pi radius^2,radius->5}
area//.myrules

Bu, tanımlanan kuralları uygular. myrules sonuç değişene kadar Bu, varsayılan değerlendiriciye oldukça benzer, ancak şimdi birkaç kural kümesine sahip olabilir ve bunları seçmeli olarak uygulayabilirsiniz. Daha gelişmiş örnek Kural uygulamalarının dizileri üzerinde arama yapan Prolog benzeri bir değerlendiricinin nasıl yapıldığını gösterir.

Mathematica'nın varsayılan değerlendiricisini kullanmanız gerektiğinde şu anki Mathematica versiyonunun bir dezavantajı ortaya çıkıyor ( Integrate, Solve, vb) ve Varsayılan değerlendirme sırasını değiştirmek istiyorum. Bu mümkün ama karmaşıkve ben sembolik programlamanın gelecekteki bazı uygulamalarının değerlendirme dizisini kontrol etmenin daha zarif bir yoluna sahip olacağını düşünmeyi seviyorum.


70
2017-12-13 22:12



@Yaro Sanırım fonksiyonların sonucu olarak kurallar aldığınızda (Solve, DSolve, vb.) - Dr. belisarius
Ama düşünebilirsin Solve bir başka yeniden yazma kuralları kümesi. Mathematica'nın çözemediği bazı denklemler verdiğinizde Solve[hard_equations] olarak kalır Solve[hard_equations] ve bir özel tanımlayabilirsiniz Solve Bu durumda geçerli olan kural. Bu durumda, tahmin ettiğim /; "Matematiksel yöntemlerle çözülebilen herhangi bir denklem" için kalıbı tanımlamak şartıyla, sabit denklemler için geçerli kural geçerli değildir ve Solve orijinal formda kalır - Yaroslav Bulatov
Bence bu onu çok karmaşık hale getiriyor, Mathematica programları temelde yeni değiştirme kuralları. Yürütme, kurallara uyuluncaya kadar var olan kuralları girişe uygulama işlemidir. - Yaroslav Bulatov
+1 Çok hoş sakinleştirilmemiş no-korna üfleme açıklama. Belki de eklemek istediğim tek şey, çoğu dilde mevcut olan tüm matematiksel kütüphaneleri temsil eden kernelde yer alan kurallar ve algoritmaların ve daha sonra birkaçının da var olduğu gazilyonlar var. - Dr. belisarius
Simon, lambda hesabı kendisi yeniden yazma sistemlerinden sadece biridir. Terimin yeniden yazılması, herhangi bir özel TRS'den daha genel bir yaklaşımdır. - SK-logic


"Sembolik programlama" deyimini duyduğumda, LISP, Prolog ve (evet) Mathematica hemen aklınıza gelir. Sembolik bir programlama ortamını, program metnini temsil etmek için kullanılan ifadelerin de birincil veri yapısı olduğu bir karakter olarak nitelendiririm. Sonuç olarak, veriler kolaylıkla kodlara dönüştürülebildiğinden ve tam tersi olduğundan, soyutlamalar üzerine soyutlamalar yapmak çok kolay hale gelir.

Mathematica bu kabiliyeti büyük ölçüde sömürüyor. LISP ve Prolog'dan (IMHO) daha ağır.

Bir sembolik programlama örneği olarak, aşağıdaki olaylar dizisini göz önünde bulundurun. Şuna benzeyen bir CSV dosyasına sahibim:

r,1,2
g,3,4

Şu dosyayı okudum:

Import["somefile.csv"]
--> {{r,1,2},{g,3,4}}

Sonuç verileri mi yoksa kod mu? İkisi de. Dosyayı okumaktan kaynaklanan verilerdir, fakat aynı zamanda bu verileri oluşturacak olan ifade de olur. Bununla birlikte, kod ilerledikçe, bu ifade, değerlendirmenin sonucu basitçe kendiliğinden beri etkisizdir.

Şimdi sonuçlara bir dönüşüm uyguluyorum:

% /. {c_, x_, y_} :> {c, Disk[{x, y}]}
--> {{r,Disk[{1,2}]},{g,Disk[{3,4}]}}

Ayrıntılar üzerinde durmadan, tüm olanlar oldu Disk[{...}] her giriş satırından son iki sayıya sarılmıştır. Sonuç hala veri / kod, ama hala inerttir. Başka bir dönüşüm:

% /. {"r" -> Red, "g" -> Green}
--> {{Red,Disk[{1,2}]},{Green,Disk[{3,4}]}}

Evet, hala inert. Ancak, dikkat çekici bir tesadüf ile bu son sonuç, Mathematica'nın grafikler için yerleşik alana özgü dilinde geçerli direktiflerin bir listesidir. Son bir dönüşüm ve şeyler olmaya başlar:

% /. x_ :> Graphics[x]
--> Graphics[{{Red,Disk[{1,2}]},{Green,Disk[{3,4}]}}]

Aslında, son sonucu göremezdiniz. Sözdizimsel şekerin destansı bir göstergesinde Mathematica, kırmızı ve yeşil dairelerin bu resmini gösterecekti:

alt text

Ama eğlence burada bitmiyor. Bu sözdizimsel şekerin altında hala sembolik bir ifade var. Başka bir dönüşüm kuralı uygulayabilirim:

% /. Red -> Black

alt text

Presto! Kırmızı daire siyah oldu.

Sembolik programlamayı karakterize eden bu tür bir "sembol iterek" dir. Mathematica programlamanın büyük bir kısmı bu niteliktedir.

İşlevsel ve Sembolik

Sembolik ve fonksiyonel programlama arasındaki farklılıkları ayrıntılı olarak ele almayacağım, ancak birkaç söze katkıda bulunacağım.

Sembolik programlamayı şu soruya bir cevap olarak görebiliriz: “Her şeyi sadece ifade dönüşümlerini kullanarak modellemeye çalışırsam ne olur?” Aksine, işlevsel programlama, şu soruya bir cevap olarak görülebilir: “Sadece işlevleri kullanarak her şeyi modellemeye çalışırsam ne olur?” Sembolik programlama gibi, fonksiyonel programlama hızlı bir şekilde soyutlama katmanlarını oluşturmayı kolaylaştırır. Burada verdiğim örnek, işlevsel tepkisel animasyon yaklaşımı kullanarak Haskell'de kolayca çoğaltılabilir. Fonksiyonel programlama, fonksiyon kompozisyonu, üst düzey fonksiyonlar, kombinatorler - fonksiyonlarla yapabileceğiniz tüm şık şeylerle ilgilidir.

Mathematica, sembolik programlama için net bir şekilde optimize edilmiştir. İşlevsel tarzda kod yazmak mümkündür, ancak Mathematica'daki işlevsel özellikler gerçekten sadece dönüşümler üzerinde ince bir kaplamadır (ve bunun altında sızan bir soyutlama, aşağıdaki dipnota bakınız).

Haskell, fonksiyonel programlama için net bir şekilde optimize edilmiştir. Sembolik tarzda kod yazmak mümkündür, ama ben bunu sözdizimsel Programların ve verilerin temsili oldukça farklıdır ve bu da deneyimi düşüktür.

Son sözler

Sonuç olarak, işlevsel programlama (Haskell tarafından örneklendiği gibi) ve sembolik programlama (Mathematica tarafından örneklendiği gibi) arasında bir ayrım olduğunu savunuyorum. Bence her ikisi de ders çalışıyorsa, o zaman biri sadece bir tane üzerinde çalışmaktan çok daha fazlasını öğrenecektir - nihai ayrıcalık testi.


Mathematicada Sızıntılı Fonksiyonel Soyutlama?

Evet, sızdıran. Bunu deneyin, örneğin:

f[x_] := g[Function[a, x]];
g[fn_] := Module[{h}, h[a_] := fn[a]; h[0]];
f[999]

WRI tarafından usulüne uygun olarak bildirilmiş ve onaylanmıştır. Tepki: kullanımından kaçının Function[var, body] (Function[body] tamam).


72
2017-12-14 03:54



WRI sizi önlemek için gerçekten tavsiye etti mi Function[var, body]? Dokümanlar için önerildiği için bu garipti ... - Simon
@Simon: Evet, WRI’den bir e-posta adresim var. Bu, "çağrı zincirindeki" herhangi bir arayanın benzer bir sembol kullanıp kullanmadığına bağlı olarak değişen bir fonksiyonun semantiği hakkında endişelendiğimde, kullanma Function[var, body]. Bunun neden düzeltilemeyeceği konusunda bir açıklama yapılmadı, ancak bu yana Function O zamandan bu yana oyunda bu davranışı değiştirmek için felaket olur. Sorun (biraz) daha ayrıntılı olarak açıklanmıştır İşte. - WReach
Dahililarının mma'da maruz kaldığı seviyeyle, bundan bile emin değilim. Function prensipte bile, tedavi edilebilir - en azından şu anki izinsiz semantikleri ile Rule ve RuleDelayedİç kapsam oluşturma yapılarının bağlarına uymayan, kendileri de dahil olmak üzere. Bu fenomen bana bu özelliği ile daha ilgili görünüyor Rule ve RuleDelayed, özellikle Function. Ama her halükarda, bunu değiştirmenin artık çok tehlikeli olduğuna katılıyorum. Çok kötü çünkü Function[var,body] Kullanılmamalıdır - bu tür hatalar büyük projelerde yakalamak neredeyse imkansız olacaktır. - Leonid Shifrin
@WReach MathicsBir FOSS Mathematica klonu olan Sızdırmaz İşlev sorununa sahip değil! Sadece denedim. - M. Alaggan


Burada daha önce de belirttiğimiz gibi Mathematica bir çok terim yeniden yazıyor. Belki de Haskell en iyi karşılaştırma değil ama Saf güzel bir işlevsel terim yeniden yazma dili (Haskell geçmişi olan insanlara aşina olmalı). Belki de tekrar yazarken Wiki sayfalarını okuyarak sizin için birkaç şey açıklığa kavuşacaktır:

http://code.google.com/p/pure-lang/wiki/Rewriting


9
2017-12-14 09:37



Semantik olarak, Saf Şemaya (dinamik yazım, istekli değerlendirmeye varsayılan değerler) veya OCaml'e (açık referans hücrelere sahiptir) benzer. Ama sözdizimi ve kütüphaneler Haskell'in aynasını yapıyor. - dubiousjim


Mathematica, terimin büyük ölçüde yeniden yazılmasını kullanıyor. Dil, çeşitli yeniden yazma biçimleri, kurallar ve stratejiler için özel destek için özel sözdizimi sağlar. Bu paradigma "yeni" değil ve elbette ki benzersiz değil, kesinlikle Axiom gibi diğer güçlü oyuncularla birlikte bu "sembolik programlama" olayının kanayan kenarında.

Haskell ile kıyaslandığında, oraya yeniden yazabilirdiniz, boilerplate kütüphanenizden bir miktar yardım alabilirsiniz, ancak dinamik olarak yazılan Mathematica'daki kadar kolay değildir.


5
2017-12-13 18:23