Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
427 views
in Technique[技术] by (71.8m points)

prolog - Getting an order into predicate resolution

Look at the following goals (I am using swi-prolog with clpfd from Markus Triska):

result(Input,Result) :-
    Input #> 10,
    Result=decline.
result(Input,Result) :-
    Input in 0..20,
    Result=offer.

A possible query looks like this:

?- result(15,B).
B = decline ;
B = offer.

I want to add an order or some sort of solution priority. If "decline" is a valid response for Input=15, then the second goal should not be considered anymore, so that only B=decline is a solution but not B=offer.

I know that I could add a !/0 but then the other way round would not work. Give me all possible answers for this predicate.

Considering this example, a Result=offer should only be true for Input 0..10, because otherwise the higher prior decline goal should fire.

Am I thinking too imperative when I try to consider an order within predicates?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There are several issues here, let's start first with the most obvious:

Modeling problems

You have a relation (result/2 is maybe not the best name), and this relation is supposed to model when decline and when offer should be true. Before reading your program, I prefer to ask Prolog:

?- result(X, decline), result(X, offer).
X in 11..20 ;
false.

So for the values from 11 up to 20, your relation is ambiguous. If you want to make a decision, then fix this relation first. Actually, I would start with

  • a better name for the relation that makes clear it is a relation
  • no imperative verbiage (like Input or imperatives)
  • a more compact formulation, you don't need so many (=)/2 goals in your program. Instead, you can write it like:
heigth_decision(I, decline) :-
   I #< 10.

Answers and success vs. solutions in CLP

And then there is another problem which is more fundamental. This is actually much more serious, since all the SO-answers given so far ignore this aspect entirely. It is about the notion of answers and success and on the other hand the notion of solutions.

When you ask a query in Prolog - what you get back is an answer. Such an answer might contain solutions, like the answer L = [_,_] which contains infinitely many solutions. Or an answer may contain exactly one solution like Decision = decline. But there is much more in between if you are using constraints like library(clpfd).

You can now get finitely many solutions:

?- abs(X) #< 3.
X in -2..2.

Or infinitely many:

?- X #> Y.
Y#=<X+ -1.

But you can get also exactly one solution, which does not look like one:

?- 2^X #= 1.
2^X#=1.

So, just to restate this: We have here exactly one solution in the integers, but for Prolog this is way too complex. What we got back was an answer that states: Yes that is all true, provided all this fine print is true.

Worse, sometimes we get answers back that do not contain any solution.

?- X^X#=0.
X^X#=0.

If Prolog would be smart enough, it would answer false. But it cannot be always that smart, simply because you can easily formulate undecidable problems. Such an answer is sometimes called inconsistency. The German notion Scheinl?sung (~fake solution, but with less negative connotation) conveys the idea a bit better.

So an answer may contain solutions, but some answers do not contain solutions at all. For this reason, the success of a goal cannot be taken as the existence of a solution! That is, all SO-answers suggesting some kind of commit as (;)/2 – if-then-else, once/1, or !/0 are all incorrect, if they take the success as a solution. To see this, try them with:

?- X^X#=0, result(X,decline).
X in 11..sup,
X^X#=0 ;
false.

?- X^X#=0, result(X,offer).
X in 0..20,
X^X#=0.

So how can you now be sure of anything?

  • You can rely on the failure of a goal.

  • You can try labeling/2, but this only works on finite domains.

  • You can use call_residue_vars/2 and copy_term/3 to determine if there are constraints "hanging around"

  • Unfortunately, you cannot entirely rely on SWI's toplevel which hides constraints that are unrelated to the variables in an answer. Only SICStus does display them correctly.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...