// Souffle - A Datalog Compiler
// Copyright (c) 2018, The Souffle Developers. All rights reserved
// Licensed under the Universal Permissive License v 1.0 as shown at:
// - https://opensource.org/licenses/UPL
// - <souffle root>/licenses/SOUFFLE-UPL.txt

// Tests the reduction of relations that appear only existentially -
// i.e. in the form r(_,...,_).

// Only appears existentially (proposition)
.decl a()
a() :- f(_,2).

// Only appears existentially (proposition)
// Means the second recursive rule will be deleted
.decl b()
b() :- !g(_).
b() :- b(), c(0,1,2), d(3), e(4), f(5,_), h(7).

// Only appears existentially
.decl c(x:number, y:number, z:number)
c(x,y,z) :- a(), e(x), f(y, z).

// Only appears existentially, except in b's recursive rule.
// Therefore, transformed if and only if b is transformed.
// But b is transformed, so this will be too.
.decl d(x:number)
d(x) :- e(x), b().
d(x+1) :- d(x), f(x,x), h(x), x < 100.

// Appears non-existentially in a non-recursive rule (c), so
// can never be transformed.
.decl e(x:number)
e(0).
e(x+1) :- e(x), x < 100.

// Appears non-existentially in a non-recursive rule (l), so
// can never be transformed.
.decl f(x:number, y:number)
f(0,1).
f(1,2).
f(2,4).
f(3,8).
f(x,x) :- f(0,x), l(x).

// Empty, so should not affect anything
.decl g(x:number)

// Appears non-existentially in b and d's recursive rules.
// Therefore, transformed if and only if b and d are both transformed.
// They are, so these will be too.
.decl h(x:number)
h(x) :- f(x,_).

// Appears non-existentially in an output relation, so can
// never be transformed.
.decl i(x:number)
i(0).

// Appears non-existentially in l's recursive rule, so can
// be transformed if and only if l can be transformed.
// l can't be transformed, so this can't be either.
.decl k(x:number)
k(1).

// Appears non-existentially in f's recursive rule, so can
// be transformed if and only if f can be transformed.
// f can't be transformed, so this can't be either.
.decl l(x:number)
l(x) :- f(_,x).
l(x) :- l(0), k(x).

// Output relations can never be transformed
.decl query(x:number)
query(x) :- a(), b(), c(_,_,_), d(_), e(_), f(_,_), !g(_), h(_), i(x), k(_), l(_).
.output query()
