clingo

How to encode normalized(A,B) properly?


I am using clingo to solve a homework problem and stumbled upon something I can't explain:

normalized(0,0).
normalized(A,1) :-
    A != 0.

normalized(10).

In my opinion, normalized should be 0 when the first parameter is 0 or 1 in every other case.

Running clingo on that, however, produces the following:

test.pl:2:1-3:12: error: unsafe variables in:
  normalized(A,1):-[#inc_base];A!=0.
test.pl:2:12-13: note: 'A' is unsafe

Why is A unsafe here? According to Programming with CLINGO

Some error messages say that the program has “unsafe variables.” Such a message usually indicates that the head of one of the rules includes a variable that does not occur in its body; stable models of such programs may be infinite.

But in this example A is present in the body.

Will clingo produce an infinite set consisting of answers for all numbers here?

I tried adding number(_) around the first parameter and pattern matching on it to avoid this situation but with the same result:

normalized(number(0),0).
normalized(A,1) :-
    A=number(B),
    B != 0.

normalized(number(10)).

How would I write normalized properly?


Solution

  • With "variables occuring in the body" actually means in a positive literal in the body. I can recommend the official guide: https://github.com/potassco/guide/releases/

    The second thing, ASP is not prolog. Your rules get grounded, i.e. each first order variable is replaced with its domain. In your case A has no domain. What would be the expected outcome of your program ?

    normalized(12351,1).
    normalized(my_mom,1).
    

    would all be valid replacements for A so you create an infinite program. This is why 'A' has to be bounded by a domain. For example:

    dom(a). dom(b). dom(c). dom(100).
    normalized(0,0).
    normalized(A,1) :- dom(A).
    

    would produce

    normalize(0,0).
    normalize(a,1).
    normalize(b,1).
    normalize(c,1).
    normalize(100,1).
    

    Also note that there is no such thing as number/1. ASP is a typefree language.

    Also,

    normalized(10).
    

    is a different predicate with only one parameter, I do not know how this will fit in your program.

    Maybe your are looking for something like this:

    dom(1..100).
    normalize(0,0).
    normalize(X,1) :- dom(X).
    
    foo(43).
    bar(Y) :- normalize(X,Y), foo(X).