Dealing with complicated prolog loops - prolog

I am using Prolog to encode some fairly complicated rules in a project of mine. There is a lot of recursion, including mutual recursion. Part of the rules look something like this:
pred1(X) :- ...
pred1(X) :- someguard(X), pred2(X).
pred2(X) :- ...
pred2(X) :- othercondition(X), pred1(X).
There is a fairly obvious infinite loop between pred1 and pred2. Unfortunately, the interaction between these predicates is very complicated and difficult to isolate. I was able to eliminate the infinite loop in this instance by passing around a list of objects that have been passed to pred1, but this is extremely unwieldy! In fact, it largely defeats the purpose of using Prolog in this application.
How can I make Prolog avoid infinite loops? For example, if in the course of proving pred1(foo) it tries to prove pred1(foo) as a sub-goal, fail and backtrack.
Is it possible to do this with meta-interpreters?

Yes, you can use meta-interpreters for this purpose, as mat suggests. But for the normal use case, that is going far beyond the regular effort.
What you may consider instead is to separate the looping functionality from your actual logic using higher-order predicates. That is a very safe way to go — SWI even checks if all the uses have a corresponding definition. This checking is either invoked when typing make. or check.
As an example, consider closure0/3 and path/4 which both handle loop checks "once and forever".

One feature that is available in some Prolog systems and that may help you to solve such issues is called tabling. See for example the related question and prolog-tabling.
If tabling is not available, then yes, meta-interpreters can definitely help a lot with this. For example, you can change the executation strategy etc. with a meta-interpreter.
In SWI-Prolog, also check out call_with_inference_limit/3 to robustly limit the execution, independent of CPU type and system load.
Related and also useful are termination analyzers like cTI: They allow you to statically derive termination conditions.

Related

Does a rule without passing a variable against the philosophy of declarative programming or prolog?

cancer():-
pain(strong),
mood(depressed),
fever(mild),
bowel(bloody),
miscellaneous(giddy).
diagnose():-
nl,
cancer()->write("has cancer").
for example, dog(X) says that X is a dog but my cancer statement just checks whether the following conditions meet. Is there a better way to do that?
In pure Prolog, a predicate without any arguments can only succeed or fail (or not terminate at all).
Thus, it can encode only very little information. A predicate that always succeeds is already available: true/0, having zero arguments. A predicate that always fails is also already available: false/0, also having zero arguments. A predicate that never terminates can be easily constructed.
So, in this sense, you do not need more predicates with zero arguments, and I think you are perfectly justified in being suspicous about such predicates.
Predicates with zero arguments are of limited use since they are so specific. They may however be used for example to describe a fixed set of tests, or be useful only for their side-effects. This is also what you are using, by emitting output on the terminal in case the predicate succeeds.
This means that you are leaving the pure subset of Prolog, and now relying on features that are beyond pure logic.
This is typically a very bad idea, because it:
prevents or at least complicates many forms of reasoning about your program
makes it much harder to test your predicates
is not thread safe in general
etc.
Therefore, suppose your write your program as follows:
cancer(Patient):-
patient_pain(Patient, strong),
patient_mood(Patient, depressed),
patient_fever(Patient, mild),
patient_bowel(Patient, bloody),
patient_miscellaneous(Patient, giddy).
This predicate is now parametrized by a patient, and thus significantly more general than what you have posted.
It can now be used to reason about several patients, it can be used to reason in parallel about different patients, you can use a Prolog query to test the predicate etc.
You can further generalize the predicate by defining for example patient_diagnosis/2, keeping everything completely pure and benefiting from the above advantages. Note that a patient may have several illnesses, which can be emitted on backtracking.
Thus: Yes, a rule without arguments is at least suspicious and atypical if it arises in your actual code. Leaving aside scenarios such as "test case" and "consistency check", it can only be useful for its side-effects, and I recommend you avoid side-effects if you can.
For more information about this topic, see logical-purity.
cancer() isn't legal syntax, but the idea's perfectly fine.
Just do the call as
cancer
and define it as a fact or rule.
cancer. % fact
cancer :- blah blah %rule
in fact, you use a system predicate with no args in your program -
nl is a predicate that always succeeds, and prints a newline.
There are many reasons to have a predicate with no arguments. Suppose you have a server that runs in a slightly different configuration in production than in development. Developer access API is off in production.
my_handler(Request) :-
development,
blah blah
development only succeeds if we're in development environment
or you might have a side effect set off, or be using state.

O(1) term look up

I wish to be able to look up the existence of a term as fast as possible in my current prolog program, without the prolog engine traversing all the terms until it finally reaches the existing term.
I have not found any proof of it.. but I assume that given
animal(lion).
animal(zebra).
...
% thousands of other animals
...
animal(tiger).
The swi-prolog engine will have to go through thousands of animals trying to unify with tiger in order to confirm that animal(tiger) is in my prolog database.
In other languages I believe a HashSet would solve this problem, enabling a O(1) look up... However I cannot seem to find any hashsets or hashtables in the swi-prolog documentation.
Is there a swi-prolog library for hashsets, or can I somehow built it myself using term_hash\2?
Bonus info, I will most likely have to do the look up on some dynamically added data, either added to a hashset data-structure or using assertz
All serious Prolog systems perform this O(1) lookup via hashing automatically and implicitly for you, so you do not have to do it yourself.
It is called argument-indexing, and you find this explained in all good Prolog books. See also "JIT (just-in-time) indexing" in more recent versions of many Prolog systems, including SWI. Indexing is applied to dynamically added clauses too, and is one reason why assertz/1 is slowed down and therefore not a good choice for data that changes more often than it is read.
You can also easily test this yourself by creating databases with increasingly more facts and seeing that the lookup time remains roughly constant when argument indexing applies.
When the built-in first argument indexing is not enough (note that some Prolog systems also provide multi-argument indexing), depending on the system, you can construct your own indexing scheme using a built-in or library term hashing predicate. In the case of ECLiPSe, GNU Prolog, SICStus Prolog, SWI-Prolog, and YAP, look into the documentation of the term_hash/4 predicate.

Implementing arithmetic for Prolog

I'm implementing a Prolog interpreter, and I'd like to include some built-in mathematical functions (sum, product, etc). For example, I would like to be able to make calculations using knowledge bases like this one:
NetForce(F) :- Mass(M), Acceleration(A), Product(M, A, F)
Mass(10) :- []
Acceration(12) :- []
So then I should be able to make queries like ?NetForce(X). My question is: what is the right way to build functionality like this into my interpreter?
In particular, the problem I'm encountering is that, in order to evaluate Sum, Product, etc., all their arguments have to be evaluated (i.e. bound to numerical constants) first. For example, while to code above should evaluate properly, the permuted rule:
NetForce(F) :- Product(M, A, F), Mass(M), Acceleration(A)
wouldn't, because M and A aren't bound when the Product term is processed. My current approach is to simply reorder the terms so that mathematical expressions appear last. This works in simple cases, but it seems hacky, and I would expect problems to arise in situations with multiple mathematical terms, or with recursion. Is there a better solution?
The functionality you are describing exists in existing systems as constraint extensions. There is CLP(Q) over the rationals, CLP(R) over the reals - actually floats, and last but not least CLP(FD) which is often extended to a CLP(Z). See for example
library(clpfd).
In any case, starting a Prolog implementation from scratch will be a non-trivial effort, you will have no time to investigate what you want to implement because you will be inundated by much lower level details. So you will have to use a more economical approach and clarify what you actually want to do.
You might study and implement constraint languages in existing systems. Or you might want to use a meta-interpreter based approach. Or maybe you want to implement a Prolog system from scratch. But don't expect that you succeed in all of it.
And to save you another effort: Reuse existing standard syntax. The syntax you use would require you to build an extra parser.
You could use coroutining to delay the evaluation of the product:
product(X, A, B) :- freeze(A, freeze(B, X is A*B))
freeze/2 delays the evaluation of its second argument until its first argument is ground. Used nested like this, it only evaluates X is A*B after both A and B are bound to actual terms.
(Disclaimer: I'm not an expert on advanced Prolog topics, there might be an even simpler way to do this - e.g. I think SICStus Prolog has "block declarations" which do pretty much the same thing in a more concise way and generalized over all declarations of the predicate.)
Your predicates would not be clause order independent, which is pretty important. You need to determine usage modes of your predicates - what will the usage mode of NetForce() be? If I were designing a predicate like Force, I would do something like
force(Mass,Acceleration,Force):- Force is Mass * Acceleration.
This has a usage mode of +,+,- meaning you give me Mass and Acceleration and I will give you the Force.
Otherwise, you are depending on the facts you have defined to unify your variables, and if you pass them to Product first they will continue to unify and unify and you will never stop.

Which is more common practice in Prolog?

I'm writing a rule that searches a database of facts in the form:
overground(Station1, Station2, DurationOfTravel).
and allows to you search for all journeys that take the same duration of travel.
I've written these two rules:
timesearch(Duration) :-
overground(Station1, Station2, Duration),
print([Station1, Station2]).
timesearch(Duration, [Station1,Station2]) :-
overground(Station1, Station2, Duration).
Which do essentially the same thing. What I'm unsure about is which is best practice? Or are they two equally good solutions?
They don't do essentially the same thing; they contain the same "business" logic, but the first mixes in presentation logic (output code). It's a general principle of program design that business logic and presentation should be separated, so go with the second option and put the printing in some kind of main predicate.
In particular, in this example you don't want the printing to be done in the timesearch predicate; what if you decide one day that you want a more complicated algorithm that can determine the duration of a route of more than two hops? You can implement such an algorithm in terms of the second definition of timesearch, but not in terms of the first.
(This has very little to do with Prolog and all the more with the craft of good software design.)
In addition to #larsmans's answer, I'd like to add a link about pure functions. In any language where you have the chance to apply this concept, prefer pure functions when possible and handle the IO in separate parts.
Especially here in prolog, when backtracking is needed, the fact that you output things in your business logic predicates might reveal really problematic, since those things may be printed during the execution of a branch that won't lead to a relevant result.

Prolog, fail and do not backtrack

Is there any build-in predicate in SWI-Prolog that will always fail AND prevent machine from backtracking - it is stop the program from executing immediately (this is not what fail/0 does)?
I could use cuts, but I don't like them.
Doing something like !, fail is not a problem for me, but in order to accomplish what I want, I would have to use cuts in more locations and this is what I don't like.
You could use exceptions. Based on your question - it should help.
Refer link
You could use the mechanism explicitly designed to help you accomplish something, but you don't like it?
You can always use not, which is syntactic sugar for cut fail
Two alternatives come to mind:
Pass around a backtrack(true) or backtrack(false) term through the code you want to control, and interpret it in the definition of the predicates you're writing to fail quickly if it is set to backtrack(false), or to continue if backtrack(true). Note that this won't actually prevent backtracking; it should just enable fast-failure. Even if your proof tree is deep, this should provide a fast way of preventing the execution of certain code on backtracking.
Use exceptions, as suggested by #Xonix (+1). Throwing an exception will terminate the proof tree construction immediately, and you can pass any term data through the exception up to the handler, bypassing any more execution - it will probably be faster than the first option, but may not be as portable.
Personally I've used both methods before - the first where I've anticipated the need before writing the code, the latter where I haven't.
Too bad, that's what cuts are for.

Resources