git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@1388 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
		
			
				
	
	
		
			353 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			353 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
|                    BEAM How-to-get-started
 | |
| 
 | |
| This document gives you an introduction on how to use the EAM withing YAP. 
 | |
| We start by explaining how to prepare YAP to use the EAM.
 | |
| Then we present some code examples that you can use to try 
 | |
| out the EAM.
 | |
| 
 | |
| 
 | |
| WARNING:
 | |
| THE BEAM WITHING YAP IS STILL IN EARLY DEVELOPMENT, 
 | |
| SO DON'T EXPECT IT TO RUN SMOOTHLY... 
 | |
| WE ARE WORKING TO IMPROVE THE INTEGRATION OF BEAM WITHIN
 | |
| YAP, BUT THIS THINGS TAKE TIME. SO PLEASE BE PATIENT...
 | |
| 
 | |
| 
 | |
| ---------------------------------------------------------------------------
 | |
| 1. Compiling Yap to support the EAM.
 | |
| ---------------------------------------------------------------------------
 | |
| If you want to use the BEAM prototype you must compile YAP using the 
 | |
| flag --enable-eam 
 | |
| 
 | |
| tar -xvzf yapfile.tar.gz           <- will extract yap to $YAPDIR
 | |
| mkdir tmp                          
 | |
| cd tmp
 | |
| ../YAPDIR/configure --enable-eam   <- prepare yap to compilation
 | |
| make                               <- compile yap
 | |
| su                                 <- enter as root
 | |
| make install                       <- install yap
 | |
| 
 | |
| You are now ready to try YAP-BEAM. Just run "yap" on the
 | |
| command line. 
 | |
| 
 | |
| 
 | |
| ---------------------------------------------------------------------------
 | |
| 2. Quick start + Examples...
 | |
| ---------------------------------------------------------------------------
 | |
| Quick example on how to run a Prolog program using the EAM.
 | |
| 
 | |
| First you must enable the EAM using the comand 
 | |
| ?- eam.
 | |
| yes
 | |
| 
 | |
| then you should load your program, and make your queries 
 | |
| using ?- eam(query).
 | |
| You can write the query normally as in normal Prolog mode, but
 | |
| in this case you will only receive the first solution (or yes or no).
 | |
| 
 | |
| 
 | |
| Small example:
 | |
| Supose that you have the file Example.pl with the Prolog code:
 | |
| f(1).
 | |
| f(2).
 | |
| f(3).
 | |
| 
 | |
| Here is an execution example:
 | |
| [user]$ ./yap
 | |
| % Restoring file /.../startup
 | |
| YAP version Yap-5.0.0
 | |
|    ?- eam.
 | |
| yes
 | |
|    ?- [t].
 | |
|  % consulting /.../t.pl...
 | |
|  % consulted /.../t.pl in module user, 1 msec 1328 bytes
 | |
| yes
 | |
|    ?- eam(f(X)).
 | |
| [ EAM execution started to solve f/1 ]
 | |
| X = 1 ? ;
 | |
| X = 2 ? ;
 | |
| X = 3 ? ;
 | |
| no
 | |
|    ?- f(X).
 | |
| [ EAM execution started to solve f/1 ]
 | |
| X = 1 ? ;
 | |
| no
 | |
|    ?-
 | |
| 
 | |
| ---------------------------------------------------------------------------
 | |
| A first example:
 | |
| 
 | |
| You can try out the next example, the well-known benchmark scanner.pl
 | |
| that behaves badly in standard Prolog systems.
 | |
| Just run the demos... (demo1, demo2, demo3 or demo4).
 | |
| Remember to enable the EAM before loading the program.
 | |
| After running the examples, try restarting YAP and 
 | |
| loading the program without the EAM enabled. Try to run
 | |
| the demo4... :)
 | |
| 
 | |
| demo1:- demo(tiny).
 | |
| demo2:- demo(small).
 | |
| demo3:- demo(data).
 | |
| demo4:- demo(snake).
 | |
| 
 | |
| demo(Data):- 
 | |
| 	scannerdata(Data,R,C,D1,D2), 
 | |
| 	write('Rows '), write(R),nl,
 | |
| 	write('Columns '), write(C),nl,
 | |
| 	write('Left diagonals '), write(D1),nl,
 | |
| 	write('Right diagonals '), write(D2),nl,nl,
 | |
| 	scanner(R,C,D1,D2,Image), !,
 | |
| 	displi(Image).
 | |
| 
 | |
| sequence(Spec):-
 | |
| 	samples(Spec,Samples),
 | |
| 	cat(Samples,Images), !,
 | |
| 	displ(Images).
 | |
| 
 | |
| samples([],Samples):- !, Samples=[].
 | |
| samples([S|Spec],Samples):- !, 
 | |
| 	scannerdata(S,R,C,D1,D2),
 | |
| 	Samples=[sample(R,C,D1,D2)|Smpls],
 | |
| 	samples(Spec,Smpls).
 | |
| 
 | |
| cat([],Images):- !, Images=[].
 | |
| cat([Sample|Samples], Images):- !, 
 | |
| 	image(Sample,Image),
 | |
| 	Images=[Image|Imgs],
 | |
| 	cat(Samples,Imgs).
 | |
| 
 | |
| image(sample(R,C,D1,D2), Image):-
 | |
| 	scanner(proc,R,C,D1,D2,I), !,
 | |
| 	Image=I.
 | |
| 
 | |
| 
 | |
| displ([]):- nl, nl.
 | |
| displ([I|Imgs]):- nl, displi(I), nl, displ(Imgs).
 | |
| 
 | |
| displi([]):- nl .
 | |
| displi([R|Rws]):- write('    '),displr(R), displi(Rws).
 | |
| 
 | |
| displr([]):- nl.
 | |
| displr([on|R]):- write('X '), displr(R).
 | |
| displr([off|R]):- write('_ '), displr(R).
 | |
| 
 | |
| 
 | |
| scannerdata(tiny, [1,1],[2,0],[1,1,0],[0,1,1]).
 | |
| 
 | |
| scannerdata(small, [1,2,1],[2,1,1],[1,1,1,0,1],[0,0,3,1,0]).
 | |
| 
 | |
| scannerdata(double, 
 | |
| 	[2,2,3,2,2,1],
 | |
| 	[1,3,3,1,3,1], 
 | |
| 	[0,1,1,2,1,2,3,1,1,0,0],
 | |
| 	[0,2,0,1,2,2,2,1,2,0,0]).
 | |
| 
 | |
| scannerdata(snake, 
 | |
| 	[4,2,6,2,4,4,3,2],
 | |
| 	[3,5,5,3,2,3,3,3],
 | |
| 	[1,2,2,1,1,2,5,2,2,3,3,2,1,0,0],
 | |
| 	[0,1,0,3,2,2,4,3,3,3,1,3,2,0,0]).
 | |
| 
 | |
| scanner(RwData,ClData,D1Data, D2Data, Rws):- 
 | |
| 	llength(RwData,R),
 | |
| 	llength(ClData,C),
 | |
| 	board(R,C,All,Rws,Cls,D1,D2), 
 | |
| 	check(RwData,Rws),
 | |
| 	check(ClData,Cls),
 | |
| 	check(D1Data,D1),
 | |
| 	check(D2Data,D2).
 | |
| 
 | |
| pixle(on).
 | |
| pixle(off).
 | |
| 
 | |
| 
 | |
| check([],[]).
 | |
| check([K|RwsD],[R|Rws]):-
 | |
| 	llength(R,L),
 | |
| 	line(K,L,R),
 | |
| 	check(RwsD,Rws).
 | |
| 
 | |
| line(0,0,[]).
 | |
| line(K,L,[on|R]):-
 | |
| 	K > 0,    
 | |
| 	K1 is K - 1,
 | |
| 	L1 is L - 1,
 | |
| 	line(K1,L1,R).
 | |
| line(K,L,[off|R]):-
 | |
| 	L > K,  
 | |
| 	L1 is L - 1,
 | |
| 	line(K,L1,R).
 | |
| 
 | |
| board(0,C,[],[],Cls,D,D):- 
 | |
| 	C > 0, 
 | |
| 	C1 is C - 1,
 | |
| 	seed(C,Cls),
 | |
| 	seed(C1,D).
 | |
| board(R,C,All,[Row|Rws],Cols,Rdiag,Ldiag):- 
 | |
| 	R > 0,
 | |
| 	R1 is R - 1,
 | |
| 	row(C, Row),
 | |
| 	all2(Row,Al,All),
 | |
| 	column(Row,Cls,Cols),
 | |
| 	diagonal(Row,Rdg,Rdiag),
 | |
| 	rev(Row,[],Rev),
 | |
| 	diagonal(Rev,Ldg,Ldiag),
 | |
| 	board(R1,C,Al,Rws,Cls,Rdg,Ldg).
 | |
| 
 | |
| seed(0,[]).
 | |
| seed(C,[[]|S1]):- C > 0, C1 is C -1 , seed(C1,S1).
 | |
| 
 | |
| all2([],Al,Al).
 | |
| all2([H|Row],Al,[H|All]):- all2(Row,Al,All).
 | |
| 
 | |
| row(0,[]).
 | |
| row(C,[_|R]):- C > 0, C1 is C -1, row(C1,R).
 | |
| 
 | |
| column([],X,X).
 | |
| column([H|R],[Cl|Cls],[[H|Cl]|Columns]):-  column(R,Cls,Columns).
 | |
| 
 | |
| diagonal([H|Row],Dg, [[H]|Diag]):- column(Row,Dg,Diag).
 | |
| 
 | |
| rev([],Y,Y).
 | |
| rev([H|T],Y,Z):- rev(T,[H|Y],Z).
 | |
| 
 | |
| llength([],0).
 | |
| llength([A|R],N):- llength(R,M), N is M+1.
 | |
| 
 | |
| 
 | |
| 
 | |
| ---------------------------------------------------------------------------
 | |
| Another example:
 | |
| 
 | |
| The famours queens...
 | |
| Try to evaluate in normal Prolog que query:
 | |
| ?- queens([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],X).
 | |
| Now quit YAP and enable eam before loading the queens program
 | |
| Here is the code for you to try it:
 | |
| 
 | |
| demo1:- queens([1,2,3,4,5,6,7,8,9],L), write(L), nl, fail.
 | |
| demo2:- queens([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],L), write(L), nl.
 | |
| 
 | |
| queens(L,C):-	
 | |
| 	perm(L,P),
 | |
| 	pair(L,P,C),
 | |
| 	safe([],C).
 | |
| 
 | |
| perm([],[]).
 | |
| perm(Xs,[Z|Zs]):-
 | |
| 	select(Z,Xs,Ys), 
 | |
| 	perm(Ys,Zs).
 | |
| 
 | |
| select(X,[X|Xs],Xs).    
 | |
| select(X,[Y|Ys],[Y|Zs]):-
 | |
| 	select(X,Ys,Zs).
 | |
| 
 | |
| pair([],[],[]).
 | |
| pair([X|Y],[U|V],[p(X,U)|W]):-
 | |
| 	pair(Y,V,W).
 | |
| 
 | |
| safe(X,[]).
 | |
| safe(X,[Q|R]):-
 | |
| 	test(X,Q),
 | |
| 	safe([Q|X],R).
 | |
| 
 | |
| test([],X).
 | |
| test([p(C1,R1)|S],p(C2,R2)):-
 | |
| 	test(S,p(C2,R2)),
 | |
| 	nd(p(C1,R1),p(C2,R2)).
 | |
| 
 | |
| nd(p(C1,R1),p(C2,R2)):-
 | |
| 	wait_while_var([C1,C2,R1,R2]),
 | |
| 	C is C1-C2, 
 | |
| 	R is R1-R2, 
 | |
| 	C=\=R,
 | |
| 	NR is R2-R1, 
 | |
| 	C=\=NR.
 | |
| 
 | |
| Note that on the nd predicate, we have used wait_while_var
 | |
| to force the EAM to wait while C1, C2, R1, R2 are not bound,
 | |
| because the operations in this predicate can't be done with 
 | |
| those variables unbound.
 | |
| 
 | |
| ---------------------------------------------------------------------------
 | |
| 3. Some notes...
 | |
| ---------------------------------------------------------------------------
 | |
| 
 | |
| - BEAM create the indexing code (try, retry and trust) only
 | |
| considering the first argument and only when the predicates are first called.
 | |
| So the first time you run a query there can be a slowdown, because the
 | |
| EAM is indexing the code.
 | |
| 
 | |
| ---------------------------------------------------------------------------
 | |
| - A lot of builtins/code are not yet supported...
 | |
| For example var(X), not , ; (or), ... 
 | |
| You will have a internal compiler error for these cases. 
 | |
| and the clause that uses the builtin/code not supported  will always fail.
 | |
| Example: consider the code:
 | |
|   tst(X):- var(X), X=1.
 | |
|   tst(2).
 | |
| 
 | |
| You will receive a warning that there is unsupported code.
 | |
| Although you can still use the tst predicate, the first alternative
 | |
| will always fail...
 | |
| 
 | |
|   ?- tst(X).
 | |
| [ EAM execution started to solve tst/1 ]
 | |
| X = 2 ? ;
 | |
| no
 | |
| 
 | |
| 
 | |
| ---------------------------------------------------------------------------
 | |
| - The EAM prefers deterministic instead of non-deterministic.
 | |
| and thus can change the order of goals of your code to delay
 | |
| non-deterministic bindings.
 | |
| 
 | |
| So, you must be careful when using builtins that have side-effects,
 | |
| or that may expect variables to be bound.
 | |
| 
 | |
| For example, supose that you have  the following Prolog code:
 | |
| f(1). 
 | |
| f(2).
 | |
| 
 | |
| tst(Y):- f(X), Y is X+1.
 | |
| 
 | |
| Normal prolog would be fine, but the EAM can not execute this
 | |
| code correctly because since f(X) is non-deterministic, 
 | |
| Y is X+1 is executed before X being bound. The result would be:
 | |
| 
 | |
| ?- tst(X).
 | |
| [ EAM execution started to solve tst/1 ]
 | |
| % INSTANTIATION ERROR- in arithmetic at user:tst/1 (clause 1): expected bound value
 | |
| 
 | |
| 
 | |
| The solution for this case is to force the EAM to wait for X to be bound.
 | |
| 
 | |
| So the code correct code would be:
 | |
| tst(Y):- f(X), skip_while_var(X), Y is X+1.
 | |
| 
 | |
| That means that the code Y is X+1 should be skipped 
 | |
| while X is var. Note that in this case there is no more
 | |
| after Y is X+1. If there were, execution would continue
 | |
| on that code. 
 | |
| 
 | |
| Another alternative is to use:
 | |
| tst(Y):- f(X), wait_while_var(X), Y is X+1.
 | |
| 
 | |
| that means what execution can not proceed while X is not bound.
 | |
| 
 | |
| 
 | |
| ---------------------------------------------------------------------------
 | |
| 
 | |
| - To support the EAM within the YAP the WAM compilation was 
 | |
| specially the classification of permanent variables.
 | |
| This code was adapted from the initial BEAM implementation and is not
 | |
| yet completed. 
 | |
| I've have already discover some code examples where the variables
 | |
| should are not being classified as permanent, and as result the BEAM
 | |
| returns false solutions. We are also working on this problem...
 | |
| 
 | |
| ---------------------------------------------------------------------------
 | |
| Expect more info soon...
 | |
| ...
 | |
| 
 |