Both sides previous revision
Poprzednia wersja
|
|
pl:miw:piw08_prolog_java [2008/06/19 17:56] miw |
pl:miw:piw08_prolog_java [2008/06/19 18:06] miw |
====== Opis ====== | |
| |
Wojciech Leś, Michał Łosiewicz, (IS) keepsake@o2.pl, colesiu@student.agh.edu.pl | |
| |
Integracja kodu Prologu z Java | |
| |
porównać z projektami z 2006 roku http://www.ugosweb.com/jiprolog/ http://portal.acm.org/citation.cfm?id=787039 http://www.sics.se/sicstus|SICStus]] | |
| |
patrz https://ai.ia.agh.edu.pl/wiki/prolog:prolog_tools#java_and_prolog | |
| |
InterProlog http://www.declarativa.com/interprolog/, description, how to use, does it make any sense? | |
- najlepiej działa na XSB Prolog, na SWI wg dokumentacji powinno działać, jednak wszystkie przykłady są na XSB, a konwersja wymaga dość dobrej znajomości Interprologa | |
| |
http://www.swi-prolog.org/packages/jpl/java_api/index.html , do sprawdzenia | |
| |
| |
| |
| |
| |
====== Java + Prolog rozwiązania ====== | |
| |
===== Interprolog ===== | |
Stworzony dla XSB Prolog. Posiada interfejsy dla SWI i YAP. Istnieje zarówno Java, jak i Prolog API. Brakuje niestety niedeterministycznych celów w Javie, da się to zrobić tylko przez sztuczne stworzenie listy wszystkich rozwiązań w Prologu. Dokumentacja zawiera podstawowy opis metod i kilka banalnych przykładów. Bardziej rozbudowane przykłady stworzone są z użyciem XSB. Komunikacja odbywa się na zasadzie TCP/IP sockets. | |
| |
| |
===== JPL ===== | |
Stworzony dla SWI Prolog. Rozprowadzany z tą dystrybucją. Najnowsza wersja - 3.0. Współpracuje praktycznie tylko z SWI. Dokumentacja istnieje do wersji do 2.0, ale poprzez forum można bezpośrednio skontaktować się z autorami projektu. API istnieje dla Javy jak i dla Prologa. Wysokopoziomowe API jest proste w użyciu. | |
| |
| |
===== Inne ===== | |
Istnieją także interpretery Prologu (właściwie języka Prologo-podobnego) w Javie, jest to dość duża grupa projektów, ale rozwiązania te są dość ubogie i mniej efektywne. | |
| |
| |
====== Implementacja ====== | |
| |
===== JPL ===== | |
| |
* Należy stwożyć zmienną środowiskową SWI_HOME_DIR ze ścieżką do katalogu w którym jest zainstalowany SWIProlog. | |
* Do zmiennej PATH należy dodać dodać ścieżkę do katalogu SWI_HOME_DIR\bin | |
| |
| |
| |
| |
==== Wywoływanie SWIProlog z Javy ==== | |
| |
W kodzie Java'y należy: | |
* Stworzyć instancję klasy jpl.Query | |
| |
| |
new jpl.Query(String statement); gdzie statement jest poleceniem prologa, | |
| |
* Aby sprawdzić czy statement jest prawdziwy wywołujemy funkcję hasSolution() zwracającą boolean, | |
| |
| |
* Aby dostać jedną odpowiedź wywołujemy funkcję oneSolution() zwracającą Hashtable, gdzie kluczami są nazwy zmiennych zawarte w statement, | |
| |
| |
* Aby dostać wszystkie możliwe odpowiedzi wywołujemy funkcję allSolutions() zwracającą Hashtable[], | |
| |
| |
* Aby pojedynczo otrzymywać kolejne wyniki wywołujemy na zmiane dwie funkcje | |
| |
| |
hasMoreSolutions() zwracającą true jeśli istnieje jeszcze jakieś rozwiązanie | |
nextSolution() zwracającą Hashtable z wartościami zmiennych, | |
| |
* Na koniec wywołujemy funkcję close(). | |
| |
| |
| |
JPL w wersji nie wymaga bezpośredniej inicjalizacji silnika prologa, przy pierwszym stworzonym obiekcie jpl.Query dokona się to samo. Inicjalizować prologa trzeba tylko wtedy gdy chcemy, używać określonego modułu w prologu. | |
| |
| |
| |
| |
==== Wywoływanie Javy z SWIProlog ==== | |
| |
Wykorzystuje się 4 predykaty | |
* jpl_new(+Class,+Params,-Ref) | |
| |
jpl_new( 'nazwa_klasy', [parametry_funkcji_odzielone_przecinkami], Referencja) | |
Po takim wywołaniu tworzony jest obiekt klasy nazwa_klasy dostępny poprzez referencję Referencja. Jest to odpowiednik Java'owego: | |
| |
nazwa_klasy Referencja new nazwa_klasy(parametry_funkcji_odzielone_przecinkami); | |
Jeśli chcemy stworzyć obiekt napisanej przez nas klasy pliki class muszą zostać umieszczone w odpowiednim katalogu względem pliku pl (nazwa package, do którego należy nasza klasa). Niestety nie da się korzystać z klas umieszczonych w plikach jar | |
| |
* jpl_call( +Ref, +Method, +Params, -Result) | |
| |
jpl_call( Referencja, 'nazwa_funkcji', [parametry_funkcji_odzielone_przecinkami], Wynik) | |
Po takim wywołaniu na obiekcie dostępnym poprzez referencję Referencja wywoływana jest funkcja nazwa_funkcji. Jest to odpowiednik Java'owego: | |
| |
Wynik = Referencja.Nazwa_funkcji(parametry_funkcji_odzielone_przecinkami); | |
Aby wywołać funkcję statyczną wywołanie wygląda następująco: | |
| |
jpl_call( 'nazwa_klasy', 'nazwa_funkcji', [parametry_funkcji_odzielone_przecinkami], Wynik) | |
Jeśli chcemy wywołać funkcję napisanej przez nas klasy pliki java muszą zostać umieszczone w odpowiednim katalogu względem pliku pl (nazwa package, do którego należy nasza klasa). Niestety nie da się korzystać z klas umieszczonych w plikach jar | |
| |
* jpl_get( +Class_or_Object, +Field, -Datum) | |
Służy do wydobycia wartości atrybutu Field klasy lub obiektu Class_or_Object i przypisania go zmiennej datum | |
| |
* jpl_set( +Class_or_Object, +Field, +Datum) | |
Służy do przypisania atrybutowi Field klasy lub obiektu Class_or_Object wartości jaką posiada zmienna datum | |
| |
===== Interprolog ===== | |
| |
| |
==== Java API ==== | |
| |
<code java> | |
import java.io.File; | |
import com.declarativa.interprolog.SWISubprocessEngine; | |
| |
public class Car { | |
| |
public static void main(String[] args) { | |
SWISubprocessEngine engine=new SWISubprocessEngine("C:\\SWI\\pl\\bin\\plcon.exe"); | |
File f=new File("car.pl"); | |
engine.consultAbsolute(f); | |
engine.deterministicGoal("start"); | |
engine.shutdown(); | |
} | |
| |
} | |
</code> | |
| |
com.declarativa.interprolog.* - podstawowy pakiet Interprologu | |
| |
W celu rozpoczęcia pracy z Interprologiem, należy storzyć obiekt SubProcessEngine ( dla SWI - SWISubProcessEngine, odpowiednio dla YAP i XSB). W konstruktorze obiektu należy podać ścieżkę do interpretera Prologu. Adres interpretera (ścieżka) powinien być określony bezwzględnie, jednak stosując zmienne środowiskowe (PATH) i wywołanie programu z parametrem można z powodzeniem zmieniać dynamicznie interpreter, przez podanie nazwy pliku. | |
| |
<code java> | |
SWISubprocessEngine engine=new SWISubprocessEngine("C:\\SWI\\pl\\bin\\plcon.exe"); | |
</code> | |
| |
<code java> | |
boolean SWISubprocessEngine.consultAbsolute(File f) | |
</code> | |
| |
Pozwala na załadowanie logiki z dowolnego pliku prologowego do interpretera, można także wywołać: | |
| |
<code java> | |
boolean SWISubprocessEngine.deterministicGoal("[file]"); | |
</code> | |
| |
Podstawową metodą komunikacji z Proogiem w Javie jest zadawanie celów. Pozwala na to funkcja: | |
| |
<code java> | |
Object [] SWISubprocessEngine.deterministicGoal(String goal); | |
</code> | |
| |
gdzie goal jest zadanym celem (bez kropki). Zwracana jest tablica obiektów, którą należy przetworzyć, np. wywołanie goal w programie Sudoku jako "top([list])", gdzie list było listą argumentów, zwracało Stringa: "top([newlist])", gdzie newList było listą (prologową, w Javie jako String) wyznaczonych zmiennych oddzielonych przecinkiem. Wymaga to dodatkowego nakładu pracy i mocy obliczeniowej na konwersję danych i dzielenie Stringa. | |
| |
Interprolog nie posiada mechanizmu definiowania niedeterministycznych celów, można to obejść np. wykorzystując Java Term Model z bilbioteki Interprologu http://www.declarativa.com/interprolog/faq.htm#nonDeterministicGoal | |
jednak nie jest to bardzo wygodne. | |
| |
Tych kilka metod pozwala komunikować się z Prologiem z poziomu Javy w zakresie zadawania celów i korzystania z bazy wiedzy. | |
| |
| |
==== Prolog API ==== | |
| |
Interprolog posiada także predykaty Prologowe pozwalające na komunikację z Javą z poziomu Prologu. | |
| |
Najbardziej podstawowym z nich jest javaMessage występujący w trzech wersjach: | |
| |
<code> | |
javaMessage( Target,Result,Exception,MessageName,ArgList,NewArgList ) | |
</code> | |
| |
Target określa docelowy obiekt Javy do którego wysyłana jest wiadomość | |
| |
Result wynik wywołania metody obiektu | |
| |
Exception wyjątek jaki może się pojawić | |
| |
MessageName metoda obiektu Target | |
| |
ArgList lista argumentów wywołania metody w postaci obiektów kompatybilnych z Java | |
| |
NewArgList zawiera te same argumenty co ArgList, ale pobrane są one po zakończeniu działania metody, daje możliwość monitorowania zmian stanu obiektu | |
| |
| |
<code> | |
javaMessage( Target,Result,Message ) | |
</code> | |
| |
Target j.w. | |
| |
Result j.w. | |
| |
Message pozwala na wywołanie metody przez nazwaMetody(parametry), pozwala na wykorzystanie podstawowych konwersji np. integer(value), string(value). Pomija zmiany stanu obiektu. | |
| |
| |
<code> | |
javaMessage(Target,Message) | |
</code> | |
| |
Działa jak javaMessage(Target,_,Message) | |
| |
Pozostałe predykaty opisane są tu: http://www.declarativa.com/interprolog/prologAPI.htm | |
| |
System ekspertowy Car demonstruje wykorzystanie wyżej opisanej metody: | |
| |
<code> | |
javaMessage('javax.swing.JOptionPane', | |
showMessageDialog(null,string('This program diagnoses why a car won''t start.'))), | |
</code> | |
| |
Wyświetla okienko z wiadomością informacyjną. | |
| |
<code> | |
javaMessage('javax.swing.JOptionPane',A, | |
showConfirmDialog(null,string(' | |
When you first started trying to start the car, | |
\n did the starter crank the engine normally?'))), | |
</code> | |
| |
Wyświetla okno z zapytaniem Yes/No do użytkownika, zwraca 0 lub 1. | |
| |
<code> | |
ipObjectSpec(C,X,Variables,_) | |
</code> | |
| |
Pozwala wykorzystać obiekt otrzymany z metody Java w Prologu. Przykład użycia: | |
| |
<code> | |
ipObjectSpec('java.lang.Integer',B,[A],_), | |
</code> | |
| |
Pozwala odczytać zwrócony obiekt B jako integer A w Prologu. | |
| |
| |
====== Porównanie ====== | |
| |
JPL - Interprolog | |
| |
* Łatwość programowania - JPL jest zdecydowanie prostszy w obsłudze, nie wymaga inicjalizacji maszyny wnioskującej, metody Java są intuicyjne | |
* Szybkość działania - testy wykazały, że nie ma różnicy w wykorzystaniu obu systemów. Uśrednione wartości testów pokazały, że czas wykonania operacji (rozwiązanie Sudoku) jest bardzo podobny. | |
* Wygoda - Interprolog nie posiada non-deterministic goal api, stąd wszelkie multiple-solutions trzeba generować w prologu i zwracać jako listę rozwiązań, która jest obiektem typu String w Javie i trzeba ją parsować, natomiast JPL generuje kolejne rozwiązania z poziomu Java poprzez kolejne wywołania tych samych 2 funkcji | |
* Dostęp do konsoli interpretera Prologu - JPL musi mieć zdefiniowaną zmienną środowiskową (SWI_HOME_DIR), w której jest adres katalogu domowego SWI, w Interprologu w kodzie programu Java należy wywołać SWISubProcessEngine z parametrem jakim jest śćieżka dostępu do interpretera | |
* Łączność Prolog-Java - w JPL realizuje się to za pomocą 4 predykatów (tworzenie obiektów Java, wywoływanie funkcji, powiązanie obiektu Java ze zmienną w Prologu, ustalenie wartości zmiennej), w Interprologu działa to na zasadzie komunikacji synchronicznej przez Java Message | |
| |
| |
====== Przykłady programów ====== | |
| |
Programy testowane tylko w środowisku Windows | |
| |
===== Interprolog ===== | |
| |
| |
==== Sudoku ==== | |
| |
{{prolog_java_sudoku_interprolog.zip}} | |
| |
Wywołanie: java -jar Sudoku.jar [prolog compiler] | |
| |
np. java -jar Sudoku.jar plcon | |
| |
Kompilacja: | |
| |
javac -classpath interprolog.jar Sudoku.java | |
| |
jar cfm Sudoku.jar manifest *.class | |
| |
| |
| |
| |
| |
| |
| |
==== Car ==== | |
| |
{{prolog_java_car_interprolog.zip}} | |
| |
Kompilacja j.w. | |
| |
Uruchomienie j.w. | |
| |
| |
| |
| |
===== JPL ===== | |
SUDOKU | |
{{prolog_java_sudoku_jpl.zip}} | |
| |
Przykład działania wywołania prologa w javie (GUI w javie i wnioskowanie w prologu). | |
Należy ustawić zmienną środowiskową SWI_HOME_DIR, do zmiennej środowiskowej PATH należy dodać SWI_HOME_DIR/bin | |
| |
CAR.PL | |
{{prolog_java_car_jpl.zip}} | |
| |
Przykład działania wywołania javy w prologu (Okno startowe w javie wywołuje prologa, a prolog wywołuje kolejne dialogBoxy z pytaniami). | |
Należy ustawić zmienną środowiskową SWI_HOME_DIR, do zmiennej środowiskowej PATH należy dodać SWI_HOME_DIR/bin | |
| |
====== Problemy ====== | |
| |
Do poprawy, --- //[[wojnicki@agh.edu.pl|Igor Wojnicki]] 2008/06/11 13:10//: | |
| |
- https://ai.ia.agh.edu.pl/wiki/pl:miw:piw08_prolog_java#jpl cos nie tak z wersjami | |
- https://ai.ia.agh.edu.pl/wiki/pl:miw:piw08_prolog_java#inne prosze podac linki | |
- literowki | |
- cos nie tak: "Daje możliwość pozwala na załadowanie logiki..." | |
- co z porownaniem Szybkosci Dzialania, https://ai.ia.agh.edu.pl/wiki/pl:miw:piw08_prolog_java#porownanie | |
| |
| |