test(simple_sat1, [nondet]) :-
init_idl_solver(GraphMut),
% a-c<=1 & c-b<=-3
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(a),integer,[]),b(identifier(c),integer,[])),integer,[]),b(integer(1),integer,[])),pred,[])),
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(c),integer,[]),b(identifier(b),integer,[])),integer,[]),b(integer(-3),integer,[])),pred,[])),
!,
get_solver_result(GraphMut, Res),
ground(Res),
Res = solution(Bindings),
member(binding(a,int(-2),'-2'), Bindings),
member(binding(b,int(0),'0'), Bindings),
member(binding(c,int(-3),'-3'), Bindings),
\+ get_unsat_core(_).
test(simple_sat2, [nondet]) :-
init_idl_solver(GraphMut),
% a-c<=-1 & c-b<=3
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(a),integer,[]),b(identifier(c),integer,[])),integer,[]),b(integer(-1),integer,[])),pred,[])),
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(c),integer,[]),b(identifier(b),integer,[])),integer,[]),b(integer(3),integer,[])),pred,[])),
!,
get_solver_result(GraphMut, Res),
ground(Res),
Res = solution(Bindings),
member(binding(a,int(-1),'-1'), Bindings),
member(binding(b,int(0),'0'), Bindings),
member(binding(c,int(0),'0'), Bindings),
\+ get_unsat_core(_).
test(simple_sat3, [nondet]) :-
init_idl_solver(GraphMut),
% a-c<=1 & c-b<=3
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(a),integer,[]),b(identifier(c),integer,[])),integer,[]),b(integer(1),integer,[])),pred,[])),
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(c),integer,[]),b(identifier(b),integer,[])),integer,[]),b(integer(3),integer,[])),pred,[])),
!,
get_solver_result(GraphMut, Res),
ground(Res),
Res = solution(Bindings),
member(binding(a,int(0),'0'), Bindings),
member(binding(b,int(0),'0'), Bindings),
member(binding(c,int(0),'0'), Bindings),
\+ get_unsat_core(_).
test(simple_sat4, [nondet]) :-
init_idl_solver(GraphMut),
% a-1<=1 & 3<=b & 2<=b-1
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(a),integer,[]),b(integer(1),integer,[])),integer,[]),b(integer(1),integer,[])),pred,[])),
register_constraint(GraphMut, b(less_equal(b(integer(3),integer,[]),b(identifier(b),integer,[])),pred,[])),
register_constraint(GraphMut, b(less_equal(b(integer(2),integer,[]),b(minus(b(identifier(b),integer,[]),b(integer(1),integer,[])),integer,[])),pred,[])),
!,
get_solver_result(GraphMut, Res),
ground(Res),
Res = solution(Bindings),
member(binding(a,int(2),'2'), Bindings),
member(binding(b,int(3),'3'), Bindings),
\+ get_unsat_core(_).
test(simple_sat_introduce_zero, [nondet]) :-
init_idl_solver(GraphMut),
% a-b<=-1 & a<=-1
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(a),integer,[]),b(identifier(b),integer,[])),integer,[]),b(integer(-1),integer,[])),pred,[])),
register_constraint(GraphMut, b(less_equal(b(identifier(a),integer,[]),b(integer(-1),integer,[])),pred,[])),
!,
get_solver_result(GraphMut, Res),
ground(Res),
Res = solution(Bindings),
member(binding(a,int(-1),'-1'), Bindings),
member(binding(b,int(0),'0'), Bindings),
\+ get_unsat_core(_).
test(simple_sat_rewrite_equality, [nondet]) :-
init_idl_solver(GraphMut),
% a-b<=-1 & a=1
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(a),integer,[]),b(identifier(b),integer,[])),integer,[]),b(integer(-1),integer,[])),pred,[])),
register_constraint(GraphMut, b(equal(b(identifier(a),integer,[]),b(integer(1),integer,[])),pred,[])),
!,
get_solver_result(GraphMut, Res),
Res = solution(Bindings),
member(binding(a,int(1),'1'), Bindings),
member(binding(b,int(2),'2'), Bindings),
\+ get_unsat_core(_).
test(simple_sat_all_solutions_single_var, [nondet]) :-
init_idl_solver(GraphMut),
% all solutions for x>0 & x<5
register_constraint(GraphMut, b(greater(b(identifier(x),integer,[]),b(integer(0),integer,[])),pred,[])),
register_constraint(GraphMut, b(less(b(identifier(x),integer,[]),b(integer(10),integer,[])),pred,[])),
!,
findall(Res, get_all_solutions_on_bt(GraphMut, Res), SolverResults),
SolverResults == [solution([binding(x,int(1),'1')]),solution([binding(x,int(2),'2')]),solution([binding(x,int(3),'3')]),solution([binding(x,int(4),'4')]),solution([binding(x,int(5),'5')]),solution([binding(x,int(6),'6')]),solution([binding(x,int(7),'7')]),solution([binding(x,int(8),'8')]),solution([binding(x,int(9),'9')])].
test(simple_sat_all_solutions_two_vars, [nondet]) :-
init_idl_solver(GraphMut),
% all solutions for x>0 & x<4 & y>0 & y<4
register_constraint(GraphMut, b(greater(b(identifier(x),integer,[]),b(integer(0),integer,[])),pred,[])),
register_constraint(GraphMut, b(less(b(identifier(x),integer,[]),b(integer(4),integer,[])),pred,[])),
register_constraint(GraphMut, b(greater(b(identifier(y),integer,[]),b(integer(0),integer,[])),pred,[])),
register_constraint(GraphMut, b(less(b(identifier(y),integer,[]),b(integer(4),integer,[])),pred,[])),
!,
findall(Res, get_all_solutions_on_bt(GraphMut, Res), SolverResults),
length(SolverResults, Length),
Length == 9,
SolverResults == [solution([binding(y,int(1),'1'),binding(x,int(1),'1')]),solution([binding(y,int(2),'2'),binding(x,int(2),'2')]),solution([binding(y,int(3),'3'),binding(x,int(3),'3')]),solution([binding(x,int(2),'2'),binding(y,int(3),'3')]),solution([binding(x,int(1),'1'),binding(y,int(3),'3')]),solution([binding(x,int(1),'1'),binding(y,int(2),'2')]),solution([binding(y,int(2),'2'),binding(x,int(3),'3')]),solution([binding(y,int(1),'1'),binding(x,int(2),'2')]),solution([binding(y,int(1),'1'),binding(x,int(3),'3')])].
test(simple_sat_all_solutions_two_vars_subtraction, [nondet]) :-
init_idl_solver(GraphMut),
% all solutions for x>0 & x<10 & y>0 & y<10 & x-y>5
register_constraint(GraphMut, b(greater(b(identifier(x),integer,[]),b(integer(0),integer,[])),pred,[])),
register_constraint(GraphMut, b(less(b(identifier(x),integer,[]),b(integer(10),integer,[])),pred,[])),
register_constraint(GraphMut, b(greater(b(identifier(y),integer,[]),b(integer(0),integer,[])),pred,[])),
register_constraint(GraphMut, b(less(b(identifier(y),integer,[]),b(integer(10),integer,[])),pred,[])),
register_constraint(GraphMut, b(greater(b(minus(b(identifier(x),integer,[]),b(identifier(y),integer,[])),integer,[]),b(integer(5),integer,[])),pred,[])),
!,
findall(Res, get_all_solutions_on_bt(GraphMut, Res), SolverResults),
length(SolverResults, Length),
Length == 6,
SolverResults == [solution([binding(y,int(1),'1'),binding(x,int(7),'7')]),solution([binding(y,int(2),'2'),binding(x,int(8),'8')]),solution([binding(y,int(3),'3'),binding(x,int(9),'9')]),solution([binding(y,int(2),'2'),binding(x,int(9),'9')]),solution([binding(y,int(1),'1'),binding(x,int(8),'8')]),solution([binding(y,int(1),'1'),binding(x,int(9),'9')])].
test(simple_unsat1, [nondet]) :-
init_idl_solver(GraphMut),
% a-c<=1 & c-b<=-3 & b-a<=1
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(a),integer,[]),b(identifier(c),integer,[])),integer,[]),b(integer(1),integer,[])),pred,[])),
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(c),integer,[]),b(identifier(b),integer,[])),integer,[]),b(integer(-3),integer,[])),pred,[])),
\+ register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(b),integer,[]),b(identifier(a),integer,[])),integer,[]),b(integer(1),integer,[])),pred,[])),
!,
get_solver_result(GraphMut, Res),
Res == contradiction_found,
get_unsat_core(UnsatCore),
UnsatCore = b(conjunct(b(conjunct(b(less_equal(b(minus(b(identifier(b),integer,_),b(identifier(a),integer,_)),integer,_),b(integer(1),integer,_)),pred,_),b(less_equal(b(minus(b(identifier(a),integer,_),b(identifier(c),integer,_)),integer,_),b(integer(1),integer,_)),pred,_)),pred,_),b(less_equal(b(minus(b(identifier(c),integer,_),b(identifier(b),integer,_)),integer,_),b(integer(-3),integer,_)),pred,_)),pred,_).
test(simple_unsat2, [nondet]) :-
init_idl_solver(GraphMut),
% c-c<=1 & a-c<=1 & c-b<=-3 & b-a<=1
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(c),integer,[]),b(identifier(c),integer,[])),integer,[]),b(integer(1),integer,[])),pred,[])),
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(a),integer,[]),b(identifier(c),integer,[])),integer,[]),b(integer(1),integer,[])),pred,[])),
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(c),integer,[]),b(identifier(b),integer,[])),integer,[]),b(integer(-3),integer,[])),pred,[])),
\+ register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(b),integer,[]),b(identifier(a),integer,[])),integer,[]),b(integer(1),integer,[])),pred,[])),
!,
get_solver_result(GraphMut, Res),
Res == contradiction_found,
get_unsat_core(UnsatCore),
% c-c<=1 is not part of the unsat core
UnsatCore = b(conjunct(b(conjunct(b(less_equal(b(minus(b(identifier(b),integer,_),b(identifier(a),integer,_)),integer,_),b(integer(1),integer,_)),pred,_),b(less_equal(b(minus(b(identifier(a),integer,_),b(identifier(c),integer,_)),integer,_),b(integer(1),integer,_)),pred,_)),pred,_),b(less_equal(b(minus(b(identifier(c),integer,_),b(identifier(b),integer,_)),integer,_),b(integer(-3),integer,_)),pred,_)),pred,_).
test(simple_unsat_negation, [nondet]) :-
init_idl_solver(GraphMut),
% a-b<=-1 & a<=-1 & b<=10 & not(a<=-1)
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(a),integer,[]),b(identifier(b),integer,[])),integer,[]),b(integer(-1),integer,[])),pred,[])),
register_constraint(GraphMut, b(less_equal(b(identifier(a),integer,[]),b(integer(-1),integer,[])),pred,[])),
register_constraint(GraphMut, b(less_equal(b(identifier(b),integer,[]),b(integer(10),integer,[])),pred,[])),
\+ register_constraint(GraphMut, b(negation(b(less_equal(b(identifier(a),integer,[]),b(integer(-1),integer,[])),pred,[])),pred,[])),
!,
get_solver_result(GraphMut, Res),
Res = contradiction_found,
get_unsat_core(UnsatCore),
% not(a<=-1) & a<=-1
UnsatCore = b(conjunct(b(negation(b(less_equal(b(identifier(a),integer,_),b(integer(-1),integer,_)),pred,_)),pred,_),b(less_equal(b(identifier(a),integer,_),b(integer(-1),integer,_)),pred,_)),pred,_).
test(simple_unsat_negation_rewrite_beforehand, [nondet]) :-
init_idl_solver(GraphMut),
% we receive the same unsat core containing the original constraints when rewriting constraints before registering them
% a-b<=-1 & a<=-1 & b<=10 & not(a<=-1)
C2 = b(less_equal(b(identifier(a),integer,[]),b(integer(-1),integer,[])),pred,[]),
C3 = b(less_equal(b(identifier(b),integer,[]),b(integer(10),integer,[])),pred,[]),
C4 = b(negation(b(less_equal(b(identifier(a),integer,[]),b(integer(-1),integer,[])),pred,[])),pred,[]),
rewrite_to_idl(C2, C2IdlConjList),
rewrite_to_idl(C3, C3IdlConjList),
rewrite_to_idl(C4, C4IdlConjList),
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(a),integer,[]),b(identifier(b),integer,[])),integer,[]),b(integer(-1),integer,[])),pred,[])),
register_constraints(GraphMut, C2IdlConjList),
register_constraints(GraphMut, C3IdlConjList),
\+ register_constraints(GraphMut, C4IdlConjList),
!,
get_solver_result(GraphMut, Res),
Res = contradiction_found,
get_unsat_core(UnsatCore),
% not(a<=-1) & a<=-1
UnsatCore = b(conjunct(b(negation(b(less_equal(b(identifier(a),integer,_),b(integer(-1),integer,_)),pred,_)),pred,_),b(less_equal(b(identifier(a),integer,_),b(integer(-1),integer,_)),pred,_)),pred,_).
test(register_constraint_undone_on_bt1, []) :-
init_idl_solver(GraphMut),
empty_graph_state(GraphMut),
Constraint = b(less_equal(b(minus(b(identifier(a),integer,[]),b(identifier(b),integer,[])),integer,[]),b(integer(1),integer,[])),pred,[]),
( register_constraint(GraphMut, Constraint),
get_mutable(graph(nodes(Nodes),edges(Edges),shortest_paths(SPs)), GraphMut),
memberchk(a, Nodes),
memberchk(b, Nodes),
memberchk(b:[(b,1,a,_)], Edges),
memberchk((a,0), SPs),
memberchk((b,0), SPs),
constraint_store(b,a,Constraint),
\+ negative_weight,
\+ contains_zero,
fail
; empty_graph_state(GraphMut)
).
test(register_constraint_undone_on_bt2, []) :-
init_idl_solver(GraphMut),
empty_graph_state(GraphMut),
Constraint = b(less_equal(b(identifier(a),integer,[]),b(integer(-1),integer,[])),pred,[]),
( register_constraint(GraphMut, Constraint),
get_mutable(graph(nodes(Nodes),edges(Edges),shortest_paths(SPs)), GraphMut),
memberchk(a, Nodes),
memberchk('_zero', Nodes),
memberchk('_zero':[('_zero',-1,a,_)], Edges),
memberchk((a,-1), SPs),
memberchk(('_zero',0), SPs),
constraint_store('_zero',a,b(less_equal(b(minus(b(identifier(a),integer,[]),b(identifier('_zero'),integer,[])),integer,[]),b(integer(-1),integer,[])),pred,[])),
negative_weight,
contains_zero,
fail
; empty_graph_state(GraphMut)
).
test(register_constraint_overwrite_old, [nondet]) :-
init_idl_solver(GraphMut),
empty_graph_state(GraphMut),
% a-b<=2 is replaced by a-b<=1
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(a),integer,[]),b(identifier(b),integer,[])),integer,[]),b(integer(2),integer,[])),pred,[])),
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(a),integer,[]),b(identifier(b),integer,[])),integer,[]),b(integer(1),integer,[])),pred,[])),
get_mutable(graph(nodes(_),edges(Edges),shortest_paths(SPs)), GraphMut),
memberchk('b':[('b',1,a,_)], Edges),
memberchk((a,0), SPs),
memberchk((b,0), SPs).
test(register_constraint_overwrite_old_undone_on_bt, [nondet]) :-
init_idl_solver(GraphMut),
empty_graph_state(GraphMut),
% a-b<=2 is replaced by a-b<=1 but effect is undone on backtracking
register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(a),integer,[]),b(identifier(b),integer,[])),integer,[]),b(integer(2),integer,[])),pred,[])),
( register_constraint(GraphMut, b(less_equal(b(minus(b(identifier(a),integer,[]),b(identifier(b),integer,[])),integer,[]),b(integer(1),integer,[])),pred,[])),
fail
; get_mutable(graph(nodes(_),edges(Edges),shortest_paths(SPs)), GraphMut),
memberchk('b':[('b',2,a,_)], Edges),
memberchk((a,0), SPs),
memberchk((b,0), SPs)
).