Đây là code C# cho suy diễn tiến với logic mệnh đề
[code]using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Frmnhapluat : Form
{
string cat1,cat2,cat3;
string kl;
bool ketluan=false, cai=false;
int vitri,demgt,demluat,demsat,md_don,n;
Int32[] r_cot = new int[10];//Xác định tập luật bằng cách tìm toạ độ, gióng ngang và dọc để tìm mệnh đề sinh ra chúng.
Int32[] r_hang=new int[10];
Int32[] SAT_cot = new int[10];//Toạ độ luật lấy ra từ tgian ở trên mảng "mang"
Int32[] SAT_hang = new int[10];
String[] gt=new string [20];
String[] mddon = new string[10];
String[] tgian = new string[30];// Tập trung gian(mệnh đề đúng tại thời điểm htại)
String[,] mang = new string[20,21];
void reset()// Reset lại các mảng, biến, textbox
{
cat1 = null; cat2 = null; cat3 = null;
kl = null;
vitri = 0; demgt = 0; demluat = 0; md_don = 0;
r_cot = new int[10];
r_hang = new int[10];
for (int i = 0; i < gt.Length;i++)
gt[i] = null;
for (int i = 0; i < tgian.Length; i++)
tgian[i] = null;
for (int i = 0; i < 20; i++)
for(int j=0;j<20;j++)
mang[i,j] = null;
SAT_cot = new int[10];
SAT_hang = new int[10];
txtdsluat.Text = "";
txtgt.Text = "";
txtkl.Text = "";
txtluat.Text = "";
txtthongbao.Text = "";
}
int timvitri1(string bien)// tim vi tri tren mang khi biet menh de
{
if (bien == "a")
vitri= 1;
else
if (bien == "b")
vitri = 2;
else
if (bien == "c")
vitri = 3;
else
if (bien == "d")
vitri = 4;
else
if (bien == "e")
vitri = 5;
else
if (bien == "f")
vitri = 6;
else
if (bien == "g")
vitri = 7;
else
if (bien == "h")
vitri = 8;
else
if (bien == "i")
vitri = 9;
else
if (bien == "j")
vitri = 10;
return vitri;
}
// tim vi tri tren mang khi biet menh de (phuc)
int timvitri2(string bien)
{
if (bien == "a")
vitri = 1;
else
if (bien == "b")
vitri = 2;
else
if (bien == "c")
vitri = 3;
else
if (bien == "d")
vitri = 4;
else
if (bien == "e")
vitri = 5;
else
if (bien == "f")
vitri = 6;
else
if (bien == "g")
vitri = 7;
else
if (bien == "h")
vitri = 8;
else
if (bien == "i")
vitri = 9;
else
if (bien == "j")
vitri = 10;
return vitri;
}
int timvitri3(string bien)// tim vi tri tren mang khi biet menh de (don)
{
if (bien == "a")
vitri = 11;
else
if (bien == "b")
vitri = 12;
else
if (bien == "c")
vitri = 13;
else
if (bien == "d")
vitri = 14;
else
if (bien == "e")
vitri = 15;
else
if (bien == "f")
vitri = 16;
else
if (bien == "g")
vitri = 17;
else
if (bien == "h")
vitri = 18;
else
if (bien == "i")
vitri = 19;
else
if (bien == "j")
vitri = 20;
return vitri;
}
public Frmnhapluat()
{
InitializeComponent();
}
private void Frmnhapluat_Load(object sender, EventArgs e)
{
textBox1.Text = "- Nhập các mệnh đề từ a -> j." + "\r\n - Mệnh đề là các chữ cái thường (a, b, c...)." + "\r\n - Nhập mệnh đề logic theo nút hỗ trợ đã có sẵn." + "\r\n - Không dùng dấu cách khi nhập luật." + "\r\n - Chọn xong 1 mệnh đề giả thiết bạn phải bấm nút 'Chọn'.";
txtdsluat.Enabled = false;
txtgt.Enabled = false;
txtluat.Focus();
}
private void btnand_Click(object sender, EventArgs e)
{
txtluat.Text =txtluat.Text + " ^ ";
txtluat.Focus();
txtluat.Select(txtluat.Text.Length, 0);
}
private void btnsuyra_Click(object sender, EventArgs e)
{
txtluat.Text =txtluat.Text + " --> ";
txtluat.Focus();
txtluat.Select(txtluat.Text.Length, 0);
}
private void btnok_Click(object sender, EventArgs e)
{
demluat++;
int dd = (txtluat.Text).Length;
if (dd == 11)
{
cat1 = txtluat.Text.Substring(0, 1);
cat2 = txtluat.Text.Substring(4, 1);
cat3 = txtluat.Text.Substring(10, 1);
mang[timvitri1(cat1), timvitri2(cat2)] = cat3;
r_hang[demluat] = timvitri1(cat1);
r_cot[demluat] = timvitri2(cat2);
}
if (dd == 7)
{
md_don++;
cat1 = txtluat.Text.Substring(0, 1);
cat2 = txtluat.Text.Substring(6, 1);
mang[timvitri1(cat1), timvitri3(cat2)] = cat2;
mddon[md_don] = cat2;
r_hang[demluat] = timvitri1(cat1);
r_cot[demluat] = timvitri3(cat2);
}
txtdsluat.Text = txtdsluat.Text + txtluat.Text + "\r\n";
txtluat.Text = "";
txtluat.Focus();
}
private void btnchon_Click(object sender, EventArgs e)
{
demgt++;
gt[demgt] = txtchonmd.Text;
txtgt.Text=txtgt.Text+ txtchonmd.Text+"\r\n";
txtchonmd.Text = "";
txtchonmd.Focus();
}
private void btnreset_Click(object sender, EventArgs e)
{
reset();
}
private void btnthuchien_Click(object sender, EventArgs e)
{
kl = txtkl.Text;
if (kl =="")
MessageBox.Show("Bạn phải nhập mệnh đề kết luận");
else
cai = true;
// Gán TGIAN = GT;
for (int i = 1; i <= demgt; i++)
tgian[i] = gt[i];
// Tìm luật vào tập SAT
// Trường hợp mđ đơn:
for (int i = 1; i <= md_don; i++)
for (int j = 1; j <= md_don; j++)
{
if (mang[timvitri1(tgian[i]), timvitri3(mddon[j])] != null)
{
demsat++;
SAT_hang[demsat] = timvitri1(tgian[i]);
SAT_cot[demsat] = timvitri3(mddon[j]);
}
}
// Trường hợp mđ phức:
for (int i=1;i<=demgt;i++)
for (int j = 1; j <=demgt; j++)
{
if (mang[timvitri1(tgian[i]), timvitri2(tgian[j])] != null)
{
demsat++;
SAT_hang[demsat] = timvitri1(tgian[i]);
SAT_cot[demsat] = timvitri2(tgian[j]);
}
}
// Kiểm tra xem kết luận có trong tập trung gian hay không.
for (int i = 0; i <= demgt; i++)
{
if (kl == tgian[i])
ketluan = true;
}
while(ketluan == false && demsat != 0 && cai==true)
{
// Lấy luât từ SAT, cộng thêm mệnh đề vào TGIAN
demgt++;
tgian[demgt] = mang[SAT_hang[1], SAT_cot[1]];
// Loại bỏ luật đã sd ra khỏi tập luật:
for(int i=1; i<=demsat;i++)
for (int j=1; j<=demluat ;j++)
if(r_cot[j]==SAT_cot[i] && r_hang[j]==SAT_hang[i])
n=j;
for (int m = n; m <= demluat - 1; m++)
{
r_cot[m] = r_cot[m + 1];
r_hang[m] = r_hang[m + 1];
}
demluat--;
// Loại bỏ luật vừa dùng ra khỏi tập SAT:
for (int i = 1; i <= demsat-1; i++)
{
SAT_hang[i] = SAT_hang[i + 1];
SAT_cot[i] = SAT_cot[i + 1];
}
demsat--;
// Thêm tập SAT từ mệnh đề vừa thêm vào TGIAN:
// Trường hợp mệnh đề đơn:
for (int i = 11; i <= 20; i++)
{
if (mang[timvitri1(tgian[demgt]),i] != null)
{
demsat++;
SAT_hang[demsat] = timvitri1(tgian[demgt]);
SAT_cot[demsat] = i;
}
}
// Trường hợp mệnh đề phức:
for (int i = 1; i <= 10; i++)
{
if (mang[timvitri1(tgian[demgt]), i] != null)
{
demsat++;
SAT_hang[demsat] = timvitri1(tgian[demgt]);
SAT_cot[demsat] = i;
}
}
// Kiểm tra kết luận có nằm trong TGIAN không:
for (int i = 0; i <= demgt; i++)
{
if (kl == tgian[i])
ketluan = true;
}
}
MessageBox.Show("Luat: "+ demluat);
MessageBox.Show("Sat: "+ demsat);
if (cai==true && ketluan == true)
txtthongbao.Text = "Thành công!";
else
txtthongbao.Text = "Không thành công";
}
}
}
[/code]
Vậy g∈T nên bài toán được chứng minh (g: true).
* Nhận xét:
Quá trình suy diễn tiến là quá trình xem xét các luật, với mỗi luật ta
xét
phần điều kiện (ở vế trái) tới phần kết luận (ở vế phải) và khi mà tất
cả các điều
kiện của luật đều thoã mãn thì ta suy ra sự kiện trong phần kết luận.
Chính vì lẽ đó
mà có tên là suy diễn tiến.
Trong mỗi bước của thủ tục, người ta xét một luật trong tập luật. So
sánh
mỗi điều kiện (ở vế trái) của tập luật với các sự kiện trong cơ sở sự
kiện, nếu tất cả
các điều kiện của luật được thoã mãn thì sự kiện trong phần kết luận
được xem là
sự kiện được suy ra. Nếu sự kiện này là sự kiện mới (không có trong bộ
nhớ làm
việc) thì nó được đưa vào bộ nhớ làm việc. Quá trình trên cứ lặp lại
cho đến khi
nào không có luật nào sinh ra sự kiện mới.
Quá trình suy diễn tiến không định hướng tới giải quyết một vấn đề nào
cả,
không hướng tới tìm ra câu trả lời cho một câu hỏi nào cả. Suy diễn
tiến chỉ là quá
trình suy ra các sự kiện mới từ các sự kiện có trong bộ nhớ làm việc.
+ Suy diễn lùi (lập luận lùi - backward chaining hoặc backward
reason)
Là quá trình xuất phát từ sự kiện cần chứng minh và thay vào đó là
những
sự kiện ở vế trái của 1 luật có vế phải là sự kiện cần chứng minh. Quá
trình này
được thực hiện cho đến khi đưa về các sự kiện là tập sự kiện con của
tập sự kiện
giả thiết. (Nghĩa là: để đưa ra kết luận b, ta thử tìm tất cả các luật
có dạng: a1 ⋀ ....⋀
an ⟹ b, để có b, phải đưa ra các kết luận a1,...,an. Quá trình xác
định ai cũng tương tự như đối với b, nếu đến một lúc nào đó phát hiện
được rằng có một ai nào đó
không dẫn xuất được từ các giả thiết thì quay lui sang các luật sản
xuất khác sinh
ra b có dạng b1⋀....⋀bm ⟹ b. Ngược lại, nếu mọi ai đều dẫn xuất được
giả thiết thì quá trình dẫn xuất ra b là đúng)
* Giải thuật:
GỌi T là tập các sự kiện cần chứng minh tại thời điểm đang xét (khởi
tạo
T= G, G là tập kết luận).
S(p) ={ri∈R / right(ri) = p} ( là tập các luật trong R sao cho vế phải
chứa p)
Procedure suydienlui (g);
Begin
T:= {g};
If T⊂ F then write (‘g đã được chứng minh ‘)
Else
Begin
p:=get(T);
If S(p) = {} then write (‘g không chứng minh được ‘)
Else
For ri∈ S(p) do
Begin
T:= T \ right(ri);
T:= T + left(ri);
For l∈T \ F do suydienlui(l);
End;
End;
End;
* Ví dụ:
Cho tập sự kiện F={p, r}, và tập luật R:
r1: p ⟹ q
r2: q ⋀ r⟹ s
Chứng minh s
p r T S(p)
s
s r2 q, r r2
q r1 r, p r
--. Nhận xét
- Suy diễn tiến
Ưu điểm:
+ Làm việc tốt khi bài toán có bản chất là đi thu thập thông tin rồi
thấy điều
cần suy diễn.
+ Cho ra khối lượng lớn các thông tin từ một số thông tin ban đầu. Nó
sinh
ra nhiều thông tin mới.
+ Suy diễn tiến là tiếp cận lý tưởng đối với các loại bài toán cần
giải quyết
các nhiệm vụ như lập kế hoạch, điều hành, điều khiển và diễn dịch.
Nhược điểm:
+ Không cảm nhận được rằng chỉ cần một vài thông tin quan trọng. hệ
thống
hỏi các câu hỏi có thể hỏi mà không biết rằng chỉ một ít câu đã đi đến
kết luận
được.
+ Hệ thống có thể hỏi cả câu hỏi không liên quan. Có thể các câu trả
lời
cũng quan trọng nhưng làm người dùng lúng túng khi phải trả lời các
câu chẳng
dính đến chủ đề.
- Suy diễn lùi:
Ưu điểm:
+ Phù hợp với bài toán đưa ra giả thuyết và liệu giả thuyết đó có đúng
hay
không?
+ Tập trung vào đích đã cho. Nó tạo ra một loạt câu hỏi chỉ liên quan
đến
vấn đề đang xét, thuận tiện đối với người dùng.
+ Khi suy diễn một điều gì từ thông tin đã biết , nó chỉ tìm trên một
phần
của cơ sở tri thức thích đáng đối với bài toán đang xét.
+ Suy diễn lùi được đánh giá cao trong các bài toán như là chẩn đoán,
dự
đoán và tìm lỗi.
Nhược điểm:
+ Nhược điểm cơ bản của loại suy diễn này là nó thường tiếp theo dòng
suy
diễn thay vì đúng ra phải dừng ở đó mà sang nhánh khác.
Như vậy, dựa vào các ưu và nhược điềm của từng loại suy diễn mà ta nên
chọn kỹ thuật suy diễn nào để áp dụng vào bài toán. Trước tiên, ta xem
xét các
chuyên gia giải nó như thế nào?. Nếu cần thu thập dữ liệu rồi mới
quyết định suy
diễn cái gì thì ta chọn suy diễn tiến. còn nếu đã có giử thuyết và cần
chứng minh
cái đích này thì ta dùng suy diễn lùi.
Ví dụ: Một bác sĩ có thể hiểu hàng trăm vấn đề có thể xảy ra với một
cá
nhân, nhưng vẫn phải tìm hiểu hiện trạng của bệnh nhân, lúc đó cần suy
diễn tiến.
Nguợc lại bác sĩ hầu như thấy được bệnh (ví dụ như viêm họng) thì ông
ta dùng suy
diễn lùi.
Suy diễn lùi : là quá trình suy luận ngược xuất phát từ một số sự kiện ban đầu, ta tìm kiếm các sự kiện đã "sinh" ra sự kiện này. Một ví dụ thường gặp trong thực tế là xuất phát từ các tình trạng của máy tính, chẩn đoán xem máy tính đã bị hỏng hóc ở đâu.
Ví dụ :
Tập các sự kiện :
Tập các luật :
R1. Nếu ( (ổ cứng "hỏng") hoặc (cáp màn hình "lỏng")) thì không sử dụng được máy tính.
R2. Nếu (điện vào máy là "có") và ( (âm thanh đọc ổ cứng là "không") hoặc tình trạng đèn ổ cứng là "tắt")) thì (ổ cứng "hỏng").
R3. Nếu (điện vào máy là "có") và (tình trạng đèn màn hình là "chớp đỏ") thì (cáp màn hình "lỏng").
Để xác định được các nguyên nhân gây ra sự kiện "không sử dụng được máy tính", ta phải xây dựng một cấu trúc đồ thị gọi là đồ thị AND/OR như sau :
Như vậy là để xác định được nguyên nhân gây ra hỏng hóc là do ổ cứng hỏng hay cáp màn hình lỏng, hệ thống phải lần lượt đi vào các nhánh để kiểm tra các điều kiện như điện vào máy "có", âm thanh ổ cứng "không"…Tại một bước, nếu giá trị cần xác định không thể được suy ra từ bất kỳ một luật nào, hệ thống sẽ yêu cầu người dùng trực tiếp nhập vào. Chẳng hạn như để biết máy tính có điện không, hệ thống sẽ hiện ra màn hình câu hỏi "Bạn kiểm tra xem có điện vào máy tính không (kiểm tra đèn nguồn)? (C/K)". Để thực hiện được cơ chế suy luận lùi, người ta thường sử dụng ngăn xếp (để ghi nhận lại những nhánh chưa kiểm tra).