How to express the idea that a fact is "wrong"?

Hello everyone,

I’m a complete beginner in the domain of logic programming, so probably my question will sound weird for experts. However, I’m interested in how this idea would be expressed in idiomatic Prolog.

Let’s assume, I define some facts like:

f(a, b).
f(a, c).
f(a, d).
f(a, e).

If I get the semantic model of Prolog right, facts are true by their very definition. Now let’s assume, I want to model some situation, where the combinations (a, d) or (a, e) are not allowed, since, for whatever reason, only a and b / a and c are compatible. How can I find out, that f(a, d) and f(a, e) are stated erroneously?

Coming mainly from statically typed functional languages, I’m probably too much thinking about value range limitations strictly enforced by types to find an idiomatic solution in Prolog. Or probably the idea of “wrong facts” cannot be expressed in Prolog?

Thanks very much in advance for any hints!

Kind regards,

Thomas

1 Like

In Prolog, the absence of a fact makes it false. So, adding this to your list wouldn’t make change:

f(a,d) :- false. % Effectively a no-op because f(a,d) is already asserted.
f(a,e) :- false. % Same, for f(a,e).

(Well, you could do something with “cut” and ordering the “false” rules first. But that’s very hack-y and error-prone.)

You could add some other validation code, such as:

valid_facts :-
    \+ f(a,d),
    \+ f(a,e).

Beyond this, you’re in the world of non-monotonic logics, which are interesting but not trivial.

First, facts are never taken to be wrong.

However the solution to your problem lies in your own description,

I want to model some situation

So you create a model and don’t let the system direct access to the facts. Instead use the model to query the information.

In this case you just need to add some predicates like

compatible(f(a,b),f(a,c)).

and query like this


?- compatible(f(a,b),f(a,c)).
true.

?- compatible(f(a,d),f(a,e)).
false.

?- compatible(f(a,b),f(a,d)).
false.

The problem with your example as given is that the individual facts are not needed, only if they are compatible.


One nice ability of Prolog using Closed-world assumption is that if the predicates are written correctly you can use the most general query to get all the results.

?- compatible(A,B).
A = f(a, b),
B = f(a, c).

Now the problem with this is that one would typically also want

A = f(a, c),
B = f(a, b).

in the result. Resolving that is an entirely different problem that can be solved, but not as easy as adding

compatible(A,B) :-
    compatible(B,A).
1 Like

Standard Prolog implements negation as failure. I.e. what cannot be proved to be true, is assumed to be false. This semantics can be regarded as the implementation counterpart of the Closed World Assumption (see e.g. https://en.wikipedia.org/wiki/Closed-world_assumption).

There is another easy way you can do it:

f(a,b,allowed).
f(a,c,allowed).
f(a,d,not_allowed).
f(a,e,not_allowed).

Then you could have predicates like:

allowed(f(X,Y)) :-
    f(X,Y,allowed).

not_allowed(f(X,Y)) :-
    f(X,Y,not_allowed).

And you could query:

1 ?- allowed(What).
What = f(a, b) ;
What = f(a, c).

2 ?- not_allowed(What).
What = f(a, d) ;
What = f(a, e).

Thank you very much for your interesting hints. They seem to be quite helpful, and I’ll now play around with them a little bit to find out, how I can tweak them to match my situation as good as possible.

I really like the idea of LP but I feel, I still need to deepen my intuition of the appropriate problem solving approaches…

You should be aware that Prolog has a relational data model at heart. So, just ?- retract( f(a,d) ), retract( f(a,e) ). when appropriate for your model. Code is data… more or less…