2015-02-10 22 views
5

Yasal olarak sınırsız sonuçların tüm öğelerini sıralayabilecek herhangi bir prolog uygulaması var mı?Prolog: Adsız Sonsuz Sonuçların Tüm Unsurlarını Numaralandırın

Tüm doğal sayı çiftlerini numaralandırmayı düşünelim. Eğer çiftleri {(0,0), (0,1), (1,0), (0,2), (1,1), (2,0), ...} sıralarına göre numaralandırırsak tüm çiftleri sıralayabilir. Bununla birlikte, eğer aşağıdaki GNU prolog programı olarak {(0,0), (0,1), (0,2), (0,3) ...} sıralarıyla çiftleri sayıyorsak, (1,1).

% cat nats.pl 
nat(0). 
nat(X1) :- nat(X), X1 is X + 1. 

pair_of_nats(X, Y) :- nat(X), nat(Y). 
% prolog 
GNU Prolog 1.3.0 
By Daniel Diaz 
Copyright (C) 1999-2007 Daniel Diaz 
| ?- ['nats.pl']. 
compiling /home/egi/prolog/nats.pl for byte code... 
/home/egi/prolog/nats.pl compiled, 4 lines read - 762 bytes written, 9 ms 

yes 
| ?- pair_of_nats(X,Y). 

X = 0 
Y = 0 ? ; 

X = 0 
Y = 1 ? ; 

X = 0 
Y = 2 ? ; 

X = 0 
Y = 3 ? 
+0

Teşekkürler! Arama algoritmasını derinlik-ilk aramadan ilk ilk aramaya kadar yapılandırabileceğimiz herhangi bir uygulama var mı? Bence, bazı durumlarda, ilk arama, yararlıdır ve derinlemesine ilk arama için programı yeniden yazma programı dağınık hale getirir. – egi

+1

Varsayılan stratejinin önce derinlik olmasının iyi nedenleri vardır. Ardından gelen çözümler, herhangi bir önemsiz sıraya göre sıralanmamıştır, bu nedenle programınızda, tam olarak neyin peşinde olduğunuzu açıklamanız beklenir. –

+1

Şimdiye kadar sunulan cevaplar doğal sayı çiftleri oluşturmak için güzel, ama sanıyorum daha genel sorun, Prolog'un arama stratejisi tarafından vurgulandığı gibi @Boris tarafından vurgulanacaktır.Eğer iki (ya da daha fazla) keyfi yükleminiz varsa, p1 've' p2 ', her biri bir tür sonsuz sayıda çözüm üretiyorsa, Prolog'un çözümlerini ilk bakışta, kendi aralarında çözümlerini keşfetmesi için bir yol olduğundan emin değilim. Doğal sayılar (* örn. *, 'p1 (N, ...)', 'p2 (N, ...)' ile açık bir ilişkiye sahip olmadıkça, doğal sayı metodu kısıtlamak için kullanılabilir. backtracking sonuçları. – lurker

cevap

-1

I 'iç tabakalara' doyurmaya yeterli olması için, bunun yerine Nat/'1, 3/arasında olduğu gibi, isteğe bağlı sınırlı bir üst değere sahip bir jeneratör kullanmak öneriyoruz. Örneğin

?- between(0,inf,A),between(0,A,B). 
A = B, B = 0 ; 
A = 1, 
B = 0 ; 
A = B, B = 1 ; 
A = 2, 
B = 0 ; 
A = 2, 
B = 1 ; 
A = B, B = 2 ; 
A = 3, 
B = 0 
.... 

için GNU Prolog belki current_prolog_flag(max_integer,Z) ekleyip yerine inf ait Z kullanın between(0,inf,A) izin vermez.

+0

Teşekkürler! Kod çok basit! – egi

+2

Bu yaklaşımın bir sınırı, hiçbir zaman '(A, B)' yi 'B 'A' oluşturamayacağıdır. – lurker

+2

'length (_, A)' inf', SWI'ye özel – false

2

Sen çiftlerinin her oluşturmak için CLPFD (sonlu etki alanları üzerinde kısıtlama mantık programlama) kullanabilirsiniz: aynı yöne çalışan (

nat(0). 
nat(X1) :- nat(X), X1 is X + 1. 

pairs((A, B)) :- 
    nat(X), 
    A + B #= X, 
    fd_labeling([A,B]). 

Bu yaklaşık klasik Cantor's proof that the rationals are countable kullanılan rasyonel sayı matrisi geçişi izler sonuçlanan) yerine alternatif her diyagonal tarih:

| ?- pairs(P). 

P = (0,0) ? ; 

P = (0,1) ? ; 

P = (1,0) ? ; 

P = (0,2) ? ; 

P = (1,1) ? ; 

P = (2,0) ? ; 

P = (0,3) ? ; 

P = (1,2) ? ; 

P = (2,1) ? ; 

P = (3,0) ? ; 

P = (0,4) ? ; 
... 
+1

'nat/1' tanımınız çok verimsiz: İkinci dereceden maliyeti vardır. Hatta uzunluk (_, X) 'daha hızlıdır. Bunu deneyin: '(nat (N), N = 10000)' ve '(uzunluk (_, N), N = 10000)' – false

+2

Çiftler/2'ye gelince: (çift, (A, B)): - A #> = 0, B #> = 0, X #> = 0, A + B # = X, uzunluk (_, X). 'Bu sadece daha hızlı değil, daha iyi sona erer, aynı zamanda SICStus ve SWI'da da çalışır. – false

+0

@false Sadece OP'nin gösterim için 'nat/1' tanımını yanlışıyordum. Daha verimli bir versiyon sunmayı düşünmemekle birlikte, cevabın özü tanımlandıktan sonra 'nat/1' ile ne yapılacağıdır. Ve çiftler üzerinde önerilen verimlilik artışı için teşekkürler. Ancak, GNU Prolog'da "yakalanmamış istisna" üretir: error (type_error (integer, _ # 4195348 (0..268435455)), (# =)/2). – lurker

3

için sahip nat/1 bu tanımla kolayca yapılabilir olmadığı nedeni, istediğiniz düzen bir arama gerektirmesi ispatlanmış ağacın ne kadar derin olduğu, ne de ilk genişliği. @CapelliC'nin cevabı geniş bir ilk aramadır. @lurker tarafından verilen cevap, size sonradan gelen cevapları verir.

pairs(A, B) :- 
    pairs_1(0, 0, A, B). 

pairs_1(A, B, A, B). 
pairs_1(A, B, RA, RB) :- 
    ( succ(B1, B) 
    -> succ(A, A1), 
     pairs_1(A1, B1, RA, RB) 
    ; succ(A, B1), 
     pairs_1(0, B1, RA, RB) 
    ). 

Bu sadece rasyonel sayı matrisi ile "hareket" Tüm Numaralandırılacak anlatılmaktadır:

Eğer bir nedenle veya CLPFD kullanmak istemiyorsanız başkası için, burada saf Prolog bir çözümdür tam sayı çiftleri.

2

CappeliCs çözümünün iyi olduğunu düşündüm. Ama sonra Lurkers bakarak
CLP (FD) çözümü, şu düşünüyorum komple Prolog çözümdür:

?- between(0, inf, X), between(0, X, A), B is X-A. 

Bye

PS:

: İşte SWI-Prolog çalıştırmak bir örnektir
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.1.33) 
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam 
?- [user]. 
pair((A, B)) :- 
    between(0, inf, X), 
    between(0, X, A), 
    B is X-A. 

?- pair(P). 
P = (0, 0) ; 
P = (0, 1) ; 
P = (1, 0) ; 
P = (0, 2) ; 
P = (1, 1) ; 
P = (2, 0) ; 
...