Could use some help with if/3 implementation for Amzi! Prolog 
Author Message
 Could use some help with if/3 implementation for Amzi! Prolog

Firstly please note that I'm a newcomer to Prolog, being self-taught
on and off during the last couple of months (mostly for understanding
Prolog programs, but now with a requirement to actually write Prolog!)
and so I apologise in advance for the quality of any code I might post
:-)

Over the last few weeks I've dug around the 'net, hunted through the
news, and generally searched under every e-stone I could find looking
for a Prolog implementation of SICStus if/3 predicate (or an
equivalent to SWIs '*->'/2;/1 predicate). I found one call for help
that mentioned Amzi!'s implementation of Prolog, and sample source
that implemented the blackboard predicates, however as far as I have
been able to tell, the code (at least as supplied, and with the blanks
- bb_delete - filled in) doesn't work properly.

In frustration I've been trying to write my own equivalent, and
thought (for a wonderful moment) that I'd finally managed it with:

if(If, Then, Else) :-
    retractall(if3_no_solutions),    % clean up first
    assert(if3_no_solutions),        % set the flag
    if0(If, Then, Else).             % do the work

if0(If, Then, Else) :-
    call(If),
    retractall(if3_no_solutions),    % found at least one soln.
    (call(Then) -> true;true).       % ALWAYS succeed to allow
backtracking.

if0(If, Then, Else) :-
    if3_no_solutions,                % If failed completely...
    call(Else).

However this doesn't work 100% of the time. I can't post examples of
where it fails, because the simple examples I tried work. Where it
fails is in a port of ALE that I'm trying to make to Amzi! Prolog
(it's now practically 99% working, but fails - after consuming several
100s Mb of VM - when trying to compile the HPSG sample grammar.)

I also confirmed that the problem is in this code and not other
changes I made to ALE, by replacing the if/3 implementation in the SWI
port (which simply makes use of SWI's *->/2;/1) and running that
version - same result.

So, can anyone suggest where I am going wrong and/or suggest an
alternative way to write an if/3 equivalent (and please don't suggest
that the Prolog provider should write it!)

Many thanks in advance,

John

Email: jjcullen at yahoo dot com

John Cullen
Programador - Divis?o de Sistemas e Desenvolvimento
_______________________________________________________________

Porto Editora
Rua da Restaura??o, 365 * 4099-023 * PORTO - PORTUGAL
Tel.: +351 22 6088326 * Fax: +351 22 6088331
Porto Editora, the Future of Education
http://www.*-*-*.com/



Tue, 26 Jul 2005 02:59:32 GMT  
 Could use some help with if/3 implementation for Amzi! Prolog

Quote:

> So, can anyone suggest where I am going wrong and/or suggest an
> alternative way to write an if/3 equivalent (and please don't suggest
> that the Prolog provider should write it!)

I think there are lots of ways. This version is like SICStus'
implementation of ( -> ; ) in that it will only explore the first solution
of If:

if( If, Then, _Else ) :-
        call( If ),
        !,
        call( Then ).
if( If, _Then, Else ) :-
        call( Else ).

If you remove the cut, it will act like SICStus' if/3, in that it will be
able to explore all solutions of If.

--
Matthew Purver - matt at purver dot org



Tue, 26 Jul 2005 04:06:08 GMT  
 Could use some help with if/3 implementation for Amzi! Prolog

Quote:

> if(If, Then, Else) :-
>     retractall(if3_no_solutions),    % clean up first
>     assert(if3_no_solutions),        % set the flag
>     if0(If, Then, Else).             % do the work

> if0(If, Then, Else) :-
>     call(If),
>     retractall(if3_no_solutions),    % found at least one soln.
>     (call(Then) -> true;true).       % ALWAYS succeed to allow
> backtracking.

> if0(If, Then, Else) :-
>     if3_no_solutions,                % If failed completely...
>     call(Else).

You are not doing bad at all, certainly better than the other answer you got ...
There are two ways in which your implementation goes wrong some of the time.

1) how about nested use of if/3 ? i.e. using in the If-goal another if/3 ?
the nested use will fiddle with iff3_no_solutions and this can mess up the outer use;
the remedy is to get a new identifier (might be an integer) for each call to if/3, say i1, i2, i3 ...
and assert facts of the form iff3_no_solutions(i2) and test for their existence in if0 - of course
if0 now must get the identifier as an extra argument

2) the construct (call(Then) -> true;true) prevents backtracking in the Then goal, so if your
Then goal is multidet, you lose solutions; the comment on that same line is a bit strange as well ...
replace the line by just   call(Then) in any case

These two together should make it work always.
Here is one more way which works in case the If has no side-effects:

if (If, Then, Else) :-
            copy_term(If,NewIf),
            (call(NewIf) ->
                        call(If), call(Then)
            ;
                        call(Else)
            ).

You lose efficiency (in the worst case, you double the cost of the If, and there is the
cost of copying) - be careful: I haven't tested that code :-)

Cheers

Bart Demoen



Tue, 26 Jul 2005 05:11:10 GMT  
 Could use some help with if/3 implementation for Amzi! Prolog

<snipped>

Quote:
> Here is one more way which works in case the If has no side-effects:

> if (If, Then, Else) :-
>             copy_term(If,NewIf),
>             (call(NewIf) ->
>                         call(If), call(Then)
>             ;
>                         call(Else)
>             ).

> You lose efficiency (in the worst case, you double the cost of the If, and
there is the
> cost of copying) - be careful: I haven't tested that code :-)

To save the cost of copying, and perhaps make it more readable:

if ( If, Then, Else ) :-
    ( \+ call( If ) ->
        call( Else )
    ; otherwise ->
        call( If ),
        call( Then )
    ).

--
Regards

John Fletcher



Tue, 26 Jul 2005 05:57:00 GMT  
 Could use some help with if/3 implementation for Amzi! Prolog

< about if/3 >

Bart's first solution is the one I'd try first, but what about something
like the following as an alternative to Bart's second solution:

if(If,Then,Else) :-
    findall(If,call(If),Sols),
    if_(Sols,If,Then,Else).

if_([],_,_,Else) :-
    call(Else).
if_([H|T],If,Then,_) :-
    member(If,[H|T]),  % get the bindings
    call(Then).

of course, if the if-call has side-effects then this is different from
the sicstus/swi variant. But this prevents calling the if-goal twice.

GJ

--
Gertjan van Noord Alfa-informatica, RUG,  Postbus 716, 9700 AS Groningen
vannoord at let dot rug dot nl            http://www.let.rug.nl/~vannoord



Tue, 26 Jul 2005 15:33:36 GMT  
 Could use some help with if/3 implementation for Amzi! Prolog

Quote:

>< about if/3 >

> Bart's first solution is the one I'd try first, but what about something
> like the following as an alternative to Bart's second solution:

> if(If,Then,Else) :-
>     findall(If,call(If),Sols),
>     if_(Sols,If,Then,Else).

> if_([],_,_,Else) :-
>     call(Else).
> if_([H|T],If,Then,_) :-
>     member(If,[H|T]),  % get the bindings
>     call(Then).

> of course, if the if-call has side-effects then this is different from
> the sicstus/swi variant. But this prevents calling the if-goal twice.

All of these are quite nice.  I actually never thought of a solution
along the lines of the original poster.  With some more work it should
be possible to turn this into a fully functioning one, although nesting
and exceptions always make the use of global flags cumbersome.

Big trouble is that the user needs to think about the situation and go
for Barts or Gertjan's solution.  Either of them is often acceptable,
depending on cost of the If, side-effects and number of solutions.

I think Prolog vendors should implement if/3 or *-> (which I like better
as the implementation is compiled and transparent to ! just like ->). At
the implementation level it is really easy and I have seen many cases
where it comes very handy.

        --- Jan



Tue, 26 Jul 2005 18:09:01 GMT  
 Could use some help with if/3 implementation for Amzi! Prolog

Quote:

> < about if/3 >

[...]
> of course, if the if-call has side-effects then this is different from
> the sicstus/swi variant. But this prevents calling the if-goal twice.

> GJ

Many thanks to all for the suggestions, especially pointing out the
(now obvious!) fact that there may be embedded calls to if/3 - I
haven't confirmed directly (ALE has over 5000 lines of code and I'm
fighting to understand even a tiny percentage of that :-) that this is
the case, however it does explain the some of the problems I had with
my original code.

In addition I cannot guarantee the calls to if/3 wouldn't have side
effects, and so the various suggestions given are not applicable in
this case.

After reading the comments from Bart Demoen, plus an email from
Gertjan van Noord reminding me of the existence of gensym/2
(thankyou!), I did manage to come up with the following version which
_appears_ to work as expected (read, my simple examples work, and I
can now compile the complex hpsg sample that comes with ALE!):

if(If, Then, Else) :-
    retractall(if3_no(_)),              % cleanup before we start
    gensym(sol, X),                     % generate a tracking number
so we know which if is being called
    assert(if3_no(X)),                  % checkpoint
    if0(If, Then, Else, if3_no(X)).     % do the work

if0(If, Then, Else, X) :-
    call(If),
    retractall(X),                      % if succeeded at least once,
remove the no solution checkpoint
    call(Then).                         % results.

if0(If, Then, Else, X) :-
    (X),                                % if the no solution
checkpoint exists, the if failed.
    call(Else).                         % results.

Finally, my comment in the original message regarding not asking me to
ask the Prolog provider to implement this was not due to any
reluctance on their part, rather I was looking for a quick solution to
the problem. Having now reached a working solution (at least I hope so
:-) I'm going to ask Amzi! if they wouldn't be interested in providing
an equivalent to if/3 for their prolog implementation.

Again, many thanks to all who replied!

Regards,

John



Tue, 26 Jul 2005 19:29:05 GMT  
 Could use some help with if/3 implementation for Amzi! Prolog

Quote:

> I think Prolog vendors should implement if/3

I second that.

Quote:
> or *-> (which I like better
> as the implementation is compiled and transparent to ! just like ->).

The surface syntax should not imply whether it is transparent and compiled.
It is just as easy to catch if/3 during compilation as for catching ->

Quote:
> At the implementation level it is really easy

Indeed, it is so easy that if Amzi! gives me their sources, I volunteer to give it a try for free :-)

Cheers

Bart Demoen



Tue, 26 Jul 2005 21:16:26 GMT  
 Could use some help with if/3 implementation for Amzi! Prolog

Quote:

> At the implementation level it is really easy

Well, depends on how thoroughly you want to do it. If you want
it to work correctly with side effects AND to get rid of the
choicepoint as early as possible (with all the consequences
this has for garbage collection etc), then it is not so easy
at all...

Quote:
> and I have seen many cases where it comes very handy.

That I find surprising! I have been programming in Prolog for
about 15 years and never missed it. What am I doing wrong?

--
 Joachim Schimpf              /             phone: +44 20 7594 8187

 Imperial College London    /    http://www.icparc.ic.ac.uk/eclipse



Tue, 26 Jul 2005 23:31:28 GMT  
 Could use some help with if/3 implementation for Amzi! Prolog

Quote:


> > At the implementation level it is really easy

> Well, depends on how thoroughly you want to do it. If you want
> it to work correctly with side effects AND to get rid of the
> choicepoint as early as possible (with all the consequences
> this has for garbage collection etc), then it is not so easy
> at all...

It is very easy. Here is the "source level implementation":

if(A,B,C) :-
        (
          save_cp(CP),
          call(A),
          disable_cp(CP),
          call(B)
        ;
          call(C)
        ).

All you need two builtins: savecp/1 you probably have already (SICStus' 'choice idiom' I think)
disable_cp/1 sets the alternative of the CP choice point to !,fail or in case A has left no choice points, just cuts it.
Now inline this definition - taking care of any cuts in A - and you are done.
Side-effect - apart from cut in A - seem not to play a role - or am I overlooking something ?

Quote:
> > and I have seen many cases where it comes very handy.

> That I find surprising! I have been programming in Prolog for
> about 15 years and never missed it. What am I doing wrong?

Same question here ! I have used it a couple of times for problems of the type "find
maximal subsets with a certain property", but that's it.
On the other hand, most of my uses of -> ; would have run exactly the same if
I had used if/3

Cheers

Bart Demoen



Wed, 27 Jul 2005 00:43:46 GMT  
 Could use some help with if/3 implementation for Amzi! Prolog

Quote:

>This version is like SICStus'
>implementation of ( -> ; ) in that it will only explore the first solution
>of If:

>if( If, Then, _Else ) :-
>        call( If ),
>        !,
>        call( Then ).
>if( If, _Then, Else ) :-
>        call( Else ).

>If you remove the cut, it will act like SICStus' if/3, in that it will be
>able to explore all solutions of If.

If you just remove the cut, then the `Else' goal will get executed on
backtracking even if the `If' goal succeeeded!

--

The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.



Wed, 27 Jul 2005 01:07:10 GMT  
 Could use some help with if/3 implementation for Amzi! Prolog

Quote:


>> I think Prolog vendors should implement if/3

>I second that.

>> or *-> (which I like better
>> as the implementation is compiled and transparent to ! just like ->).

>The surface syntax should not imply whether it is transparent and compiled.
>It is just as easy to catch if/3 during compilation as for catching ->

The surface syntax *should* imply whether or not it is transparent to cuts.
Otherwise, how is the poor reader supposed to figure out what a cut means?

Standard Prolog has a simple mnemonic for that: the standard Prolog
built-ins whose names are operators (e.g. ",", ";", "->" are transparent),
and the ones whose names are words (e.g. "call", "once") are not.
If an alternative if-then-else construct is added, it would be best
if it could preserve the correctness of this mnemonic.

If the construct it is transparent to cuts, then it needs to be recognized
by the compiler.  However, you are right in the sense that if it is not
transparent, it could still be recognized and inlined by the compiler.
So the surface syntax should not determine whether it is "compiled".

--

The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.



Wed, 27 Jul 2005 01:15:49 GMT  
 Could use some help with if/3 implementation for Amzi! Prolog

----------

Quote:

>Standard Prolog has a simple mnemonic for that: the standard Prolog
>built-ins whose names are operators (e.g. ",", ";", "->" are transparent),
>and the ones whose names are words (e.g. "call", "once") are not.
>If an alternative if-then-else construct is added, it would be best
>if it could preserve the correctness of this mnemonic.

If by 'standard' you mean ISO-standard then this statement is not strictly
correct. The if-part of ->/2 is not transparent to cut, but the then-part
is. See the notes to section 7.8.7.

regards

Graham Thwaites



Wed, 27 Jul 2005 02:21:14 GMT  
 Could use some help with if/3 implementation for Amzi! Prolog

Quote:


>>This version is like SICStus'
>>implementation of ( -> ; ) in that it will only explore the first solution
>>of If:

>>if( If, Then, _Else ) :-
>>        call( If ),
>>        !,
>>        call( Then ).
>>if( If, _Then, Else ) :-
>>        call( Else ).

>>If you remove the cut, it will act like SICStus' if/3, in that it will be
>>able to explore all solutions of If.

> If you just remove the cut, then the `Else' goal will get executed on
> backtracking even if the `If' goal succeeeded!

oops, good point - I guess you'd need a \+call(If) in the second clause
once you've removed the cut

--
Matthew Purver - matt at purver dot org



Wed, 27 Jul 2005 02:27:20 GMT  
 Could use some help with if/3 implementation for Amzi! Prolog

Quote:

> >The surface syntax should not imply whether it is transparent and compiled.
> >It is just as easy to catch if/3 during compilation as for catching ->

> The surface syntax *should* imply whether or not it is transparent to cuts.
> Otherwise, how is the poor reader supposed to figure out what a cut means?

> Standard Prolog has a simple mnemonic for that: the standard Prolog
> built-ins whose names are operators (e.g. ",", ";", "->" are transparent),
> and the ones whose names are words (e.g. "call", "once") are not.

I wish I had a copy of the ISO Prolog standard at hand. But here is
what the SICStus Prolog manual says about

          +P -> +Q ; +R [ISO]

   ...
   In sicstus execution mode no cuts are allowed in P.
   In iso execution mode cuts are allowed in P and their scope is the goal P.

Is the SICStus Prolog manual  correct w.r.t. the ISO standard,
or is your notion of "Standard Prolog" not the same as ISO Prolog ?

Apart from all that ... anyone using cuts inside the if/3 construct,
is in need of a long vacation.

Cheers

Bart Demoen



Wed, 27 Jul 2005 02:55:58 GMT  
 
 [ 19 post ]  Go to page: [1] [2]

 Relevant Pages 

1. Amzi Prolog versus LPA Prolog.

2. Amzi-Prolog vs. Visual Prolog

3. Searching Amzi Prolog with Smalltalk examples

4. Amzi Prolog - Newbie Question

5. Code correction. Was: Re: Could use some help with if/3 implementation for Amzi! Prolog

6. Amzi Prolog - Warplan exame: extending it

7. Amzi Prolog for the Web

8. Amzi! Prolog

9. Random in Amzi Prolog

10. How Do I: Browser-Enable Amzi Prolog Program

11. Amzi Prolog and SQL Server

12. How to use COM with Amzi Prolog

 

 
Powered by phpBB® Forum Software