Search code examples
prologlogic

Is Prolog really based on the closed-world assumption?


Under the closed-world assumption,

what is not currently known to be true, is false

Prolog's semantics is often said to follow the closed-world assumption, for example, here:

Prolog is based on closed world assumption (CWA) -- that is, if a proposition is not in the fact database and not derivable from the fact database, then it is not true.

However, it doesn't quite behave this way. Under CWA, I'd expect

?- a.
false.

But instead, in SWI-Prolog, I get:

?- a.
ERROR: Undefined procedure: a/0 (DWIM could not correct goal)

Why is that? Is it wrong to say that Prolog is based on CWA?


Solution

  • When talking about Closed-World Assumption (CWA) in the context of Prolog, a distinction must be made between unknown predicates versus predicates known to the (runtime) system. In both cases, predicates with or without clauses.

    Calling an unknown predicate will, by default, raise a predicate existence error. There's a standard flag, unknown (https://www.swi-prolog.org/pldoc/man?section=flags#flag:unknown), whose default value is error, that can be set to fail (or warning). That will give you the behavior that you're apparently looking for. Still, I strongly advise you to keep the flag set to its default value of error, as it allows easier detection of programming mistakes (e.g. typos in predicate names or arity).

    What makes a predicate known to the runtime? Predicate directives or predicate clauses. The most familiar example is the dynamic/1 directive. If your code consists solely of the following text:

    :- dynamic(foo/1).
    

    Then, after compiling and loading, you can expect:

    ?- foo(_).
    no.
    

    But other directives have the same effect (e.g. multifile/1 and discontiguous/1, assuming that is a standard conforming Prolog implementation!).

    Thus, for known predicates, the interpretation of CWA in Prolog is simple: what we cannot prove to be true, is false. I.e. negation by failure, which is not the same as logical negation. The name Prolog comes from programming in logic but Prolog also aims to be a pragmatic and practical programming language.

    What's lacking in Prolog (and is provided by e.g. Logtalk) is being able to declare a predicate without being forced to declare it as dynamic, or multifile, or ... or requiring providing clauses for it (see e.g. this example). This provides simpler and clearer CWA semantics: calling a declared predicate with no clauses fails (without the need of messing with the problematic unknown flag); calling a non-declared predicate raises a predicate existence error.

    Hope this helps. Searching for negation as failure should provide further clarification.