// Souffle - A Datalog Compiler
// Copyright (c) 2016, 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

//
// Duplicates (Semantic)
//
// This test case may be used to check if relations that are semantic
// equivalent are treated as such by the final RAM program.
// Note that '///' denotes a special comment; if the statement following it
// is a 'yes' then the relation should be in the final program, whereas if
// it is a 'no' then the relation should be treated as a duplicate and elim-
// inated from the final RAM program.
//

// Symbols

.decl SymbolA(x:symbol, y:symbol)
.output SymbolA()
.decl SymbolB(x:symbol, y:symbol)
.decl SymbolC(x:symbol, y:symbol)
.decl SymbolD(x:symbol, y:symbol)
.input SymbolD()

// Symbol B

// original

SymbolB("0", "1"). /// yes
SymbolB("1", "0"). /// yes
SymbolB("0", "0"). /// yes
SymbolB("1", "1"). /// yes

// Symbol C

// same as other

SymbolC("0", "1"). /// yes
SymbolC("1", "0"). /// yes
SymbolC("0", "0"). /// yes
SymbolC("1", "1"). /// yes

// original

SymbolC("1", "2"). /// yes
SymbolC("2", "1"). /// yes
SymbolC("1", "1"). /// no
SymbolC("2", "2"). /// yes

// Symbol A

// original

SymbolA(x, x) :- SymbolB(x, x). /// yes
SymbolA(x, x) :- SymbolC(x, x). /// yes
SymbolA(x, x) :- SymbolD(x, x). /// yes

SymbolA(x, y) :- SymbolB(x, y). /// yes
SymbolA(x, y) :- SymbolC(x, y). /// yes
SymbolA(x, y) :- SymbolD(x, y). /// yes

SymbolA(x, y) :- SymbolB(x, y), SymbolC(x, y). /// yes
SymbolA(x, y) :- SymbolC(x, y), SymbolD(x, y). /// yes
SymbolA(x, y) :- SymbolD(x, y), SymbolB(x, y). /// yes

SymbolA(x, y) :- SymbolC(x, y), SymbolB(x, y). /// no
SymbolA(x, y) :- SymbolD(x, y), SymbolC(x, y). /// no
SymbolA(x, y) :- SymbolB(x, y), SymbolD(x, y). /// no

SymbolA(x, z) :- SymbolB(x, y), SymbolC(y, z). /// yes
SymbolA(x, z) :- SymbolC(x, y), SymbolD(y, z). /// yes
SymbolA(x, z) :- SymbolD(x, y), SymbolB(y, z). /// yes

SymbolA(x, z) :- SymbolC(x, y), SymbolB(y, z). /// yes
SymbolA(x, z) :- SymbolD(x, y), SymbolC(y, z). /// yes
SymbolA(x, z) :- SymbolB(x, y), SymbolD(y, z). /// yes

// substituted

SymbolA(a, a) :- SymbolB(a, a). /// no
SymbolA(a, a) :- SymbolC(a, a). /// no
SymbolA(a, a) :- SymbolD(a, a). /// no

SymbolA(a, b) :- SymbolB(a, b). /// no
SymbolA(a, b) :- SymbolC(a, b). /// no
SymbolA(a, b) :- SymbolD(a, b). /// no

SymbolA(a, b) :- SymbolB(a, b), SymbolC(a, b). /// no
SymbolA(a, b) :- SymbolC(a, b), SymbolD(a, b). /// no
SymbolA(a, b) :- SymbolD(a, b), SymbolB(a, b). /// no

SymbolA(a, b) :- SymbolC(a, b), SymbolB(a, b). /// no
SymbolA(a, b) :- SymbolD(a, b), SymbolC(a, b). /// no
SymbolA(a, b) :- SymbolB(a, b), SymbolD(a, b). /// no

SymbolA(a, c) :- SymbolB(a, b), SymbolC(b, c). /// no
SymbolA(a, c) :- SymbolC(a, b), SymbolD(b, c). /// no
SymbolA(a, c) :- SymbolD(a, b), SymbolB(b, c). /// no

SymbolA(a, c) :- SymbolC(a, b), SymbolB(b, c). /// no
SymbolA(a, c) :- SymbolD(a, b), SymbolC(b, c). /// no
SymbolA(a, c) :- SymbolB(a, b), SymbolD(b, c). /// no

// Symbols

.decl NumberA(x:number, y:number)
.output NumberA()
.decl NumberB(x:number, y:number)
.decl NumberC(x:number, y:number)
.decl NumberD(x:number, y:number)
.input NumberD()

// Number B

// original

NumberB(0, 1). /// yes
NumberB(1, 0). /// yes
NumberB(0, 0). /// yes
NumberB(1, 1). /// yes

// Number C

// same as other

NumberC(0, 1). /// yes
NumberC(1, 0). /// yes
NumberC(0, 0). /// yes
NumberC(1, 1). /// yes

// original

NumberC(1, 2). /// yes
NumberC(2, 1). /// yes
NumberC(1, 1). /// no
NumberC(2, 2). /// yes

// Number A

// original

NumberA(x, x) :- NumberB(x, x). /// yes
NumberA(x, x) :- NumberC(x, x). /// yes
NumberA(x, x) :- NumberD(x, x). /// yes

NumberA(x, y) :- NumberB(x, y). /// yes
NumberA(x, y) :- NumberC(x, y). /// yes
NumberA(x, y) :- NumberD(x, y). /// yes

NumberA(x, y) :- NumberB(x, y), NumberC(x, y). /// yes
NumberA(x, y) :- NumberC(x, y), NumberD(x, y). /// yes
NumberA(x, y) :- NumberD(x, y), NumberB(x, y). /// yes

NumberA(x, y) :- NumberC(x, y), NumberB(x, y). /// no
NumberA(x, y) :- NumberD(x, y), NumberC(x, y). /// no
NumberA(x, y) :- NumberB(x, y), NumberD(x, y). /// no

NumberA(x, z) :- NumberB(x, y), NumberC(y, z). /// yes
NumberA(x, z) :- NumberC(x, y), NumberD(y, z). /// yes
NumberA(x, z) :- NumberD(x, y), NumberB(y, z). /// yes

NumberA(x, z) :- NumberC(x, y), NumberB(y, z). /// yes
NumberA(x, z) :- NumberD(x, y), NumberC(y, z). /// yes
NumberA(x, z) :- NumberB(x, y), NumberD(y, z). /// yes

// substituted

NumberA(a, a) :- NumberB(a, a). /// no
NumberA(a, a) :- NumberC(a, a). /// no
NumberA(a, a) :- NumberD(a, a). /// no

NumberA(a, b) :- NumberB(a, b). /// no
NumberA(a, b) :- NumberC(a, b). /// no
NumberA(a, b) :- NumberD(a, b). /// no

NumberA(a, b) :- NumberB(a, b), NumberC(a, b). /// no
NumberA(a, b) :- NumberC(a, b), NumberD(a, b). /// no
NumberA(a, b) :- NumberD(a, b), NumberB(a, b). /// no

NumberA(a, b) :- NumberC(a, b), NumberB(a, b). /// no
NumberA(a, b) :- NumberD(a, b), NumberC(a, b). /// no
NumberA(a, b) :- NumberB(a, b), NumberD(a, b). /// no

NumberA(a, c) :- NumberB(a, b), NumberC(b, c). /// no
NumberA(a, c) :- NumberC(a, b), NumberD(b, c). /// no
NumberA(a, c) :- NumberD(a, b), NumberB(b, c). /// no

NumberA(a, c) :- NumberC(a, b), NumberB(b, c). /// no
NumberA(a, c) :- NumberD(a, b), NumberC(b, c). /// no
NumberA(a, c) :- NumberB(a, b), NumberD(b, c). /// no
