I'm trying to make a modified version of the expert system example within swi-prolog.org. I'm trying to modify it to be able to do:
good_pet(X) :- bird(X), small(X).
good_pet(X) :- cuddly(X), small(X).
good_pet(X) :- cuddly(X), yellow(X).
Without the program reasking if small() or cuddly is true.
I tried doing:
:- dynamic ([small/1, cuddly/1 ]).
good_pet(X) :- bird(X), assertz(small(X)).
good_pet(X) :- bird(X), small(X).
good_pet(X) :- assertz(cuddly(X)), assertz(small(X)).
good_pet(X) :- cuddly(X), small(X).
good_pet(X) :- cuddly(X), yellow(X).
As expained here.
But that ends up giving this error:
No permission to access private_procedure `assertz/1'
In:
[4] clause(assertz(cuddly(tweety)),_1306)
[3] prove(assertz(cuddly(tweety))) at line 11
[2] prove((assertz(...),assertz(...))) at line 8
[1] prove(good_pet(tweety)) at line 12
Is there a solution to this error or any another way to save the result of the asked questions?
The meta-interpreter that you are trying to use does not take into account clauses that call built-in predicates such as assertz/1. Try:
prove(true) :- !.
prove((B, Bs)) :- !,
prove(B),
prove(Bs).
prove(H) :-
predicate_property(H, built_in),
!,
call(H).
prove(H) :-
clause(H, B),
prove(B).
prove(H) :-
askable(H),
writeln(H),
read(Answer),
Answer == yes.
Related
Here is my Prolog program:
:- set_prolog_flag(verbose, silent).
:- initialization(main).
:- use_module(library(tabling)).
:- table reachable/1.
reachable(X) :- start(X).
reachable(X) :- reachable(Y), link(Y, X).
start(london).
% link(london, paris).
% link(paris, london).
% link(london, frankfurt).
% link(paris, frankfurt).
% link(frankfurt, paris).
main :-
forall(reachable(X), writeln(X)),
halt.
main :-
halt(1).
Running it gives this error:
swipl links.pl
Initialization goal raised exception:
ERROR: 'reachable tabled'/1: Undefined procedure: link/2
However this works:
:- set_prolog_flag(verbose, silent).
:- initialization(main).
:- use_module(library(tabling)).
:- table reachable/1.
reachable(X) :- start(X).
reachable(X) :- reachable(Y), link(Y, X).
start(london).
link(tokyo, hongkong).
main :-
forall(reachable(X), writeln(X)),
halt.
main :-
halt(1).
swipl links.pl
london
How can I make my program work with and without and link facts?
swipl --version
SWI-Prolog version 7.6.4 for amd64
If you intend to dynamically add the facts to the database later (for example via assertz/2 or asserta/2) you should use the directive dynamic/1:
:-dynamic link/2.
This prevents bugs in your program due to typos.
How to use the 'Univ' ( =../2 ) prolog predicate with a Logtalk object method as parameter ?
Consider this code :
baz(foo(X)) :-
write(predicate), write(X), nl.
run :-
Term =.. [baz, foo(testfoo)],
write(Term), nl, Term,nl,
TermLgt =.. [bar::baz, foo(testfoo2)],
write(TermLgt), nl, Term,nl.
:- object(bar).
:- public(baz/1).
baz(foo(X)) :-
write(method), write(X), nl.
:- end_object.
:- object(main).
:- public(run/0).
run :-
Term =.. [baz, foo(testfoo)],
write(Term), nl, Term,nl,
TermLgt =.. [bar::baz, foo(testfoo2)],
write(TermLgt), nl, Term,nl.
:- end_object.
I'll obtain :
?- {myfile}.
% (0 warnings)
true.
?- run.
baz(foo(testfoo))
predicatetestfoo
ERROR: =../2: Type error: `atom' expected, found `bar::baz' (a compound)
?- main::run.
baz(foo(testfoo))
ERROR: Undefined procedure: baz/1
ERROR: However, there are definitions for:
ERROR: baz/1
What workaround to use for a good interpretation / compilation ? It seems issue is the same with swi-prolog building predicate like predsort/3 (predsort/3 doc).
The standard =../2 predicate expects, when constructing a term from a list, that the first list argument be an atom but bar::baz is a compound term with functor ::/2 (which is both defined as a predicate - for top-level queries - and as an operator when Logtalk is loaded). The solution is to write instead:
baz(foo(X)) :-
write(predicate), write(X), nl.
run :-
Term =.. [baz, foo(testfoo)],
write(Term), nl, call(Term), nl,
TermLgt =.. [::, bar, Term],
write(TermLgt), nl, call(Term), nl.
:- object(bar).
:- public(baz/1).
baz(foo(X)) :-
write(method), write(X), nl.
:- end_object.
:- object(main).
:- public(run/0).
run :-
Term =.. [baz, foo(testfoo)],
write(Term), nl, Term,nl,
TermLgt =.. [::, bar, Term],
write(TermLgt), nl, Term,nl.
:- end_object.
With this changes, you get:
?- {univ}.
% [ /Users/pmoura/Desktop/univ.lgt loaded ]
% (0 warnings)
true.
?- run.
baz(foo(testfoo))
predicatetestfoo
bar::baz(foo(testfoo))
predicatetestfoo
true.
I want to create a list from facts like:
table(mickel).
table(harris).
table(wolfgang).
table(yanis).
table(antti).
table(peter).
table(jeroen).
table(johan).
table(luis).
table(eric).
But i don't want to use built-in rules or predicates,
unless i define them by myself.
The result almost is like that:
?- seats(Seats).
Seats = [yanis,antti,peter,jeroen,johan,luis,eric,michel,
harris,wolfgang]
I don't know what to do,please help.
You must create your own findall predicate, this post may help:
seats(L) :- find([], L), !.
find(Acc, Loa) :- table(Y), uList(Y, Acc, AccNew), find(AccNew, Loa).
find(Acc, Acc).
uList(X, [], [X]) :- !.
uList(H, [H|_], _) :- !, fail.
uList(X, [H|T], [H|Rtn]) :- uList(X, T, Rtn).
Consult:
?- seats(L).
L = [mickel, harris, wolfgang, yanis, antti, peter, jeroen, johan, luis|...].
I'm attempting to write a Prolog meta-interpreter to choose the order of goal execution, for example executing first all goals with the minimum number of parameters.
I started from the vanilla meta-interpreter:
solve2(true).
solve2(A) :- builtin(A), !, A.
solve2((A,B)) :- solve2(A), solve2(B).
solve2(A) :- clause(A,B), solve2(B).
Then i went to something like
solve2(true).
solve2(A) :- builtin(A), !, A.
solve2((A,B)) :- count(A,Args), count(B,Args2), Args<Args2, solve2(A), solve2(B).
solve2((A,B)) :- count(A,Args), count(B,Args2), Args>Args2, solve2(B), solve2(A).
solve2(A) :- clause(A,B), solve2(B).
But if the 4th line is executed then the whole block B is executed before A which is wrong.
Ex. A=a(x,y), B=(b(x,y,z), c(x)) I'd like to execute c, then a, then b. - while in this method i'd get c, b and then a.
I'm thinking about transforming the goals in a list but i'm not too sure.
Any ideas?
Here is an (untested) vanilla meta interpreter, with conjunction order changed. I would be glad if you could try with your data.
solve2(true).
solve2(A) :- builtin(A), !, A.
solve2((A,B)) :- ordering(A,B, C,D), ! /* needed */, solve2(C), solve2(D).
solve2(A) :- clause(A,B), solve2(B).
ordering(A,B, C,D) :-
minargs(A, NA),
minargs(B, NB),
( NA =< NB -> C/D=A/B ; C/D=B/A ).
minargs((A,B), N) :-
minargs(A, NA),
minargs(B, NB),
!, ( NA =< NB -> N=NA ; N=NB ).
minargs(T, N) :-
functor(T, _, N).
edit I tested with this setting:
builtin(writeln(_)).
a(1):-writeln(1).
b(1,2):-writeln(2).
c(1,2,3):-writeln(3).
test :-
solve2((c(A,B,_),a(A),b(A,B))).
and got the expected output:
?- test.
1
2
3
true .
edit I had to resort to a list representation, but then it make sense to preprocess the clauses and get the right order before, then stick to plain vanilla interpreter:
test :-
sortjoin((b(A,B),a(A),c(A,B,_)), X),
solve2(X).
sortjoin(J, R) :-
findall(C-P, (pred(J, P), functor(P,_,C)), L),
sort(L, T),
pairs_values(T, V),
join(V, R).
join([C], C).
join([H|T], (H,R)) :- join(T, R).
pred((A, _), C) :-
pred(A, C).
pred((_, B), C) :-
!, pred(B, C).
pred(C, C).
where solve2((A,B)) :- ... it's the original solve2(A),solve2(B)
I have a problem with predicate which works in that way that it takes list of atoms:
nopolfont([to,jest,tekśćik,'!'],L).
and in result
L = [to,jest,tekscik,'!'].
I have problem with make_swap and swap predicates. So far I have:
k(ś,s).
k(ą,a).
% etc.
swap(X,W) :- name(X,P), k(P,Y), !, name(Y,W).
swap(X,X).
make_swap(A,W)
:- atom(A),!,
name(A,L),
swap(L,NL),
name(W,NL).
nopolfont([],[]).
nopolfont([H|T],[NH|S]) :- make_swap(H,NH), nopolfont(T,S).
Is there any elegant way to do this?
This is also quite elegant:
polish_char_replacer(X, Y) :-
k(X, Y),
!.
polish_char_replacer(X, X).
nopolfont(Atoms1, Atoms2) :-
maplist(replace(polish_char_replacer), Atoms1, Atoms2).
replace(Goal, Atom1, Atom2) :-
atom_chars(Atom1, Chars1),
maplist(Goal, Chars1, Chars2),
atom_chars(Atom2, Chars2).
Probably as elegant as it can get:
k(ś,s).
k(ą,a).
swap(X,W) :- name(P,[X]), k(P,Y), !, name(Y,[W]).
swap(X,X).
list_swap([], []).
list_swap([H|T], [W|S]) :-
swap(H, W),
list_swap(T, S).
atom_swap(A,W) :-
atom(A), !,
name(A, L),
list_swap(L,S),
name(W, S).
nopolfont([],[]).
nopolfont([H|T],[NH|S]) :-
atom_swap(H,NH),
nopolfont(T,S).
Also, obviously define this, to get the expected result, but I assume this is in the % etc
k(ć, c).