error while compling the metaprogram in prolog - prolog

I am trying to implement a meta-program in ECLiPSe Prolog, and here's the code that i have written -
:- dynamic go/1.
sol(true):- !.
sol((A,B)):- !, sol(A), sol(B).
sol(A):- clause(A, Body), sol(Body).
go(X):- X is 5.
Now when I query with sol(go(X)). , I get the error accessing a procedure defined in another module in clause(X is 5, _292) and it aborts. I tried clearing all toplevel modules and reopening ECLiPSe and then running, but still the same error.
What could be the reason?
Thanks!

Predicate p/1 is using the built-in predicate (is)/2. Note that X is 5 is a syntactically more convenient way of writing is(X,5). But your meta-interpreter is only expecting user defined predicates and the control constructs (',')/2 and true/0. If you want to handle (is)/2 you have to introduce a separate clause for it.
sol(X is Y) :- !, X is Y.
Within ISO Prolog, the goal predicate_property(Goal,built_in) can be used to test if Goal is a built-in predicate. This works in many systems like B, GNU, SICStus, SWI, XSB, YAP. So you can write:
sol(Bip) :- predicate_property(Bip, built_in), !, Bip.
In ECLiPSe this built-in is not directly available. You have to load a library. The index of the manual suggests to use library swi or quintus. For some (unclear) reason it is not part of the ECLiPSe library iso, yet it is ISO. So state
:- use_module(library(swi)).
in your file (or at the toplevel) first.
If you want a meta-interpreter to cover the full Prolog language you will have to handle all control constructs explicitly. Here they are - as defined in the standard (7.8 Control constructs).
true/0
fail/0
call/1
!/0
(',')/2
(;)/2 - disjunction
(->)/2
(;)/2 - if-then-else
catch/3
throw/1
Please be aware that only a few of them can be handled by directly calling the goal. Most of them must be handled explicitly!

Related

current_predicate in SICStus Prolog

SICStus Prolog offers both current_predicate/1 and current_predicate/2.
The manual page states:
current_predicate(?PredSpec)
Unifies PredSpec with a predicate specifications of the form Name/Arity.
current_predicate(?Name, ?Term)
Unifies Name with the name of a user-defined predicate, and Term with the most general term corresponding to that predicate.
They appear to have the same features:
both predicates work for enumerating predicates, both work with modules.
The manual page comments:
current_predicate/1 is part of the ISO Prolog standard; current_predicate/2 is not.
Should I ever use current_predicate/2 in new (= non-legacy) code?
Short answer, no. Don't use it in new code.
The benefit of current_predicate/2 was to allow querying, using a predicate call template, if the predicate is defined, unlike current_predicate/1. E.g.
...,
( current_predicate(_, foo(_, _)) ->
foo(A, B)
; ...
),
...
But you can often use instead the standard predicate_property/2 predicate, which takes a template as first argument.
P.S. The Logtalk linter will scream at you (and suggest a more standard alternative) if it finds you calling current_predicate/2 :-)

How to check for empty Arguments in Prolog?

I'm new to prolog and could use some help.
Currently, I have to make a program that concat the last character of two strings.
For example,
?- termCat(with,spaghetti,T).
T=hi
I was wondering how can I account for one of the arguments being nonexistant.
For instance I'm hoping to catch something like this...
?- termCat( , spaghetti,T).
T = i
I use this pattern for 'default arguments' (the C++ feature, kind of). Depending on your use case and Prolog system, you should adapt as required. Beware that var/1, nonvar/1, !/0 are impure builtins that could interfere in unexpected ways with the resolution process. The cut (that is, !/0) is implicit in ->/2.
termCat(X,Y,T) :-
(var(X) -> X=with;true),
(var(Y) -> Y=spaghetti;true),
etc etc.
In SWI-Prolog, you can require arguments are not free - for instance - using assertion/1 from library(debug):
:- use_module(library(debug)).
termCat(X,Y,T) :-
assertion((nonvar(X),nonvar(Y))),
etc etc.

Prolog solve Sudoku

I'm rather new at Prolog and found this example on swi-prolog.org to solve a sudoku. But I can't run it. I looked up same_length and there is only same_length/2 not same_length/1. Also all_distinct/2 and not all_distinct/0. http://www.swi-prolog.org/pldoc/man?section=clpfd-sudoku
Here are my errors:
ERROR: d:/.../prolog/sudoku.pl:5:10: Syntax error: Operator expected
% d:/.../prolog/sudoku compiled 0.00 sec, 0 clauses
Warning: The predicates below are not defined. If these are defined
Warning: at runtime using assert/1, use :- dynamic Name/Arity.
Warning:
Warning: all_distinct/1, which is referenced by
Warning: d:/.../prolog/sudoku.pl:16:8: 2-nd clause of blocks/3
And here is the code of SWI-Prolog example:
use_module(library(clpfd)).
sudoku(Rows) :-
length(Rows, 9), maplist(same_length(Rows), Rows),
append(Rows, Vs),
Vs in 1..9,
maplist(all_distinct, Rows),
transpose(Rows, Columns),
maplist(all_distinct, Columns),
Rows = [As,Bs,Cs,Ds,Es,Fs,Gs,Hs,Is],
blocks(As, Bs, Cs),
blocks(Ds, Es, Fs),
blocks(Gs, Hs, Is).
blocks([], [], []).
blocks([N1,N2,N3|Ns1], [N4,N5,N6|Ns2], [N7,N8,N9|Ns3]) :-
all_distinct([N1,N2,N3,N4,N5,N6,N7,N8,N9]),
blocks(Ns1, Ns2, Ns3).
problem(1, [[_,_,_,_,_,_,_,_,_],
[_,_,_,_,_,3,_,8,5],
[_,_,1,_,2,_,_,_,_],
[_,_,_,5,_,7,_,_,_],
[_,_,4,_,_,_,1,_,_],
[_,9,_,_,_,_,_,_,_],
[5,_,_,_,_,_,_,7,3],
[_,_,2,_,1,_,_,_,_],
[_,_,_,_,4,_,_,_,9]]).
I hope you can help me to find my mistake.
As far as I can tell, it now already works for you. However, I would still like to take the opportunity to show a few hints that may be useful for you:
Facts vs. directives
First, why doesn't the code that you post in your answer work?
The Prolog message already gives a pretty good indication:
Warning: The predicates below are not defined. ...
...
all_distinct/1, which is referenced by
This shows that you are in fact using all_distinct/1 (not all_distinct/2!) in your code somewhere, and it is not available.
Why? Because all_distinct/1 is available in library(clpfd), and you are not importing that library!
This is a pretty common error among beginners. Take a look at the following line in your program:
use_module(library(clpfd)).
Contrary to what you may believe, this does not import the library! Why? Because, as it stands, this is simply a Prolog fact of the form use_module/1, similar to the fact:
name(bob).
which, likewise, does not name bob, but simply states that name(bob) holds.
What you want instead is to use a directive to import a library.
Directives are terms of the form :-(D), which can also be written as :- D since (:-)/1 is a prefix operator.
Hence, what you meant to write is:
:- use_module(library(clpfd)).
This is a term of the form :-(T), and will be processed as a directive when the file is loaded.
Convenience definitions
Personally, I often write small Prolog programs, and most of them use CLP(FD) constraints. At some point, I got tired of adding :- use_module(library(clpfd)). to all my programs, so I added the following definition to my ~/.emacs:
(global-set-key "\C-cl" (lambda ()
(interactive)
(insert ":- use_module(library()).")
(forward-char -3)))
When you now press C-c l, the following snippet is inserted at point:
:- use_module(library()).
and point is placed within the () so that you only have to type the actual name of the library instead of the whose :- use_module...etc. directive.
So, to use library(clpfd), I would simply type:
C-c l clpfd
After a while, I got tired of that as well, and simply added :- use_module(library(clpfd)). to my ~/.swiplrc configuration file, because almost all programs I write perform integer arithmetic, and so it makes sense for me to make CLP(FD) constraints available in all Prolog programs I write. This is also already the case in systems like GNU Prolog and B-Prolog, for example.
However, I still have kept the .emacs definition, because sometimes I need to import other libraries, and I find typing the whole :- use_module... directive too cumbersome and error-prone.

What is the meaning of predicate "simple/1" in Prolog (SWI-Prolog)

I run into problem while reading a book.
I see a program use predicate "simple" ( I guess simple/1 ). I don't know what is the meaning of this predicate, I can't find it with ?-help(simple) in the console.
But when I tried with some queries in console, it worked something like:
5 ?- simple(p(x)).
false.
6 ?- simple(mia).
true.
7 ?- simple(Mia).
true.
8 ?- simple(f(Mia)).
false.
I guess it is some sort of predicate to determine if the argument was Terms(or Variables) or Complex Terms.
The swi-prolog manual has the following definition:
simple(#Term) is semidet
Term is atomic or a variable.
the definition is in the quintus prolog compatibility library; in the quintus prolog documentation the definition is:
simple(+Term)
Term is currently instantiated to either an atom, a number, a database
or a variable.
in any case, simple/1 is true if the argument is a simple term (not sure what the quintus manuals means by database; possibly a handler for an ODBC connection i guess)
translated to ISO predicates:
simple(T) :- var(T) ; atomic(T).
var/1 it's the most basic metaprogramming device, because it's impossible to predicate (i.e. execute code, binding variables) about any clause without instancing the variables, that are many times the essential part we are interested to.

Defining a rule that the user cannot query

How do I define a rule that the user cannot query?
I only want the program itself to call this rule through another rule.
Ex:
rule1():- rule2().
rule2():- 1<5.
?-rule1().
true
?-rule2().
(I don't know what the answer will be, I just want this query to fail!)
Use a Logtalk object to encapsulate your predicates. Only the predicates that you declare public can be called (from outside the object). Prolog modules don't prevent calling any predicate as using explcit qualification bypasses the list of explicitly exported predicates.
A simple example:
:- object(rules).
:- public(rule1/1).
rule1(X) :-
rule2(X).
rule2(X) :-
X < 5.
:- end_object.
After compiling and loading the object above:
?- rules::rule1(3).
true.
?- rules::rule2(3).
error(existence_error(predicate_declaration,rule2(3)),rules::rule2(3),user)
If you edit the object code and explicitly declare rule2/1 as private you would get instead the error:
?- rules::rule2(3).
error(permission_error(access,private_predicate,rule2(3)),rules::rule2(3),user)
More information and plenty of examples at http://logtalk.org/
First, some notes:
I think you mean "predicate" instead of "rule". A predicate is a name/k thing such as help/0 (and help/1 is another) and can have multiple clauses, among them facts and rules, e.g. length([], 0). (a fact) and length([H|T], L) :- ... . (a rule) are two clauses of one predicate length/2.
Do not use empty parenthesis for predicates with no arguments – in SWI-Prolog at least, this will not work at all. Just use predicate2 instead of predicate2() in all places.
If you try to call an undefined predicate, SWI-Prolog will say ERROR: toplevel: Undefined procedure: predicate2/0 (DWIM could not correct goal) and Sicstus-Prolog will say {EXISTENCE ERROR: predicate2: procedure user:predicate2/0 does not exist}
Now, to the answer. Two ideas come to my mind.
(1) This is a hack, but you could assert the predicate(s) every time you need them and retract them immediately afterwards:
predicate1 :-
assert(predicate2), predicate2, retractall(predicate2).
If you want a body and arguments for predicate2, do assert(predicate2(argument1, argument2) :- (clause1, clause2, clause3)).
(2) Another way to achieve this would be to introduce an extra argument for the predicate which you do not want to be called by the user and use it for an identification that the user cannot possibly provide, but which you can provide from your calling predicate. This might be a large constant number which looks random, or even a sentence. This even enables you to output a custom error message in case the wrong identification was provided.
Example:
predicate1 :-
predicate2("Identification: 2349860293587").
predicate2(Identification) :-
Identification = "Identification: 2349860293587",
1 < 5.
predicate2(Identification) :- Identification \= "Identification: 2349860293587",
write("Error: this procedure cannot be called by the user. Use predicate1/0 instead."),
fail.
I don't use the equivalent predicate2("Identification: 2349860293587") for the first clause of predicate2/0, because I'm not sure where the head of the clause might appear in Prolog messages and you don't want that. I use a fail in the end of the second clause just so that Prolog prints false instead of true after the error message. And finally, I have no idea how to prevent the user from looking up the source code with listing(predicate2) so that will still make it possible to simply look up the correct identification code if s/he really wants to. If it's just to keep the user from doing accidental harm, it should however suffice as a protection.
This reminds me to facility found in Java. There one can query the
curent call stack, and use this to regulate permissions of calling
a method. Translated to Prolog we find in the old DEC-10 Prolog the
following predicate:
ancestors(L)
Unifies L with a list of ancestor goals for the current clause.
The list starts with the parent goal and ends with the most recent
ancestor coming from a call in a compiled clause. The list is printed
using print and each entry is preceded by the invocation number in
parentheses followed by the depth number (as would be given in a
trace message). If the invocation does not have a number (this will
occur if Debug Mode was not switched on until further into the execution)
then this is marked by "-". Not available for compiled code.
Since the top level is usually a compiled predicate prolog/0, this could be
used to write a predicate that inspects its own call stack, and then decides
whether it wants to go into service or not.
rule2 :- ancestors(L), length(L,N), N<2, !, write('Don't call me'), fail.
rule2 :- 1<5.
In modern Prologs we don't find so often the ancestors/1 predicate anymore.
But it can be simulated along the following lines. Just throw an error, and
in case that the error is adorned with a stack trace, you get all you need:
ancestors(L) :- catch(sys_throw_error(ignore),error(ignore,L),true).
But beware stack eliminiation optimization might reduce the stack and thus
the list returned by ancestors/1.
Best Regards
P.S.: Stack elimination optimization is already explained here:
[4] Warren, D.H.D. (1983): An Abstract Prolog Instruction Set, Technical Note 309, SRI International, October, 1983
A discussion for Jekejeke Prolog is found here:
http://www.jekejeke.ch/idatab/doclet/prod/en/docs/10_pro08/13_press/03_bench/05_optimizations/03_stack.html

Resources