Lazy findall

280 views
Skip to first unread message

Eyal Dechter

unread,
Sep 26, 2015, 10:12:38 AM9/26/15
to SWI-Prolog
Is there a way to define a findall-like predicate that produces a lazy list of solutions? That is, a list of solutions whose tail is frozen. Thanks.

Sent from my iPhone

Markus Triska

unread,
Sep 26, 2015, 10:29:41 AM9/26/15
to SWI-Prolog
Hi Eyal,

one way to do something similar is explained in "Structure and Interpretation of Computer Programs":

The idea is to create a "stream" (lazy list) as a pair, one of whose components captures the relation between the stream's current state and the next.

I have put some showcases of this approach online at:

This requires to explicitly encode the relation between the current state and the next, so it is not compatible with findall/3.

In your case, is it not acceptable to simply give alternative solutions on backtracking?

All the best!
Markus

Eyal Dechter

unread,
Sep 26, 2015, 2:24:17 PM9/26/15
to Markus Triska, SWI-Prolog
I saw your stream implementation but I think your "A couple of meta-interpreters" is more relevant. Let me make this a little more concrete to make it clear what I'm after. 

Suppose I have a database of weighted clauses held in a predicate rule/3 of the form rule(Weight, Head, Body) where Weight is a positive number and Head and Body are compound terms. I would like to implement a search procedure that finds a proof for some Goal using these rules, and I would like to find the proofs that has the largest weight. I would like to use a beam search to do this. The basic beam search algorithm is simply, 

- let N be the maximum size of the beam
- initialize Beam = [{elem:Goal, score:0}}
- until a solution is found:
  - AllChildren <- apply every rule to every goal in the beam if it applies, setting the score of each resulting element to be the score of the parent plus the weight of the rule
  - Beam <- the N elements of AllChildren with the largest scores

Now, this isn't difficult to implement, but suppose the number of rules is very large and the size of the beam is small by comparison. Then one does not need to apply every rule to the beam. Instead, one can apply rules in decreasing order of their weights (that is why I asked in a separate thread about sorting clauses in the dynamic database); if the resulting goal has a score that is worse than that lowest score in a full beam, then the rest of the rules can be pruned. 

I'm having trouble implementing this pruning. The rules are in the database, so I can obtain the children of goal G roughly by calling findall(W-B, rule(W, G, B), Children), but I don't want all of them, I want them one by one so that I can decide when to prune. 

Does this make sense? 

In the breadth-first meta-interpreter you present in your "A couple of meta-interpreters" you use findall/4 to reify the alternatives. To do the same thing here, but implement pruning, we want to use a lazy findall. That is, we want to reify the choice point, so that we can ask it for more alternatives only if we need to. 

Best,
Eyal
--
You received this message because you are subscribed to the Google Groups "SWI-Prolog" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swi-prolog+...@googlegroups.com.
Visit this group at http://groups.google.com/group/swi-prolog.
For more options, visit https://groups.google.com/d/optout.

Samer Abdallah

unread,
Sep 26, 2015, 3:51:22 PM9/26/15
to Eyal Dechter, <swi-prolog@googlegroups.com>
Hi Eyal,

What you describe sounds like Paul Tarau’s ‘logic engines', which give you access to an object that 
you can extract solutions from one by one. We’d be able to implement such a thing if we had
delimited continuations, but they only exist in an experimental form in hProlog. (Tarau’s binprolog
is indeed a continuation based implementation of Prolog.)

An alternative would be to realise a Prolog engine using a SWI Prolog thread which accepts a goal
and then sends each solution to a queue. If you make the queue size equal to 1,  then the thread will
block waiting for each solution to be consumed. (I expect this is more or less what the Pengines library
does.)

Regarding your application in particular, if you can make sure the clauses of rule/3 are asserted
in descending order of Weight, then you might be able to get it to work in the way you describe.
You could use thread_signal/2 to stop the engine thread when you have enough
solutions. I’m not sure if you would need to maintain multiple engines to achieve what you want to do.

The system you describe reminds me of David Poole’s Probabilistic Horn Abduction, which attaches
probabilities to the alternatives at each choice point, and uses a priority queue to keep track of 
the most likely proof paths so far. I have a reimplementation of that for SWI Prolog that I was toying 
with a while ago, based on a meta-interpreter (which captures the continuation at each choice point),
a priority queue of continuations, and produces solutions in the form of a lazy list. However, it still
uses a findall to get all the possibilities at each choice point. You’re welcome to have a look at it.

cheers,
Samer
signature.asc

Julio Di Egidio

unread,
Sep 26, 2015, 4:58:37 PM9/26/15
to SWI-Prolog
On Saturday, September 26, 2015 at 8:51:22 PM UTC+1, Samer Abdallah wrote:
Hi Eyal,

What you describe sounds like Paul Tarau’s ‘logic engines', which give you access to an object that 
you can extract solutions from one by one. We’d be able to implement such a thing if we had
delimited continuations, but they only exist in an experimental form in hProlog. (Tarau’s binprolog
is indeed a continuation based implementation of Prolog.)

I have done exactly that recently (with threads, message queues, and ancestral cuts):


It is not complete, missing the return statement: already designed though, just literally need to find the time.

Nice to know there are use cases...

Julio

Markus Triska

unread,
Sep 26, 2015, 5:24:23 PM9/26/15
to SWI-Prolog, tri...@logic.at
Hi Eyal,

first, some related information:

You may find the call_nth/2 predicate implemented by Ulrich Neumerkel useful, implemented for SICStus:


A sample usage is shown here, it includes a trimmed down definition for SWI-Prolog:

You can use this to ask for the N-th solution of a goal.

This, or a similar meta-predicate, may be the semantic construct you are looking for.

In particular, check out the findnsols/4 predicate in SWI-Prolog, allowing you to access chunks of at most N solutions on backtracking.

That being said, you can manually construct a version of findall/3 that fetches as many solutions as are necessary in your use case. This is not quite the same as doing it lazily, but it seems to match the description of your use case: You fetch solutions until you prune.

"The Craft of Prolog" describes an approach for rolling your own version of findall/3, using the dynamic database. In particular, make sure to symbolically distinguish marks (separating nested findall/3 calls) from accumulated solutions.

All of this can be combined with my streams implementation, by letting the stream carry information about which N solutions to obtain next, and also with the breadth-first meta-interpreter, yielding a combination of breadth-first (for each N alternatives) and depth-first search (for all next N alternatives) on backtracking.

All the best!
Markus

Jan Burse

unread,
Sep 27, 2015, 5:26:37 AM9/27/15
to SWI-Prolog, tri...@logic.at
Hi,

In a recent new module (*) there is now a limit/2,
which can be used inside an findall/3 as well I guess.

Bye

(*)
The module is http://www.swi-prolog.org/pldoc/doc/swi/library/solution_sequences.pl
I guess it was developed for SWISH, but has further
goodies like offset/3 etc.. which could also go into a findall.

Jan Wielemaker

unread,
Sep 27, 2015, 8:05:50 AM9/27/15
to Samer Abdallah, Eyal Dechter, <swi-prolog@googlegroups.com>
On 09/26/2015 09:51 PM, Samer Abdallah wrote:
> Hi Eyal,
>
> What you describe sounds like Paul Tarau’s ‘logic engines', which
> give you access to an object that you can extract solutions from one
> by one. We’d be able to implement such a thing if we had delimited
> continuations, but they only exist in an experimental form in
> hProlog. (Tarau’s binprolog is indeed a continuation based
> implementation of Prolog.)

delimited continuations will likely end up in SWI-Prolog as well
at some point. Note that Tarau's engines are basically the same
as SWI-Prolog threads. I had some discussion with Paul about this
in Cork. May be my wording is not very precise. Should be that
the underlying primitives are the same, but Paul uses them to
create engines while SWI-Prolog uses them to create threads. We
could create engines in the binprolog sense quite easily.

> An alternative would be to realise a Prolog engine using a SWI
> Prolog thread which accepts a goal and then sends each solution to a
> queue. If you make the queue size equal to 1, then the thread will
> block waiting for each solution to be consumed. (I expect this is
> more or less what the Pengines library does.)

More or less. It uses two message queues. The goal running inside
a pengine is wrapped into something that resembles the Prolog
toplevel. To get the next (N) answers, you send a message to
one of the queues that causes the pengine to call findnsols/4
and send the answers to the other queue.

Pengines are very close to Tarau's engines, except that they
normally run in a different Prolog process.

Cheers --- Jan

Julio Di Egidio

unread,
Sep 27, 2015, 8:32:57 AM9/27/15
to SWI-Prolog
On Sunday, September 27, 2015 at 1:05:50 PM UTC+1, Jan Wielemaker wrote:
On 09/26/2015 09:51 PM, Samer Abdallah wrote:
> Hi Eyal,
>
> What you describe sounds like Paul Tarau’s ‘logic engines', which
> give you access to an object that you can extract solutions from one
> by one. We’d be able to implement such a thing if we had delimited
> continuations, but they only exist in an experimental form in
> hProlog. (Tarau’s binprolog is indeed a continuation based
> implementation of Prolog.)

delimited continuations will likely end up in SWI-Prolog as well
at some point.  Note that Tarau's engines are basically the same
as SWI-Prolog threads.

Tarau's Fluents (*) may boil down to executing a goal in a separate thread, but his Interactors (**) are more than just that.

Namely, can we do anything like this with pengines?

  nat(N) :- return(N), N1 is N+1, nat(N1).

Julio

Jan Wielemaker

unread,
Sep 27, 2015, 8:39:09 AM9/27/15
to Julio Di Egidio, SWI-Prolog
On 09/27/2015 02:32 PM, Julio Di Egidio wrote:
> On Sunday, September 27, 2015 at 1:05:50 PM UTC+1, Jan Wielemaker wrote:
>
> On 09/26/2015 09:51 PM, Samer Abdallah wrote:
> > Hi Eyal,
> >
> > What you describe sounds like Paul Tarau’s ‘logic engines', which
> > give you access to an object that you can extract solutions from one
> > by one. We’d be able to implement such a thing if we had delimited
> > continuations, but they only exist in an experimental form in
> > hProlog. (Tarau’s binprolog is indeed a continuation based
> > implementation of Prolog.)
>
> delimited continuations will likely end up in SWI-Prolog as well
> at some point. Note that Tarau's engines are basically the same
> as SWI-Prolog threads.
>
>
> Tarau's Fluents (*) may boil down to executing a goal in a separate
> thread, but his Interactors (**) are more than just that.
>
> Namely, can we do anything like this with pengines?
>
> nat(N) :- return(N), N1 is N+1, nat(N1).

Yes, return(X) is basically pengine_output(X), except that the client
can distinguish whether the new term was produced by a pengine_output
or by a solution to the goal.

Cheers --- Jan

Julio Di Egidio

unread,
Sep 27, 2015, 8:48:07 AM9/27/15
to swi-p...@googlegroups.com, ju...@diegidio.name
Unless I am missing something, it is not: that return suspends the computation *in nat*..  [Indeed, nat there is supposed to be a goal run by some pengine, not a predicate calling a pengine.]

But I'd expect Pengines and my Answer Sources to share *a lot* of code: threads, two queues for each pair client-worker, and so on, they are indeed there.  Could be interesting to converge rather than duplicate/overlap, i.e. extend Pengines to full Interactors.  Or not, but then they are not.

Julio

Jan Wielemaker

unread,
Sep 27, 2015, 9:25:46 AM9/27/15
to Julio Di Egidio, SWI-Prolog
On 09/27/2015 02:48 PM, Julio Di Egidio wrote:
> On Sunday, September 27, 2015 at 1:39:09 PM UTC+1, Jan Wielemaker wrote:
>
> On 09/27/2015 02:32 PM, Julio Di Egidio wrote:
> >
> > delimited continuations will likely end up in SWI-Prolog as well
> > at some point. Note that Tarau's engines are basically the same
> > as SWI-Prolog threads.
> >
> > Tarau's Fluents (*) may boil down to executing a goal in a separate
> > thread, but his Interactors (**) are more than just that.
> >
> > Namely, can we do anything like this with pengines?
> >
> > nat(N) :- return(N), N1 is N+1, nat(N1).
>
> Yes, return(X) is basically pengine_output(X), except that the client
> can distinguish whether the new term was produced by a pengine_output
> or by a solution to the goal.
>
>
> Unless I am missing something, it is not: that return suspends the
> computation in nat...

Is the suspension in any way relevant? AFAIK, Paul's interactors run
on the same thread and thus they must suspend to give control back to
the thing interacting with it. Threads do not need to suspend. If
you want to suspend you can use pengine_input(+Prompt, -Reply), where
Prompt, is an arbitrary Prolog term.

> But I'd expect Pengines and my Answer Sources to share *a lot* of code:
> threads, two queues for each pair client-worker, and so on, they are
> indeed there. Could be interesting to converge rather than
> duplicate/overlap, i.e. extend Pengines to full Interactors. Or not,
> but then they are not.

Torbjörn was (AFAIK) unaware of interactors. He modelled pengines to the
Prolog toplevel and the goal is to access and control Prolog notably
from JavaScript. I was aware of Paul's work, but I fear I must admit it
was when Torbjörn and I wrote an ICLP article about Pengines that I
became aware how closely they are related.

I'm not sure how much purpose is there in trying to avoid the overlap.
They serve rather different goals. The interactors allow you to
implement control structures that are hard to implement in normal
Prolog. They are light-weight. Pengines concentrate on remote execution.
That is much more heavyweight anyway and comes with problems such as
resource management, security and isolation (between pengines).

If you really want interactors in SWI-Prolog, I think you need to do
this:

- Change the thread/engine API to return answers directly instead
of using message queues. That is more natural and the whole
sequence to ask a thread via message-queues to generate a new
answer is both clumsy and slow.
- Provide a Prolog API to access Prolog engines seperated from
threads. The C API for that exists, although it is a bit
clumsy and heavy weight as it involves a temporary thread
for creating a new engine.
- Associate engines with blob-based handles, so you can GC them.

Then there are some corner cases. Current SWI-Prolog engines keep some
data local, such as thread-local predicates, flags and the standard
streams. You probably do not want that with engines. I don't think it
is a big project to get all this done.

Cheers --- Jan

Julio Di Egidio

unread,
Sep 27, 2015, 10:03:58 AM9/27/15
to swi-p...@googlegroups.com
On Sunday, September 27, 2015 at 2:25:46 PM UTC+1, Jan Wielemaker wrote:
On 09/27/2015 02:48 PM, Julio Di Egidio wrote:
> On Sunday, September 27, 2015 at 1:39:09 PM UTC+1, Jan Wielemaker wrote:
>     On 09/27/2015 02:32 PM, Julio Di Egidio wrote:
>     >
>     >     delimited continuations will likely end up in SWI-Prolog as well
>     >     at some point.  Note that Tarau's engines are basically the same
>     >     as SWI-Prolog threads.
>     >
>     > Tarau's Fluents (*) may boil down to executing a goal in a separate
>     > thread, but his Interactors (**) are more than just that.
>     >
>     > Namely, can we do anything like this with pengines?
>     >
>     >   nat(N) :- return(N), N1 is N+1, nat(N1).
>
>     Yes, return(X) is basically pengine_output(X), except that the client
>     can distinguish whether the new term was produced by a pengine_output
>     or by a solution to the goal.
>
> Unless I am missing something, it is not: that return suspends the
> computation in nat...

Is the suspension in any way relevant?

Yes, absolutely: the return operation is what upgrades fluents to interactors.  Indeed, note that the above nat could be easily rewritten with a more standard couple of clauses, but in general that is not possible (unless with workers, etc.).

 AFAIK, Paul's interactors run
on the same thread and thus they must suspend to give control back to
the thing interacting with it.

Tarau's engines are indeed orthogonal to threading: but to achieve that, Tarau builds his system on top of an *ad-hoc interpreter* that has got, built into it, the ability to handle these suspend/resume operations.  So we are essentially faced with two options: 1) rebuild a Prolog system from scratch, starting from the ad-hoc interpreter as Tarau does; or, 2) just build these engines on top of SWI (or any other existing Prolog system) infrastructure.  I have opted for the latter, not willing to build the nth Prolog variant around.  --  That in a nutshell: more can be said about what we gain and what we lose by adopting one approach vs. the other.

Threads do not need to suspend.  If
you want to suspend you can use pengine_input(+Prompt, -Reply), where
Prompt, is an arbitrary Prolog term

Suspend in the worker, not in the client: the client just requests the next answer at any point of his own execution.  --  But I will have a better look into Pengines to be sure...
 
> But I'd expect Pengines and my Answer Sources to share *a lot* of code:
> threads, two queues for each pair client-worker, and so on, they are
> indeed there.  Could be interesting to converge rather than
> duplicate/overlap, i.e. extend Pengines to full Interactors.  Or not,
> but then they are not.

Torbjörn was (AFAIK) unaware of interactors. He modelled pengines to the
Prolog toplevel and the goal is to access and control Prolog notably
from JavaScript. I was aware of Paul's work, but I fear I must admit it
was when Torbjörn and I wrote an ICLP article about Pengines that I
became aware how closely they are related.

I'm not sure how much purpose is there in trying to avoid the overlap.
They serve rather different goals. The interactors allow you to
implement control structures that are hard to implement in normal
Prolog. They are light-weight. Pengines concentrate on remote execution.

They are as lightweight as a dedicated interpreter is: indeed, Tarau's interpreter is even native...  Again, Tarau's specific approach is akin to writing a (non-standard) Prolog engine from scratch: necessarily, from a conceptual point of view as well as in terms of efficiency.

That is much more heavyweight anyway and comes with problems such as
resource management, security and isolation (between pengines).

I have not encountered any of those problems.  The only thing my implementation (when completed) will lack re pengines is remote execution... and I would not think that is a difficult part: I am an expert network programmer anyway if it comes to that...

If you really want interactors in SWI-Prolog, I think you need to do
this:

I do not think so, for the reasons hinted at above.  But I may still be missing something, of course.  :)

Maybe let me have a look at these Pengines a bit better: I'd think a little extension to these, if that is all there is to it, would still be much better than an omission and then yet another (or zillions of semi-similar) external pack...

Julio

Jan Burse

unread,
Sep 27, 2015, 3:47:25 PM9/27/15
to SWI-Prolog, ju...@diegidio.name
Hi Jan W.,

I see a certain excitement here. But please be aware that practically
each Prolog system has an iterator like API somewhere. Just check
the section in the documentation that deals with foreign language XY
calls my Prolog system.

    For example tuProlog has also an iterator like API:
    http://tuprolog.sourceforge.net/doc/2p-guide.pdf
    Chapter 8 Using tuProlog from Java

    You find method calls such as engine.solveNext() or
    engine.hasOpenAlternatives() or info.isSuccess().

One of the few alternatives for accessing from foreign language XY a
Prolog system, is to pass a continuation to the solver, which is called
for each success. The continuation might also return a flag, to issue a
cut or exception.

The difference among the Prolog systems is only how properly
isolated the iterator is. Can we have multiple iterators? Can we use
them concurrently pre-emptive? Etc.. etc.. One of the benefit of Taraus
paper is, that he suggests a book keeping for spawning iterators, via the
trail, although I am not sure whether this is necessarily the way to go.

So I would say empirically you could find:
- Most mature Prolog systems have an iterator api, since the
  developers went through the pain of implementing a trampolin
  (for example the WAM is a trampolin) AND as well implementing
  an interator like control of the trampolin (jumping in and out of
   the trampolin to give back control to the foreign language XY)

- Some student project Prolog systems might only have a
  continuation style interface, unfortunately some Closure,
  Haskell, etc.. implementations of a Prolog like language
  often also only have this interface.

Bye

P.S.: A lazy list interface is the same as an iterator interface. If
you do a force on a list cell, this is practically the same as the
next on an iterator. Right?

Jan Burse

unread,
Sep 27, 2015, 3:58:35 PM9/27/15
to SWI-Prolog
Hi,


> Then there are some corner cases. Current SWI-Prolog engines keep some
> data local, such as thread-local predicates, flags and the standard
> streams. You probably do not want that with engines.  I don't think it
> is a big project to get all this done.

If you have Knowledgebase 1<->mc Engine
   1: An engine belongs to exactly one knowledge base
   mc: A knowledgebase can have zero, one or many engines on it

You might move some of the data to the knowledge base, some
flags, tables and so on. But typically an engine can do everything
what a normal Prolog toplevel can do, for example thread_local
predicates of course.

But this is again the book keeping issue. And what you would
respectively can delegate to a GC. Prolog system developers that
use Java are less aware of the issues, since everything is GCed.
But matters are not that simple.

You should use closable iterators, I think Tarau uses an other
method name, not close() but stop(). Just think of an SQL cursor
that you better close to release query resources. Of course you
can also wait for a dead mans handle, i.e. the database system
closes it because of a time out. But I wouldn't make this the norm.

Bye

Jan Burse

unread,
Sep 27, 2015, 4:06:55 PM9/27/15
to SWI-Prolog

> P.S.: A lazy list interface is the same as an iterator interface. If
> you do a force on a list cell, this is practically the same as the
> next on an iterator. Right?

Not really. In a lazy list you can usually go back and access previous
solutions as well. In Prolog iterators, previous solutions will be gone
when you issue a next. Prolog will destroy previous variable bindings
and previous choice points to some degree.

This is SLD resolution, this is the power of Prolog, that it works
with very few resources. Lazy lists can only do this if they carbage
collect unused already generated prefixes.

So if youre foreign function interface allows variable handles, you will
see that their content might change with a next. Their context might
be undone and then unifyed with another value, even multiple times
before a new solution is obtained.

Bye

Julio Di Egidio

unread,
Sep 27, 2015, 5:32:47 PM9/27/15
to SWI-Prolog

On Sunday, September 27, 2015 at 8:47:25 PM UTC+1, Jan Burse wrote:


One of the benefit of Taraus
paper is, that he suggests a book keeping for spawning iterators, via the
trail, although I am not sure whether this is necessarily the way to go.

Tarau does not use threads at all.  Tarau's core is written in Java, consisting of the interpreter, the classes of fluents, and a couple of combinators.  On top of that he recovers Prolog and more: as the object language.  No threads anywhere, and he even underlines it as there are important points around the threads vs. no threads issue.

Are we talking of the same paper(s)?  I have given links up-thread.

Julio

Julio Di Egidio

unread,
Sep 27, 2015, 5:38:42 PM9/27/15
to SWI-Prolog

On Sunday, September 27, 2015 at 9:06:55 PM UTC+1, Jan Burse wrote:


> P.S.: A lazy list interface is the same as an iterator interface. If
> you do a force on a list cell, this is practically the same as the
> next on an iterator. Right?

Not really. In a lazy list you can usually go back and access previous
solutions as well. In Prolog iterators, previous solutions will be gone
when you issue a next. Prolog will destroy previous variable bindings
and previous choice points to some degree.

Looking forward at the next solution is not something one can do in general, as the goal to execute might have side-effects.

Regardless: to my understanding, iterators are fluents, not yet interactors.  For one thing, with an interactor you do not need to destroy bindings to enumerate solutions, you are in fact completely freed from the backtracking cycle.

Read the two papers, Tarau explains it better....

Julio

Jan Burse

unread,
Sep 28, 2015, 6:35:20 AM9/28/15
to SWI-Prolog
Hi,

I guess its the same paper you discussed, respectively you mentioned
in connection with your answer sources post on comp.lang.prolog. The
title of the paper is:
Fluents: A Refactoring of Prolog for Uniform Reflection and Interoperation with External Objects":
http://www.cse.unt.edu/~tarau/research/LeanProlog/RefactoringPrologWithFluents.pdf

What I was refering to when I mentioned iterator book keeping is found
in this paper on page (oops the paper doesn't have pages), ok then
it is found under the heading:


    3 Fluent Classes and their Operations

     If you look at the Java code you find:
      Fluent(Prog p) {trailMe(p);}
      protected void undo() {stop();}

The trailMe will put the new iterator on the Prolog trail. The Prolog trail
will call undo during backtracking of the parent interpreter. As by the
class definition the trail undo for an iterator will delegate to a stop
of the iterator.


Regardless: to my understanding, iterators are fluents, not yet interactors.  For one
thing, with an interactor you do not need to destroy bindings to enumerate solutions,
you are in fact completely freed from the backtracking cycle.

I guess you are talking about possible backtracking in the child interpreter,
and not in the parent interpreter. The parent interpreter has obviously
backtracking and a trail and undo steps. Paul Tarau says

(most Fluents also call stop on >>backtracking<<, through their internal undo operation).


Question is what you mean by completely freed from backtracking concerning

a child interpreter which was spawned by answer_source/3. In my optionion

answer_source/3 spawns a normal Prolog interpreter which might also

used backtracking. I don't know how you want to free a Prolog interpreter from

backtracking.


Even when the answer_source/3 produces the first solution it might already

have used backtracking. Just imagine the goal was:

     p(X,Y), q(X).

And the databse was:

     p(a,b).

     p(b,c).

     q(b).

if you start an answer_source/3 with the above goal, and the output

(X,Y) you will get (X,Y) = (b,c) as a first solution through simple

backtracking. Obviously further get/2 calls on an answer source

will also force a backtracking.


Bye


 

Jan Burse

unread,
Sep 28, 2015, 6:55:42 AM9/28/15
to SWI-Prolog
Hi,



Regardless: to my understanding, iterators are fluents, not yet interactors.  For one
thing, with an interactor you do not need to destroy bindings to enumerate solutions,
you are in fact completely freed from the backtracking cycle.

I guess you are talking about possible backtracking in the child interpreter,
and not in the parent interpreter. The parent interpreter has obviously
backtracking and a trail and undo steps.

On another reading, you propably mean the advantage to have a handle
to an answer source, and call get/2 when ever you want. Tarau speculates


      "The existence of this simple meta-interpreter indicates that answer

       sources lift expressiveness of first-order Horn Clause logic significantly."


Well, well. There are some doubts, first do answer sources constitute
a logic? And why are they not included in Horn Clauses?

Just imagine clauses with a numbering, i.e. a clause/3 predicate instead
of a clause/2 predicate. Go figure writing answer sources in Horn Clause
logic itself.
 


 

Michael Hendricks

unread,
Oct 2, 2015, 11:35:27 AM10/2/15
to Eyal Dechter, SWI-Prolog
On Sat, Sep 26, 2015 at 8:12 AM Eyal Dechter <eyald...@gmail.com> wrote:
Is there a way to define a findall-like predicate that produces a lazy list of solutions? That is, a list of solutions whose tail is frozen. Thanks.

Version 0.9.0 of the "list_util" pack has lazy_findall/3. The implementation has a couple warts, but it's usable in certain circumstances.

I hope that helps.

Reply all
Reply to author
Forward
0 new messages