For Programmers: Free Programming Magazines  


Home > Archive > Prolog > December 2004 > prolog question









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author prolog question
shoko2004

2004-12-11, 3:58 pm

i need to write the following program:
%count_type(Term,Type,Number)
i have written the program but it get stuck in T=..L
when i run the following predicate
count_type(f(g(1,A),A,[1,B,h(C)]),variab
le,Number).
what is the problem with my program.

count_type(T,Y,N):-
Y==numeric,
numeric(T),!,
retract(counter(Y)),
X is Y+1,
asserta(counter(X)).

count_type(T,Y,N):-
Y==atom,
(atomic(T)),!,
retract(counter(Y)),
X is Y+1,
asserta(counter(X)).


count_type(T,Y,N):-
Y==variable,
var(T),!,
retract(counter(Y)),
X is Y+1,
asserta(counter(X)).


count_type([X|Xs],T,N):- !,
count_type(X,T,N),
count_type(Xs,T,N).

count_type(T,Y,N):-
T=..L,
count_type(L,Y,N).

tmp123

2004-12-11, 3:58 pm

shoko2004 wrote:
> i need to write the following program:
> %count_type(Term,Type,Number)
> i have written the program but it get stuck in T=..L
> when i run the following predicate
> count_type(f(g(1,A),A,[1,B,h(C)]),variab
le,Number).
> what is the problem with my program.
>
> count_type(T,Y,N):-
> Y==numeric,
> numeric(T),!,
> retract(counter(Y)),
> X is Y+1,
> asserta(counter(X)).
>
> count_type(T,Y,N):-
> Y==atom,
> (atomic(T)),!,
> retract(counter(Y)),
> X is Y+1,
> asserta(counter(X)).
>
>
> count_type(T,Y,N):-
> Y==variable,
> var(T),!,
> retract(counter(Y)),
> X is Y+1,
> asserta(counter(X)).
>
>
> count_type([X|Xs],T,N):- !,
> count_type(X,T,N),
> count_type(Xs,T,N).
>
> count_type(T,Y,N):-
> T=..L,
> count_type(L,Y,N).



Hi,
Nice program, a good example of cut usage.
The major problem I see is that clause T=..L is very generic. That is,
near that anything will match it. By example:

a=..L => L=[a]
[]=..L => L=[[]]

I do not known your objectives, but probably T=..[F|L] helps a few.

In addition, some very small comments, probably just editorial
subjects:

retract(counter(Y????)), Y is not a number.
what is N in your rules?
addition of ! after T=..L ?
something for the empty list: count_type([],.... ?
nicer count_type(T,numeric,N) :- .... than count_type(T,Y,N) :-
Y==numeric, .... ?

Hope useful,
Kind regards.

Bart Demoen

2004-12-13, 4:07 pm

tmp123 wrote:
> shoko2004 wrote:
>
>
>
>
> Hi,
> Nice program, a good example of cut usage.
> The major problem I see is that clause T=..L is very generic. That is,
> near that anything will match it. By example:
>
> a=..L => L=[a]
> []=..L => L=[[]]
>
> I do not known your objectives, but probably T=..[F|L] helps a few.
>
> In addition, some very small comments, probably just editorial
> subjects:
>
> retract(counter(Y????)), Y is not a number.
> what is N in your rules?
> addition of ! after T=..L ?
> something for the empty list: count_type([],.... ?
> nicer count_type(T,numeric,N) :- .... than count_type(T,Y,N) :-
> Y==numeric, .... ?
>
> Hope useful,
> Kind regards.
>



Both the original poster and the replying poster have a problem - but
of a different kind. I will address both. First the OP.

Guessing ... the OP wants to count the number of nodes in a Prolog
term "tree", but only the nodes of a particular "type" (variable,
numeric or otherwise atomic) - as a side remark: when asking for help,
please tell us what your program is supposed to do, or which problem
you are trying to solve, because from a piece of code you yourself
describe as "it get stuck" it is impossible to deduce that.

Allow me to first give a general advice regarding the use of Prolog,
actually three advices:

1) don't use dynamic predicates
2) don't use dynamic predicates
3) don't use dynamic predicates

Here are the 3 most important reasons:

if you use dynamic predicates

1) you make more mistakes
2) you abuse them eventually
3) your programs are worse

I do not know how to help you further, except by following my hunch on
what you are trying to achieve and point out the similarity between

if I am counting numbers and the term contained already 13
numbers, and what I see now is a number, then the term
contains 14 numbers up to now

and
count(Term,What,AlReady,UpToNow) :-
What == number,
number(Term),
!,
UpToNow is AlReady + 1.

There are ways to write this (in the context of the whole program)
without a cut (!), but that's for the next lesson if you care.
BTW, number/1 is an ISO Prolog builtin - numeric/1 is not.

Now the reply the OP got from tmp123 - as a side remark: beginner's
questions are ok; they remind us how we also struggled with basic
stuff, and they allow us to show the right path to LP.

But replies as from tmp123 ... please no more !
My advice to tmp123: ask advice, do not offer it.


tmp123 writes:

> Nice program, a good example of cut usage.


How can one judge the niceness of a program without knowing what it is
supposed to solve ?

"a good example of cut usage" please, give us a break ...

> The major problem I see is that clause T=..L is very generic. That is,
> near that anything will match it. By example:
>
> a=..L => L=[a]
> []=..L => L=[[]]
>
> I do not known your objectives, but probably T=..[F|L] helps a few.


The only part that makes sense in these sentences is

I do not known your objectives

all the rest is gibberish, dangerous noise, because it gives the
impression of knowing the subject matter - believe me, tmp123 doesn't.

> In addition, some very small comments, probably just editorial
> subjects:


and what follows is indeed a comment focussing on "editorial" issues,
not related to understanding; it is commenting on form, not
contents. We can only hope that tmp123 meant it as a sick joke ...

In any case, I beg the OP: ignore the response from tmp123, except for
the part
> Kind regards.

The OP can get better help/response/advice from comp.lang.prolog than
from tmp123 (but make more clear what you want to do).

Cheers

Bart Demoen

ps. yes, I am back :-)
tmp123

2004-12-14, 9:07 am

Bart Demoen wrote:

> ps. yes, I am back :-)


Hi Bart,

Nice to read you again.

Your answer is, in my opinion, a few too much.

I think google is not a good place for long non-technical discussions,
so this is my last post to this or any other reply you make to this
subject. I will open a new thread in this post continuing with the
techinical subject. (assumption: if the original author still
interested, then it is not a homework: I can be more exact on my
comments). I think your technical opinion will be an important
contribution. One example, about how to skip cut and its variants.

Torkel Franzen

2004-12-14, 9:07 am

"tmp123" <tmp123@menta.net> writes:

> I think google is not a good place for long non-technical
> discussions,


I'm sure the people at Google have long non-technical discussions,
but we can't participate. News is however an excellent place for
long non-technical discussions between people from different parts
of the world.
tmp123

2004-12-14, 9:07 am

One example of the application of the previous comments to the rule for
"numbers". It is assumed this rule means "if T is a number, and we are
counting numbers, then number of numbers, N, is 1". With this
definition of N, it is not necessary to use retract/assert.

count_type(T,Y,1):-
Y==numeric,
numeric(T), !.

"numeric" can be changed by standard "number".

Now, the other case for numbers: "if T is a number, but we are looking
for something else, then N is 0". In this way, it is sure that no
numbers will progress to next rules. Using parameter matching instead
of == we will have the following rules:

count_type(T,numeric,1) :- number(T), !.
count_type(T,_Y,0) :- number(T), !.

Same for atoms and variables.

Going for a few more complex rule: the list.
First one "the number of anything in a empty list is 0".
count_type([],_Y,0) :- !.

Next one, the number of something in a list is the number of something
in the head more its number in the rest:
count_type([H|Q],Y,Z) :- !,
count_type(H,Y,Z1),
count_type(Q,Y,Z2),
Z is Z1+Z2.

Finally, the case of terms. At this point, atom, numbers, list, ...
have already analized, so I can suposse only rest terms with functor
and arity >=0. The rules is: the number of anything in a term is the
number of anything in the functor (?) plus the number in the
"parameters".

count_type(T,Y,Z) :-
T=..[F|Q], !,
count_type(F,Y,Z1),
count_type(Q,Y,Z2),
Z is Z1+Z2.

Finally, a completion, for not covered cases:
count_type(_,_,0).

Hope nothing forgot. Time for TECHNICAL comments and improvements (I'm
sure experts can improve it a lot). Some posibilities:
- Make rules tail recursive using 4 parameters.
- Skip cut and -> and similars.
- ...

Matthew Huntbach

2004-12-14, 9:07 am



On Sat, 11 Dec 2004, shoko2004 wrote:

> i need to write the following program:
> %count_type(Term,Type,Number)
> i have written the program but it get stuck in T=..L
> when i run the following predicate
> count_type(f(g(1,A),A,[1,B,h(C)]),variab
le,Number).
> what is the problem with my program.
>
> count_type(T,Y,N):-
> Y==numeric,
> numeric(T),!,
> retract(counter(Y)),
> X is Y+1,
> asserta(counter(X)).
>
> count_type(T,Y,N):-
> Y==atom,
> (atomic(T)),!,
> retract(counter(Y)),
> X is Y+1,
> asserta(counter(X)).
>
>
> count_type(T,Y,N):-
> Y==variable,
> var(T),!,
> retract(counter(Y)),
> X is Y+1,
> asserta(counter(X)).
>
>
> count_type([X|Xs],T,N):- !,
> count_type(X,T,N),
> count_type(Xs,T,N).
>
> count_type(T,Y,N):-
> T=..L,
> count_type(L,Y,N).
>

In the first three clauses you seem to be trying to use the variable
Y for two different things, one as a string to indicate the type
you're counting, the other as an integer to hold a count. But the
variable N doesn't get used at all.

As Bart suggests, a good rule is don't use dynamic predicates.
It's often the case that the use of such predicates indicates
a failure to think declaratively. In this case you are using one
just to keep a rewriteable count, but why not just:

count_type([X|Xs],T,N):- !,
count_type(X,T,N1),
count_type(Xs,T,N2),
N is N1+N2.

?

Even when programming in an imperative language, this would be the obvious
way to do it leading to cleaner code, rather than having a global variable
which is updated.

The time when a dynamic predicate to give an updateable count *is*
required in Prolog is when you are keeping a count which is updated over
backtracking. Prolog novices often waste many hours because no-one told
them you can't maintain information over backtracking except through
the use of assert.

Matthew Huntbach
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com