2012-10-25 53 views
1

我試着編寫一個可以理解用C#編寫的學生程序的prolog代碼。現在我被困在識別學生課程中'如果'陳述的過程中。例如: 以下是我期望學生的代碼。如何在Prolog中編寫一種有條件的規劃?

int d = int.Parse(Console.ReadLine()); // value d is inputted by user 
int s = 0; 

if (d>0) 
    s = 2; 
else if (d==0) 
    s = 1; 
else 
    s = 0; 

我定義這個目標有望代碼:

goal:- 
    hasVarName(Vid_s, s), 
    hasVarName(Vid_d, d), 
    hasVarValue(Vid_d, Vd), 
    ((not(gt(Vd,0)); hasVarValue(Vid_s, 2)),   %eq: [Vd>0] -> [val_s = 2] 
    ((gt(Vd,0); not(eq(Vd,0)); hasVarValue(Vid_s, 1)), %eq: [~(Vd>0)^(Vd=0)] -> [val_s = 1] 
    ((gt(Vd,0); eq(Vd,0); hasVarValue(Vid_s, 0).  %eq: [~(Vd>0)^~(Vd=0)] -> [val_s = 0] 

的問題是我怎麼能代表在序言事實和規則上的學生代碼,找出我們的目標是滿足的任何可能的情況。

我試圖將學生代碼的第一部分變成類似以下這樣的事實,但並不真正知道如何在prolog中將學生的'if'語句表示爲事實/規則(我想,我不應該將其更改爲Prolog的「如果」,對吧?)

hasVarName(varID_d, d) 
hasVarValue(varID_d, val_d) %it is unknown, so I represent it as symbol 'val_d' 

hasVarName(varID_s, s) 
hasVarValue(varID_s, 0) 

而另外一個,在我的目標,當我有比較如gt(Vd,0)我想我不能比運營商使用的序言時,既不Vd> 0也不Vd @> 0導致Vd中的值實際上是由用戶輸入的某個值,但它被表示爲符號值(在這種情況下,它是:val_d)。

注意:使用上述目標,我認爲如果學生代碼更改爲以下代碼,則已定義的目標將得到滿足。

int d = int.Parse(Console.ReadLine()); // value d is inputted by user 
int s = 0; 

if (d>0) 
    s = 2; 
else if (d==0) 
    s = 1; 

int d = int.Parse(Console.ReadLine()); // value d is inputted by user 
int s = 10;   // any random initialization 

if (d>0) 
{ 
    int x = 2;  // unnecessary step, but still Ok. 
    s = x; 
} 
else if (d==0) 
    s = 1; 
else 
    s = 0; 

但同樣,我需要幫助/想法如何代碼可以在序言爲行動/規則/事實上,以滿足目標來表示。

任何幫助真的很感激。

非常感謝

回答

0

我想你想的模型通過暗示IF-THEN-ELSE,使用 以下布爾身份:

A -> B == ~A v B. 

而不是使用含義的連詞,它更容易 到沿着控制流使用分支在分支之間進行選擇,並且連接 。但是,您通過否定排除之前的條件 仍然是必要的。

把你的例子:

if (d>0) 
    s = 2; 
else if (d==0) 
    s = 1; 
else 
    s = 0; 

您可以使用CLP(*)來建模。添加額外的變量,以便 變量不被覆蓋,但這不是 上面的小代碼片段中的問題。在CLP(*)上面的片段變成,我 正在使用CLP(FD)爲簡單起見:

Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 6.3.0) 
Copyright (c) 1990-2012 University of Amsterdam, VU Amsterdam 
?- use_module(library(clpfd)). 
?- [user]. 
that_if(D, S) :- 
    (D #> 0, S #= 2; 
    D #=< 0, D #= 0, S #= 1; 
    D #=< 0, D #\= 0, S #= 0) 
^D 

在體面CLP(*)系統可以任意地實例化或 約束d或S中的查詢。我們在CLP獲得例如已經 (FD):

/* What conditions give result S #= 1 ? */ 
?- S #= 1, that_if(D, S). 
S = 1, 
D = 0 . 

/* What results give condition D #= 1 */ 
?- D #= 1, that_if(D, S). 
D = 1, 
S = 2 ; 
false. 

/* What conditions give a result S #=< 1 */ 
?- S #=< 1, that_if(D, S). 
S = 1, 
D = 0 ; 
S = 0, 
D in inf.. -1. 

/* What results give a condition D #>= 0 */ 
?- D #>= 0, that_if(D, S). 
S = 2, 
D in 1..sup ; 
D = 0, 
S = 1 ; 
false. 

再見

+0

CLP這很有趣,但我認爲新手可能真的**很難弄清楚它。 – CapelliC

+0

不是我的觀點:我也不知道Budi Hartanto是否是新手,也不知道CLP(*)特別困難的統計數據。 CLP(*)應該更簡單,因爲它更具說明性。 –

+0

此外,沒有一些CLP(*)可以驗證不多。如果你有int d = int.Parse(Console.ReadLine());那麼數據可以是任意的,標準的Prolog窮舉搜索實際上不會用於回答您的查詢。你需要像CLP(*)這樣更具象徵意義的東西。 –

0

通常是一個語言的實現需要一個抽象語法樹,它的方便,指定實現我們被允許到結構的語義動作表現。

您似乎跳過了構建語法樹的階段,並且(用手?)表示程序的中間級別。

如果你堅持這樣的中等水平表示,你可以使用遞歸術語(抽象樹實際上),如if(Condition, Then, Else),其中每個變量反過來是一個語法樹。否則,更實用的表示法(通常用於命令式語言)使用基本塊(不帶跳轉的指令序列)的概念,然後使用標籤來描述執行流。

結果它是一個圖,程序的行爲是由該表示的'拓撲'確定的。

goal:- 
    hasVarName(Vid_s, s), 
    hasVarName(Vid_d, d), 
    hasVarValue(Vid_d, Vd), 

    %eq: [Vd>0] -> [val_s = 2] 
    ((not(gt(Vd,0)); hasVarValue(Vid_s, 2), goto(label(0))), 

    %eq: [~(Vd>0)^(Vd=0)] -> [val_s = 1] 
    ((gt(Vd,0); not(eq(Vd,0)); hasVarValue(Vid_s, 1), goto(label(0))), 

    %eq: [~(Vd>0)^~(Vd=0)] -> [val_s = 0] 
    ((gt(Vd,0); eq(Vd,0); hasVarValue(Vid_s, 0)), % the goto is useless here... 

    label(0), 
    ..... 

請注意,我並沒有支付任何注意正確描述您的樣本程序,只需放置跳躍,以顯示這個可能性......

編輯我認爲一般問題可以沒有解決,相當於圖靈機的halting problem。對於具體的案例,沒有迴路,我會在AST上使用抽象解釋來解決問題。即計算有趣的解釋器。

如果可行取決於目標程序的一般性。您應該能夠爲每個條件點中涉及的每個變量分割整數域。事情變得很複雜...

具體來說,在IF的條件點,然後嘗試分割域。使用這種方法,讓Prolog 執行 IF測試兩個分支,傳播這些值。但是,正如我所說的,不是很容易...

+0

嗨Chac,謝謝你的建議解決方案。你能稍微解釋一下你的建議嗎?爲了您的信息,這是我做的全部事情:我有一個C#程序,用於讀取學生C#程序。在我的C#程序中,我擁有學生代碼的AST。從這個AST中,我創建了prolog子句讓prolog確定我爲學生的任務設定的目標是否滿意。所以,我的C#程序中已經準備好了AST,但是我不知道如何在序言中將它與我的目標聯繫起來。或者,也許我定義我的目標的方式不正確?謝謝 –