Chương IV: Thư viện SemWeb.dll và ứng dụng minh họa

Một phần của tài liệu Đồ án tốt nghiệp nghiên cứu description logic và ứng dụng (Trang 98)

SemWeb là thư viện về Semantic Web/RDF, được viết bằng ngôn ngữ C# dùng cho .Net hoặc Mono. Thư viện này có khả năng truy vấn dữ liệu trong kho lưu trữ thông qua khớp lược đồ và ngôn ngữ truy vấn SPARQL. API( Aplication Programing Interface ) của SemWeb thì không phức tạp và linh động.

Đặc tính cơ bản như: đọc ghi dữ liệu RDF theo cú pháp XML hoặc bộ N3, hỗ trợ kho dữ liệu, ngôn ngữ truy vấn dữ liệu SPARQL. Trong đó SPARQL (Protocol And RDF Query Language) là ngôn ngữ dùng để truy vấn dữ liệu trên RDF mà chúng ta đã thảo luận. Bản thân ngôn ngữ này được tác giả Ryan Levering viết để hỗ trợ việc truy vấn dữ liệu trong Java và được converted sang dùng cho .Net bằng cách dùng thư viện IKYM (được viết bởi Jeroen Frijters).

4.2 Các đặc điểm cơ bản của SemWeb.

API của nó thực sự đơn giản và dễ dàng triển khai. Đọc và ghi dữ liệu với định dạng RDF/XML.

Có chức năng đọc dữ liệu dưới dạng luồng, điều này có nghĩa là toàn bộ dữ liệu không cần phải nạp vào trong bộ nhớ.

Đọc và ghi dữ liệu dạng bộ Ntriples, Turle, và phần lớn là Notation N3 (tất cả các luồng vào khoảng 20.000 statemnents/sec).

SQL DB-backed là kho lưu trữ dữ liệu dùng cho MySQL, Sqlite và PostgreSQL. Tất nhiên là có khả năng lưu trữ trên bộ nhớ.

Việc lưu trữ tên cơ sở dữ liệu hỗ trợ Select mở rộng để truy vấn nhiều thứ cùng một lúc.

Để thuận tiện cho việc triển khai ứng dụng, thì trong khi lưu trữ dữ liệu bộ ba người ta đã thêm vào trường mới là meta, trường này dùng với mục đích: như nguồn gốc dữ liệu, phát biểu nhóm hoặc thể thức N3.

Thực thi việc lưu trữ dữ liệu mới hoặc tài nguyên của các phát biểu đơn giản là thực thi một giao diện hoặc mở rộng một lớp căn bản.

RDFS có thể suy diễn trên toàn bộ dữ liệu.

Truy vấn dữ liệu trong môi trường ASP.Net sử dụng SPARQL Protocol. 4.3 SemWeb.Store.

4.3.1 SemWeb Helloworld.

Trong SemWeb chúng ta có thể sử dụng file cấu trúc dạng RDF/XML hoặc Notation3. Chúng ta sẽ tạo một file mới có tên helloworld.cs có nội dụng như bên dưới. Trong dự án mới chúng ta reference tới thư viện semweb.dll.

Đầu tiên tạo một lớp đơn giản và không gian tên của RDF như sau:

using System; using SemWeb; public class Example {

const string RDF = "http://www.w3.org/1999/02/22-rdf- syntax-ns#";

public static void Main() {} }

Trong hàm Main() tạo một đối tượng mới MemoryStore nó là một bộ nhớ trong lưu trữ RDF Statements.

MemoryStore store = new MemoryStore();

Tiếp theo chúng ta tạo các thực thể như sau:

Entity computer = new Entity("http://example.org/computer"); Entity description = new

Entity("http://example.org/description"); Entity says = "http://example.org/says"; Entity wants = "http://example.org/wants";

Tạo một thực thể vô danh sử dụng lớp Bnode.

Entity desire = new BNode();

Tiếp theo chúng ta tạo ra các Statements sử dụng các thực thể này. Ở đây sử dụng cấu trúc statement, nó chứa các đối subject, predicate và object. predicate

Statement assertion = new Statement(computer, says, new Literal("Hello world!"));

Và statements phải được đặtt vào trong một store:

store.Add(new Statement(computer, says, (Literal)"Hello world!"));

store.Add(new Statement(computer, wants, desire));

store.Add(new Statement(desire, description, (Literal)"to be human")); (adsbygoogle = window.adsbygoogle || []).push({});

store.Add(new Statement(desire, RDF+"type", (Entity)"http://example.org/Desire"));

Cuối cùng, chúng ta nghi nội dung của store thành file dạng RDF/XML. Tạo một đối mới tượng RdfXmlWriter dùng để ghi nội dụng của store ra màn hình như sau:

using (RdfWriter writer = new RdfXmlWriter(Console.Out)) { writer.Write(store); } Kết quả là: <?xml version="1.0"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:exampleorg="http://example.org/"> <rdf:Description rdf:about="http://example.org/computer"> <exampleorg:says>Hello world!</exampleorg:says> <exampleorg:wants> <exampleorg:Desire> <exampleorg:description>to be human</exampleorg:description> </exampleorg:Desire> </exampleorg:wants> </rdf:Description> </rdf:RDF> 4.3.2 Đọc file RDF.

Để đọc được file RDF đầu tiên ta load file RDF/XML(hoặc một file dạng N- Triples, Turtle hoặc dạng Notation 3 có đuôi mở rộng là .n3) vào trong bộ nhớ thông qua phương thức Inport(đường dẫn của file) của lớp MemoryStore. Mặc định là file này đặt ở trong thư mục bin của Project hoặc có thể chỉ đường dẫn đến file đó:

MemoryStore store = new MemoryStore();

store.Import(new RdfXmlReader("data.rdf"));

// store.Import(new RdfXmlReader("D:\data.rdf"));

Hoặc cũng có thể loads file RDF từ web bằng phương thức LoadFromUri tuy nhiên nó chỉ định dạng được file XML hoặc N3:

store.Import(RdfReader.LoadFromUri(new Uri("http://www.mozilla.org/news.rdf")));

Thực tế chúng ta không bao giờ load toàn bộ dữ liệu của file vào bộ nhớ mà chỉ load nhưng statements nào cần. Vì vậy ta có thể dùng RdfReaders đọc file dưới dạng luồng (“stream”) điều này có nghĩa là chúng ta chỉ load những dữ liệu nào mà cần bằng phương thức Select . Do đó mà các đoạn lệnh trên tương đương với đoạn mã sau:

RdfReader webrdf = RdfReader.LoadFromUri(new Uri("http://www.mozilla.org/news.rdf"));

webrdf.Select(store);

4.3.3 Selecting Statements.

Việc sử dụng “Select” này nhận được từ cú pháp SQL, nó được dùng để truy tìm các statements giống như bộ lọc. Một template là một Statement nhưng các

Subject, PredicateObject có thể null. Ví dụ:

// lựa chọn tất cả các statements, các luồng bên trong sink store.Select(sink);

store.Select(new Statement(null, null, null), sink); store.Select(Statement.All, sink);

store.Select(new Statement(subj, null, null), sink); store.Select(new Statement(subj, pred, null), sink); store.Select(new Statement(subj, pred, obj), sink);

Sink có thể là bất kỳ StatemenSink, bao gồm cả RdfWriters, có thể dùng phương thức này để ghi dữ liệu ra file và Store giống như MemeryStore vì vậy ta có thể di chuyển Statements giữa các nguồn. Trong đó Statement(sub,pre,obj) là mẫu câu dùng để truy xuất mà phương thức Select dùng để khớp dữ liệu. Kết quả trả về lưu trong sink.

Store cung cấp hai phương thức thuận tiện để lấy được tất cả các Subjectobject

hoặc move.

foreach (Resource r in store.SelectObjects(person, foafname)) Console.WriteLine("His name is: " + r);

Hoặc

foreach (Statement statement in store.Select(new

Statement(null, rdftype, foafPerson))) { ... }

SemWeb cung cấp hai phương thức truy vấn dữ liệu RDF đơn giản. Phương thức đầu tiên là GraphMatch. Một truy vấn RSquary đơn giản chỉ là một lược đồ để khớp trở lại mô hình dữ liệu đích . Phương thức đơn thứ hai là của đối tượng Query.

Lớp này cho phép dùng các câu lệnh của SPARQL để thực hiện câu lệnh truy vấn dữ liệu trên file RDF.

Lớp GraphMatch đưa ra một một lược đồ với các biến và cấu hình đưa ra tất

cả các cách mà biến có thể gán được giá trị trả về trong mô hình dữ liệu đích do đó các Statements trong câu truy vấn sẽ được tìm trên toàn bộ mô hình dữ liệu đích.Ví dụ:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX foaf: <http://xmlns.com/foaf/0.1/> (adsbygoogle = window.adsbygoogle || []).push({});

PREFIX bill: <tag:govshare.info,2005:rdf/usbill/> SELECT ?bill ?person ?name

WHERE {

?bill rdf:type bill:SenateBill . ?bill bill:congress "108" .

?bill bill:number "1024" . ?bill bill:cosponsor ?person . ?person foaf:name ?name .

}

Câu truy vấn này có nghĩa là: Tìm tất cả các biến ?bill, ?person?name thỏa mãn điều kiện như sau:

1) ?bill là một hóa đơn Senate được chỉ rõ bởi congess 108 và có số là 1024. 2) ?bill?person như là một cosponsors.

3) ?name tên của ?person.

Lập trình trên .Net để chạy truy vấn:

Tạo một đối tượng truy vấn Query.

Tạo một đối tượng QueryResultSink sẽ nhận được kết quả trả về của câu truy vấn

Chạy phương thức Run của đối tượng Query

Tạo một GraphMatch thông qua cấu trúc của StatementSource (nó có thể là RdfReader và MemoryStores) vì vậy cũng có thể đọc từ một file hoặc store.

Sau đó load dữ liệu và chạy câu lệnh truy vấn:

MemoryStore data = new MemoryStore(); data.Import(new N3Reader(datafile));

Tiếp theo tạo một QueryResultSink .Sử dụng SparqlXmlQuerySink thực thi lớp này và nó có định dạng chuẩn XML và kết quả là định dạng theo SPARQL. Chúng ta cũng có thể sử dụng kết quả định dạng này bằng bất cứ đối tượng Query truy vấn nào không nhất thiết bằng lớp Sparql.Ví dụ:

QueryResultSink sink = new SparqlXmlQuerySink(Console.Out);

Cuối cùng là chạy bằng phương thức Run, thông qua mô hình dữ liệu đích data kết quả là sink:

query.Run(data, sink);

Tạo một SPARQL truy vấn, khởi tạo là một Sparql.

Query query = new Sparql(new StreamReader(queryfile)); 4.5 Inference.

4.5.1 Ruler.

Là tập các bộ ba nguồn (Antecedent) được miêu tả trong cơ sở dữ liệu và tập bộ ba đích cần kiểm tra xem có thể suy ra được không từ tập bộ ba nguồn hay không?. Ví du: Ta có chương trình miêu ta luật như sau:

MemoryStore store = new MemoryStore(); // Create BNodes

BNode HaNoi = new BNode("HaNoi"); BNode SaiGon = new BNode("SaiGon");

BNode Hue = new BNode("Hue"); BNode NamDinh = new BNode("NamDinh"); // Create two Entity

Entity oneway = new

Entity("http://www.agfa.com/w3c/euler/graph.axiom#oneway");

Entity path = new

Entity("http://www.agfa.com/w3c/euler/graph.axiom#path"); // Create Statements (adsbygoogle = window.adsbygoogle || []).push({});

Statement st1 =new Statement(HaNoi, oneway, NamDinh); Statement st2 =new Statement(NamDinh, oneway, Hue);

Statement st3 =new Statement(Hue, oneway, SaiGon); store.Add(st1); store.Add(st2); store.Add(st3);

Statement[] antecedent = new Statement[10] { st1, st2, st3};

// Create our question in the form of a statement to test.

Statement question = new Statement(HaNoi, path, SaiGon);

// Statement question = new Statement(HaNoi, path, Hue);???

SemWeb.Inference.Rule rule = new SemWeb.Inference.Rule(antecedent, consequent);

this.tbXML.Text = rule.ToString();

Ta có kết quả của chương trình:

{ _:Hanoi <http://www.agfa.com/w3c/euler/graph.axiom#oneway> _: NamDinh. _:NamDinh <http://www.agfa.com/w3c/euler/graph.axiom#oneway> _:Hue . _:Hue <http://www.agfa.com/w3c/euler/graph.axiom#oneway> _:SaiGon. } => _: Hanoi <http://www.agfa.com/w3c/euler/graph.axiom#path> _: SaiGon

Nó phải trả lời có tồn tại đường đi từ Hà Nội đến Sài Gòn không, dựa vào tập luận nguồn miêu tả mà nó sẽ khớp lược đồ thông qua toàn bộ các luật. Nếu mà nó suy ra được một phát biểu mà Subject là Hà Nội (hoặc Sài Gòn), Predicate là path và Object là Sai Gòn (hoặc Hà Nội) thì kết luận có đường đi.

4.5.2 RDFS.

Lớp lược đồ chứa các luật (Rules). Nó là một lớp thể hiển của Reasoner. Để sử dụng được một Reasoner, bạn thêm nó vào một Store bằng phương thức SemWeb.Store.AddReasoner(SemWeb.Inference.Reasoner) . Sau đó, các phương thức Select và Query của Store sẽ được thực hiện bằng suy luận. Lớp lược đồ này sẽ nạp một lược đồ vào và phân tích mối liên hệ giữa các thành phần rdf:subClassOf, rdf:subPropertyOf, rdf:domain, and rdf:range trong lược đồ để thiết lập một lớp và thuộc tính kế thừa.

Thông thường thì một máy suy diễn là được ngắn vào SemWeb.Store. Khi tất cả các trường trong một phát biểu là null, thì suy diễn được thực hiện như sau: phương thức Select(X rdf:type Y) sẽ được thực thi. Ví dụ: nếu X là kiểu của Y, thì kết quả trả về là các phát biểu có thực thể là được đánh dấu là một kiểu bất kỳ thuộc lớp con của Y, hoặc X là được tìm thấy trong miền (domain) hoặc phạm vi(range) của một predicate, trong đó các predicate này có domain và range là kiểu của Y. Nếu X là một lớp con hoặc thuộc tính con của Y thì khi gọi phương thưc Select(X rdf:subClassOf/rdf:subPropertyOf Y), các phát biểu nhận được nếu Y là bao kín

toàn bộ lớp con và thuộc tính của X, trong đó các lớp và thuộc tính này đã tồn tại được load vào trong bộ nhớ khi thông tin lược đồ được load.

Khi một hoặc nhiều trường trong phát biểu là null, thì việc suy diễn là được thực hiện như sau:

Khi muốn lấy thông tin của lớp con, lớp cha, thuộc tính con, thuộc tính cha ta sử dụng phương thức: Select(X rdfs:subClass/PropertyOf null) or Select(null

rdfs:subClass/PropertyOf Y), kết quả trả về là toàn bộ miền bao kín.

Khi muốn lấy toàn bộ các thực thể bằng cách sử dụng Select(null rdf:type Y) trả về toàn bộ các thực thể được đánh dấu là kiểu của Y hoặc bất kỳ thực thể thuộc lớp con của nó. Domain và range của thuộc tính không được sử dụng trong trường hợp này bởi vì phương thức này sẽ yêu cầu lựa chọn tất cả các thuộc tính có các domain và range điều này thì không cần thiết. (Điều này thì có thể có trong tương lai.) Khi kiểu của một thực thể được yêu cầu bằng cách gọi phương thức Select(X rdf:type null), kiểu này được tìm thấy đối với X trong domain hoặc range của bất kỳ predicates nào trong đó các các domain và range của predicate là nhận được trong lược đồ, domain và range là được trả về.

Đối với trường hợp tổng quá Select(X P Y), trong đó X và Y có thể là null, các phát biểu dạng U P V là được trả về và nếu có một phát biểu kiểu U Q V dưới dạng tài nguyên thì khi đó Q là một thuộc tính con của P. (Nếu X không là null thì U=X; tương tự đối với Y và V). Nhớ rằng các statements trả về đều chứa P như là predicate, thuộc tính thực tế được truy vấn và không phải là thuộc tính con những thuộc tính được tìm thấy dưới dạng dữ liệu tài nguyên.

Ví dụ: Mô tả chi tiết về ví dụ này?

public static void Main() {

//Đầu tiên ta khởi tạo dữ liệu lưu trong bộ nhớ bằng câu lệnh MemoryStore dataModel = new MemoryStore(); BNode me = new BNode("me");

BNode you = new BNode("you");

Entity rdfType = "http://www.w3.org/1999/02/22-rdf- syntax-ns#type";

Entity rdfsLabel= "http://www.w3.org/2000/01/rdf- schema#label"; Entity foafPerson = "http://xmlns.com/foaf/0.1/Person"; Entity foafAgent = "http://xmlns.com/foaf/0.1/Agent";

Entity foafName = "http://xmlns.com/foaf/0.1/name"; //Tạo các statement

dataModel.Add(new Statement(me, rdfType, foafPerson));

dataModel.Add(new Statement(you, rdfType, foafPerson));

dataModel.Add(new Statement(me, foafName, (Literal)"John Doe")); (adsbygoogle = window.adsbygoogle || []).push({});

dataModel.Add(new Statement(you, foafName, (Literal)"Sam Smith"));

//Load các lược đồ

RDFS engine = new RDFS();

engine.LoadSchema(RdfReader.LoadFromUri(new Uri("http://xmlns.com/foaf/0.1/index.rdf")));

//Ngắn lược đồ vào dữ liệu đã được tạo ở trên dataModel.AddReasoner(engine);

//Lấy toàn bộ các Entity có Object là foafAgengt Console.WriteLine("Who are Agents?");

foreach (Entity r in

dataModel.SelectSubjects(rdfType, foafAgent)) Console.WriteLine("\t" + r);

//Lấy toàn bộ các thuộc tính có predicate là rdfsLabel

Console.WriteLine("People's labels:");

foreach (Statement s in dataModel.Select(new Statement(null, rdfsLabel, null)))

Console.WriteLine("\t" + s); }

4.5.3 Euler.

Nếu như lớp RDFS thực thi việc suy luận bằng cách khớp lược đồ dựa trên các Ontology, thì lớp Euler thực thi việc suy lận dựa trên việc khớp lược đồ bằng suy luận ngược một chuỗi với việc phát hiện đường Euler dựa trên cơ sở thư viện Euler viết bởi Jos de Roo. Có nghĩa là Enler dựa trên bộ N3 để suy diễn.

Lớp Euler là một thể hiện của lớp Reasoner. Để sử dụng một Reasoner, bạn thêm đối tượng này vào lớp Store bằng phương thức AddReasoner( Reasoner). Sau đó gọi phương thức Select và Query trên Store sẽ được thực thi bằng reasoner.

Ví dụ: Mô tả chi tiết về ví dụ

//Khởi tạo dữ liệu thể hiện

MemoryStore dataModel = new MemoryStore(); BNode paris = new BNode("paris");

BNode orleans = new BNode("orleans"); BNode chartres = new BNode("chartres"); BNode amiens = new BNode("amiens"); BNode blois = new BNode("blois"); BNode bourges = new BNode("bourges"); BNode tours = new BNode("tours"); BNode lemans = new BNode("lemans"); BNode angers = new BNode("angers"); BNode nantes = new BNode("nantes"); Entity oneway = new

Entity("http://www.agfa.com/w3c/euler/graph.axiom#oneway"); Entity path = new

Entity("http://www.agfa.com/w3c/euler/graph.axiom#path"); //Tạo các phát biểu lưu trong bộ nhớ

dataModel.Add(new Statement(paris, oneway, orleans)); dataModel.Add(new Statement(paris, oneway, chartres)); dataModel.Add(new Statement(paris, oneway, amiens)); dataModel.Add(new Statement(orleans, oneway, blois)); dataModel.Add(new Statement(orleans, oneway, bourges)); dataModel.Add(new Statement(blois, oneway, tours)); dataModel.Add(new Statement(chartres, oneway, lemans)); dataModel.Add(new Statement(lemans, oneway, angers)); dataModel.Add(new Statement(lemans, oneway, tours)); dataModel.Add(new Statement(angers, oneway, nantes)); //tạo các luật suy diễn bằng cách đọc chúng từ một chuỗi N3

string rules = "@prefix : <http://www.agfa.com/w3c/euler/graph.axiom#>.\n" +

"\n" +

"{ ?a :oneway ?b } => { ?a :path ?b } .\n" +

"{ ?a :path ?b . ?b :path ?c . } => { ?a :path ?c } .\n";

//Tạo câu hỏi dạng statement để kiểm tra

Statement question = new Statement(paris, path, nantes); // Tạo một engin Euler

Euler engine = new Euler(new N3Reader(new StringReader(rules)));

// Phương thưc đầu tiên của Inference: yêu câu thông tin //có hay không một con đường từ Paris tới Nantes. Phương //thức Prove sẽ trả về một danh sách proofs, hoặc một //mảng trống nếu nó không tìm thấy một Proof. (adsbygoogle = window.adsbygoogle || []).push({});

foreach (Proof p in engine.Prove(dataModel, new Statement[] { question })) {

Console.WriteLine(p.ToString()); }

//Phương thức thứ hai:Gắn engine tới mô hình dữ liêu // và sau đó sử dụng dữ liệu. Mô hình chứa đựng phương // thức Contains để biết nếu statement là bên trong //model + reasoning.

dataModel.AddReasoner(engine);

Console.WriteLine("Euler Says the Question is: " + dataModel.Contains(question));

}

4.6 Ứng dụng minh họa:

4.6.1 Sử dụng ngôn ngữ SPARQL thực hiện truy vấn dữ liệu trong ontology foaf.

4.6.1.1 Mô tả cấu trúc của foaf.

FOAF(Friend Of A Friend) cung cấp một bộ từ vựng (ontology) cơ bản để mô tả thông tin về con người(people), nhóm(group), tổ chức (organization) và những loại khác và các thông tin liên quan. Ví dụ như để lưu thông tin của một người ta cần có những thông tin như sau: tên, tuổi, nghề nghiệp, số điện thoại, giới tính, ngày tháng năm sinh, hình ảnh, có những tài liệu nào.. v.v. thì FOAF đã cung cấp sẵn cho chúng ta một bộ từ vựng cơ bản để có thể mô tả những thông tin này.

Xét một ví dụ sử dụng FOAF  Xét ví dụ:

Đây là tài liệu cơ bản mô tả về person:

<foaf:Person> <foaf:name>Dan Brickley</foaf:name> <foaf:mbox_sha1sum>241021fb0e6289f92815fc210f9e9137262c252e</foaf: mbox_sha1sum> <foaf:homepage

Một phần của tài liệu Đồ án tốt nghiệp nghiên cứu description logic và ứng dụng (Trang 98)