# s(SCAP) minimum issue

in s(CASP) we can get the minimum of something by demanding there not to be something smaller, e.g.

``````min_rate(D) :-
rate(D),
not notmin(D).

notmin(D) :-
rate(D1),
D > D1.

rate(2).
rate(1).
rate(30).
``````

This works fine and produces a reasonable justification:

``````102 ?- ?++ min_rate(D).
D = 1,
% s(CASP) model
{ min_rate(1),    not notmin(1),  not rate(_A),   rate(1),        rate(2),        rate(30)
},
% s(CASP) justification
query ←
min_rate(1) ←
rate(1) ∧
not notmin(1) ←
not rate(_A) ∧
proved(rate(1)) ∧
1=<1 ∧
rate(2) ∧
1=<2 ∧
rate(30) ∧
1=<30,
_A ∉ [1,2,30] ;
false.
``````

But, if we add an extra argument, all goes wrong. This seems an issue with the forall implementation, but I have a hard time understanding the details. The new program is this and the correct answer should be `min_rate(30,5)`

``````min_rate(D,A) :-
rate(D,A),
not notmin(D,A).

notmin(D,A) :-
rate(D1,A1),
A/D > A1/D1.

rate(2,4).
rate(1,2).
rate(30,5).
``````

… But, this happens. Somehow it doesn’t seem to take the rate(30,5) into consideration!?

``````103 ?- ?++ min_rate(A,D).
A = 2,
D = 4,
% s(CASP) model
{ min_rate(2,4),    not rate(_A,4),   rate(1,2),        rate(2,4),
not notmin(2,4),  not rate(1,_B),   not rate(2,_C),   not rate(30,4)
},
% s(CASP) justification
query ←
min_rate(2,4) ←
rate(2,4) ∧
not notmin(2,4) ←
not rate(1,_B) ∧
rate(1,2) ∧
4/2=<2/1 ∧
rate(2,4) ∧
4/2=<4/2 ∧
not rate(2,_C) ∧
not rate(_A,4) ∧
not rate(30,4),
_B ∉ [2],
_C ∉ [2,4],
_A ∉ [1,2,30]
``````
Here is the detailed trace
``````104 ?- ?+++ min_rate(A,D).
A = 2,
D = 4,
% s(CASP) model
{ min_rate(2,4),    not rate(_A,4),   rate(1,2),        rate(2,4),
not notmin(2,4),  not rate(1,_B),   not rate(2,_C),   not rate(30,4)
},
% s(CASP) justification
query ←
min_rate(2,4) ←
rate(2,4) ∧
not notmin(2,4) ←
not o_user:notmin_1(2,4) ←
forall(_D,forall(_E,not'o_user:notmin_1_vh4'(2,4,_D,_E))) ←
not o_user:notmin_1_vh4(2,4,1,_B) ←
not rate(1,_B) ←
not o_user:rate_1(1,_B) ←
1\=2 ∧
not o_user:rate_2(1,_B) ←
1=1 ∧
_B\=2 ∧
not o_user:rate_3(1,_B) ←
1\=30 ∧
not o_user:notmin_1_vh4(2,4,1,2) ←
rate(1,2) ∧
4/2=<2/1 ∧
not o_user:notmin_1_vh4(2,4,2,4) ←
rate(2,4) ∧
4/2=<4/2 ∧
not o_user:notmin_1_vh4(2,4,2,_C) ←
not rate(2,_C) ←
not o_user:rate_1(2,_C) ←
2=2 ∧
_C\=4 ∧
not o_user:rate_2(2,_C) ←
2\=1 ∧
not o_user:rate_3(2,_C) ←
2\=30 ∧
not o_user:notmin_1_vh4(2,4,_A,4) ←
not rate(_A,4) ←
not o_user:rate_1(_A,4) ←
_A\=2 ∧
not o_user:rate_2(_A,4) ←
_A\=1 ∧
not o_user:rate_3(_A,4) ←
_A\=30 ∧
not o_user:notmin_1_vh4(2,4,30,4) ←
not rate(30,4) ←
not o_user:rate_1(30,4) ←
30\=2 ∧
not o_user:rate_2(30,4) ←
30\=1 ∧
not o_user:rate_3(30,4) ←
30=30 ∧
4\=5 ∧
o_nmr_check,
_B ∉ [2],
_C ∉ [2,4],
_A ∉ [1,2,30]
``````
And the dual program
``````106 ?- scasp_show(min_rate(A,D), code(duals(true))).
% User Predicates

min_rate(A, B) :-
rate(A, B),
not notmin(A, B).

notmin(A, B) :-
rate(C, D),
B/A>D/C.

rate(2, 4).
rate(1, 2).
rate(30, 5).

% Dual Rules

not notmin(A, B) :-
not o_user:notmin_1(A, B).

not o_user:notmin_1(A, B) :-
forall(C,
forall(D,
not'o_user:notmin_1_vh4'(A, B, C, D))).

not o_user:notmin_1_vh4(_, _, A, B) :-
not rate(A, B).
not o_user:notmin_1_vh4(A, B, C, D) :-
rate(C, D),
B/A=<D/C.

not rate(A, B) :-
not o_user:rate_1(A, B),
not o_user:rate_2(A, B),
not o_user:rate_3(A, B).

not o_user:rate_1(A, _) :-
A\=2.
not o_user:rate_1(A, B) :-
A=2,
B\=4.

not o_user:rate_2(A, _) :-
A\=1.
not o_user:rate_2(A, B) :-
A=1,
B\=2.

not o_user:rate_3(A, _) :-
A\=30.
not o_user:rate_3(A, B) :-
A=30,
B\=5.

not min_rate(A, B) :-
not o_user:min_rate_1(A, B).

not o_user:min_rate_1(A, B) :-
not rate(A, B).
not o_user:min_rate_1(A, B) :-
rate(A, B),
notmin(A, B).
true.
``````

The behavior is consistent with the Ciao version. Can some scasper explain this in human terms Maybe @Xuaco ?

Hi Jan,
The error is due to the implementation of c_forall/2.
Using the --prev_forall flag the behavior is as expected:

scasp --prev_forall jan.pl
% QUERY:?- min_rate(D,A).

Hi Joaquin, Thanks. Only `--prev_forall` causes other issues in our code We now worked around it using findall/3 and then take the minimum of the list.