Clingo 5 to 6

The ASP syntax is mostly unchanged, but a few arithmetic and safety changes, plus a subtle semantic change, affect results. This note lists what to check and new features worth knowing.

The API changed more substantially. We do not discuss that here.

Changes that need attention

Arithmetic operators

Expression clingo 5 clingo 6 What changed

-a**b, ~a**b

-2**2 = 4

-2**2 = -4

** now binds tighter than unary - and ~ (the standard math reading -(a**b)). Write (-a)**b to keep the old grouping.

-5/3, -5\3

-1, -2 (truncate toward zero)

-2, 1 (floor toward -∞)

Integer division / and modulo \ now use floor semantics. Results differ only when exactly one operand is negative.

100000*100000

1410065408 (32-bit wraparound)

10000000000 (exact)

Integer arithmetic is now arbitrary-precision. Any encoding that relied on 32-bit wraparound will differ.

Safety of anonymous variables under negation

clingo 5 clingo 6

:- p(V,S), not q(V,S,_).

:- p(V,S), not q(V,S,*).

clingo 6 treats every anonymous variable _ like a fresh variable and then applies the ordinary safety rule: a variable must occur in a positive body literal that can bind it. A variable appearing only inside a not …​ literal has no such occurrence, so it is unsafe.

clingo 5 applies a special rule to anonymous variables in negative literals. It treats them like fresh nested existentially quantified variables applied to the atoms of literals.

The clingo 5 behaviour can be restored by passing option --project-anonymous to clingo 6. If backward compatibility is not required, the projection can be made explicit using not p(X,*).

Conditional literals

The semantics of conditional literals in clingo 6 changed slightly.

This change affects how global variables are computed in conditional literals and how pools are expanded. Since this is about semantic corner cases, it is unlikely to affect existing encodings. We illustrate the change with a simple example:

%%% OPTIONS: 0
{p(1..3)}.
h :- p(1..3): #true.

Here, clingo 5 derives h if at least one of p(1), p(2), or p(3) is true, while clingo 6 derives h only if all of them are true.

Furthermore, clingo 6 now treats variables that occur purely in conclusions of conditional literals as non-global variables. Thus, it rejects such programs as unsafe, while clingo 5 treats such variables as global.

New in clingo 6

These are additions. They do not affect existing encodings, but 5.8.2 users may want to adopt them.

Feature Example What it does

Format Strings

label(f"row {R+1} col {C+1}") :- cell(R,C).

Evaluation of expressions with strings. See Format Strings

#parts Directives

#parts base, check.

Select which #program parts to ground from within the source, not only via the --parts command-line option. See Program Parts.

Digit separators

p(1'000).

A ' groups digits in a decimal integer (in groups of three); 1'000 is 1000. See Integers.

String escapes

p("tab\there").

Basic clingo 5 escapes: \", \\, \n. Additional clingo 6 escapes: \t, \r, and \u{HEX} (Unicode). See Strings.

Projection *

h :- p(X,*), not q(X,*).

An explicit projection placeholder that can be used in all body literals. See Projection.

Sort Aggregates

s(X,Y) :- (X,Y) = #sort { Z: p(Z) }.

Aggregates to sort a set of terms. See Body Aggregates.