美思 技術雜談:Faster Prolog in Perl with Yaswi

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

In my [previous post]({{ "/perl/prolog/2014/09/01/perl-cross-prolog-in-ai-prolog/" | prepend: site.baseurl }}), I introduced AI::Prolog, a Prolog engine written in Perl. AI::Prolog is easy to use; however, the speed may be not satisfying. Language::Prolog::Yaswi refers to Yet Another interface to SWI-Prolog; the performance of Language::Prolog::Yaswi is better than that of AI::Prolog.

Before using Yaswi, You need a SWI-Prolog complier in your system. You can get it from SWI-Prolog website.

First, you need to write a Prolog knowledge base. You may write it in the Perl script of in a seperated file. Say we have a knowledge base file train.pro.


directTrain(saarbruecken,dudweiler).
directTrain(forbach,saarbruecken).
directTrain(freyming,forbach).
directTrain(stAvold,freyming).
directTrain(fahlquemont,stAvold).
directTrain(metz,fahlquemont).
directTrain(nancy,metz).

travelFromTo(X,Y) :- directTrain(X,Y).
travelFromTo(X,Z) :-
    directTrain(X,Y),
    travelFromTo(Y,Z).
{{< / highlight >}}

Second, you have to load the knowledge base.  In this case, we also load **:query** for later use.

```perl
use Language::Prolog::Yaswi qw(:load :query);

swi_consult 'kb_train.pro';
{{< / highlight >}}

If you want to directly write your knowledge base into the Perl script, use `swi_inline`.

```perl
use Language::Prolog::Yaswi qw(:load :query);

swi_inline <<"END_OF_PROLOG";
directTrain(saarbruecken,dudweiler).
directTrain(forbach,saarbruecken).
directTrain(freyming,forbach).
directTrain(stAvold,freyming).
directTrain(fahlquemont,stAvold).
directTrain(metz,fahlquemont).
directTrain(nancy,metz).

travelFromTo(X,Y) :- directTrain(X,Y).
travelFromTo(X,Z) :-
    directTrain(X,Y),
    travelFromTo(Y,Z).
END_OF_PROLOG
{{< / highlight >}}

Then, you can query the knowledge base.  The query are wrapped by [Language::Prolog::Sugar](https://metacpan.org/pod/Language::Prolog::Sugar).  Therefore, you may follow the document there.  Finally, print out the result.

```perl
use Language::Prolog::Sugar
    vars => [qw(X Z)],
    functors => {travelFromTo => 'travelFromTo'};

swi_set_query(travelFromTo('metz', Z));
while (swi_next) {
    printf "From: metz, To: %s\n", swi_vars(Z);
}
{{< / highlight >}}

For extra credit, I write [a Perl script](http://pastebin.com/nS8nhpiS) to compare the performance difference between Language::Prolog::Yaswi and AI::Prolog.  Obviously, the former outperforms the latter much.

```console
Benchmark: timing 1000 iterations of by ai prolog, by yaswi...
by ai prolog: 34 wallclock secs (33.48 usr +  0.07 sys = 33.55 CPU) @ 29.81/s (n=1000)
  by yaswi:  0 wallclock secs ( 0.41 usr +  0.01 sys =  0.42 CPU) @ 2380.95/s (n=1000)
{{< / highlight >}}
關於作者

身為資訊領域碩士,美思認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

美思喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,美思將所學寫成文章,放在這個網站上和大家分享。