I want to count the number of successes AND failures for a predicate that doesn't have any arguments. For simplicity, the predicate I want to test is test_arith/0. test_arith/0 has 3 tests for is/2 (again, for simplicity. I really want to test more complicated predicates that I'm writing, but those details would be a distraction for this question.) (P.S. I saw the other question about counting the number times a predicate is true. I want to count both the successes and the failures in a single pass. I don't want to have to run the real predicates more than once per test case because some of them take a long time to execute. aggregate/3 and aggregate_all seem to be single-minded as well, taking only the successes.)
test_arith(Passes, Failures) :-
findall(P-F, (test_arith->(P=1,F=0);(P=0,F=1)), Scores),
summarize_scores(Scores, 0, 0, Passes, Failures).
test_arith :- 5 is 3 +2. % Test #1: Should pass
test_arith :- 5 is 2 +2. % Test #2: Should fail
test_arith :- 4 is 2 +2. % Test #3: Should pass
summarize_scores([], Passes, Failures, Passes, Failures).
summarize_scores([P-F|Scores], Passes_SF, Failures_SF, Passes, Failures) :-
Next_Passes is P + Passes_SF,
Next_Failures is F + Failures_SF,
summarize_scores(Scores, Next_Passes, Next_Failures, Passes, Failures).
When I run
test_arith(P,F).
I get
P = 1,
F = 0.
because test_arith seems to be called only once. I should get
P = 2,
F = 1.
Thanks for any help you can give.
I tried:
test_arith(Passes, Failures) :-
bagof(P-F, A^(test_arith(A)->(P=1,F=0);(P=0,F=1)), Scores),
summarize_scores(Scores, 0, 0, Passes, Failures).
test_arith(_) :- 5 is 3 +2.
test_arith(_) :- 5 is 2 +2.
test_arith(_) :- 4 is 2 +2.
test_arith2(Passes) :-
aggregate(count, A^test_arith(A), Passes).
test_arith(P,F) yields: P = 1, F = 0. test_arith2(P) yields "2". (Which is good that it works, but only 1/4 of what I'm looking for. I need a count of failures and for each predicate to be run only once per test run, 3 calls in this case.)
Then I tried adding a number for each test case:
test_arith(Passes, Failures) :-
bagof(P-F, A^(test_arith(A)->(P=1,F=0);(P=0,F=1)), Scores),
summarize_scores(Scores, 0, 0, Passes, Failures).
test_arith(1) :- 5 is 3 +2.
test_arith(2) :- 5 is 2 +2.
test_arith(3) :- 4 is 2 +2.
and got:
test_arith(P,F).
P = 1,
F = 0.
between(1,3,A), ( test_arith(A) -> ....
(It is not a good idea to remove A...) – false