2015-01-13 27 views
18

İki benzersiz değişken listesi, geçerli ISO standardından the built-ins (ISO/IEC 13211-) kullanılarak tam olarak aynı değişkenleri içeriyorsa (yalnızca başarılı veya başarısız) bir meta mantıksal yüklemin nasıl tanımlanır? 1: 1995, Cor.2 dahil).İki değişken değişkeninin eşitliği

Farklı şekilde ifade edildiğinde, benzersiz değişkenlerden oluşan bir listenin diğerinin bir permütasyonu olması durumunda, yüklemenin başarılı olması gerekir. library(ordsets) benzer şekilde, en ord_seteq/2 aksine, bu yüklem basitçe As == Bs olamaz, bu meta-mantıksal yüklem varset_seteq(As, Bs).

Not diyelim.

+2

İki argümandan herhangi biri benzersiz değişkenlerin bir listesi değilse, başarısızlık başarısız olur mu? –

+1

Sadece bekliyor, belki daha farklı cevaplar vardır. – false

+2

Farklı bir şey deniyordum, ama 'As' ve 'Bs' gerçekten boş değişkenler olup olmadığını kontrol etmek zorunda kaldım. Benim cevabımda, onların 'term_variables/2' ikinci argümanı ile birleşmesi gerektiği gerçeğiyle garanti ediliyor. –

cevap

14

önerip çözüm BsAs üzerinde hiçbir ekstra değişkenler olup olmadığını kontrol etmek için term_variables/2 kullanır ve AsBs görünmüyor hiçbir değişken vardır.

varset_seteq(As, Bs):- 
    term_variables(As-Bs, As), 
    term_variables(Bs-As, Bs). 

yukarıdaki çözüm serbest değişkenlerin setleri olmayan argümanlarla başarılı kandırdın edilebilir:

| ?- varset_seteq([A], [a]). 

A = a 

yes 

Bunu önlemek için birleşme denklik testi ile değiştirilebilir:

varset_seteq(As, Bs):- 
    term_variables(As-Bs, A0), 
    A0 == As, 
    term_variables(Bs-As, B0), 
    B0 == Bs. 
+2

Counterexample cihazınız gerçekten en iyisi! Bu üzücüdür, çünkü aksi takdirde 'term_variables/2', ikinci argümanının iyi bir şekilde kontrol edilmesinin gerekli olduğu gerçeğinden faydalanabilir, bu yüzden uzunluğunun sayılması daha sonra başarısız olmak için kullanılabilir. – false

+0

Bu yaklaşımı seviyorum! Ancak listelerin sadece çubuk olup olmadığını kontrol etmeniz gerekmez mi? Şu an bilgisayarım tarafından değil, ama varset_seteq ([A, B, a], [A, B]) başarılı olmaz mı? –

+2

Hayır, başarılı değil. Bar nedir? –

4

Başka bir çözüm, daha az Tudor'dan daha verimli ' zeki çözüm s ve tavsiye böylece değil ama hala birden çok kez kullanıldığını görüyoruz burada kayda değer şöyledir:

varset_seteq(As, Bs) :- 
    sort(As, Sa), sort(Bs, Sb), Sa == Sb. 
+1

Orijinal cevabım tam olarak bunun hakkındaydı, her iki listenin de değişkenlerden oluşup oluşmadığını kontrol etmek için bir 'varlist/1' yüklemi ekledim. Ama sonra anladım ve Tudor Berariu'nun işaret ettiği gibi, bu yaklaşımın, örneğin, As = [A, A, B, C], Bs = [B, C, B, C, A], üzerinde başarılı olacağı. Muhtemelen orijinal denememi de bırakmış olmalıyım. –

+2

Bu çözüm somut Prolog uygulamalarında çalışırken, Prolog uygulamasının uygulamaya bağlı özelliklerine dayanır. Sa == Sb 'hedefinde artık' Sa 've' Sb 'nin hala sıralı olduğu garanti edilmez. Değişken sıralamayı korumayan bir uygulamada gerçekleşen bir GC'yi düşünün; bu durum, GC'ye "sort/2" sırasında girmezken hala uygun olabilir. – false

+2

@aBathologist Indeed :-) Görünen alternatif çözümlerin tuzaklarını detaylandırmak her zaman buna değer. Yine de, asıl soru, girdinin "iki benzersiz * değişken listesi" olduğunu belirtir (benimki vurgulanır). –

3

başka bir yaklaşım. Biz (her biri kendi üzerinde faydalıdır), bu yüksek mertebeden yüklemler,

select_with(_, _, [], []). 
select_with(P, X, [Y|Ys], Ys)  :- call(P, X, Y), !. 
select_with(P, X, [Y|Ys], [Y|Ks]) :- 
    select_with(P, X, Ys, Ks). 

foldl(_,[],Vn,Vn). 
foldl(P,[X|Xs],V0,Vn) :- 
    call(P,X,V0,V1), 
    foldl_(P,Xs,V1,Vn). 

kendimizi sağlarsanız her üyenin bir liste diğerinde eşit eleman varsa o zaman kolayca kullanarak (doğrudur bir yüklemi tanımlayabilir ==/2): biz gelen argümanlar varsets olduğunu doğrulamak eğer

members_equal(A, B :- 
    foldl(select_with(==), A, B, []). 

Bu yüklem

belirtilen amaç doğrultusunda uzman edilebilir. Aşağıdaki o yöne ile gelip başardık en iyisidir (ama epeyce çıkarımlar yiyor):

is_varset([]). 
is_varset([V|Vs]) :- 
    var(V), 
    maplist(\==(V), Vs), 
    is_varset(Vs). 

(En azından SWI Prolog, sort/2 kullanarak yukarıdaki daha az çıkarımlarda sürer Muhtemelen bu, sıralama işleminin C cinsinden yapılmasından kaynaklanmaktadır. Ayrıca, bu cevap hala term_vars/2 yaklaşımının zarafetine yaklaşmıyor —— "semantik yükselme" nin gücü de budur :)

7

Bunu varsayabilirsek iki liste benzersiz değişkenler içerir, sonra aşağıdaki çift olumsuzlama kullanımı çalışır:

varset_seteq(As, Bs) :- 
    \+ \+ (numbered_from(As, 1), 
      sort(Bs, SBs), 
      As == SBs). 

numbered_from([], _). 
numbered_from([X|Xs], X) :- 
    X1 is X + 1, 
    numbered_from(Xs, X1). 

Bu, Paulo'nun çözümüne benzer, ancak değişken siparişin yalnızca ISO/IEC 13211-1 tarafından tek bir yürütme sırasında sort/2 tutarlı olmasını gerektirmesi sorununu önler.

İlgili konular