How can i get values by an specific condition, and next with these selected elements get values from other facts serie?
I've this code
%code, date, amount
values1('AAA', date(02, 03, 2020), 1000).
values1('AAA', date(31, 03, 2020), 2000).
values1('BBB', date(02, 04, 2020), 1350).
values1('BBB', date(15, 04, 2020), 1500).
values1('CCC', date(23, 05, 2020), 5500).
values1('CCC', date(01, 05, 2020), 750).
values1('DDD', date(06, 05, 2020), 3560).
values1('AAA', date(18, 06, 2020), 4600).
values1('CCC', date(27, 07, 2020), 1200).
%code, percent
values2('AAA', '0.2').
values2('BBB', '0.25').
values2('CCC', '0.55').
values2('DDD', '0.98').
predicate1(Code, Percent) :-
findall(Code, (values1(Code, _, Value), Value > 1000), Code),
findall(Percent, values2(Code, Percent), Percent).
For example in this case the idea it's get Code which amount is bigger than 1000, and when there are selected get the percent from value2, but the Percent list it's return empty. Why it happening that?
This is the return
predicate1(Code, Percent).
Code = ['AAA', 'BBB', 'BBB', 'CCC', 'DDD', 'AAA', 'CCC'],
Percent = []
it may be by the difference between number of elements in list of Code and number of fact of values2 maybe?
You have a typo and a (few) logic errors.
The value of Code
goes into a list of Code
: CodeList
. You have variable Code
on first and third position. Use this:
findall(Code, (values1(Code, _, Value), Value > 1000), CodeList).
Run it:
?- findall(Code, (values1(Code, _, Value), Value > 1000), CodeList).
CodeList = ['AAA', 'BBB', 'BBB', 'CCC', 'DDD', 'AAA', 'CCC'].
Duplicate elements are removed by using the predicate setof/3
instead.
However, setof/3
demands that you indicate ("existentially quantify" with the caret notation: Value^Date^
) the variables that shall be invisible outside the inner goal, otherwise backtracking over possible values of Value
and Date
will occur outside of setof/3
:
?- setof(Code, Value^Date^(values1(Code, Date, Value), Value > 1000), CodeList).
CodeList = ['AAA', 'BBB', 'CCC', 'DDD'].
Now you just need to "join" any "code" with the "percentage" ... inside of setof/3
:
?- setof([Code,Percent],
Value^Date^(values1(Code, Date, Value),
Value > 1000,
values2(Code,Percent)),
Set).
Set = [['AAA', '0.2'], ['BBB', '0.25'], ['CCC', '0.55'], ['DDD', '0.98']].
You can pack this into a predicate which backtracks over the setof/3
result:
gimme(Code, Percent) :-
setof([Code,Percent],
Value^Date^(values1(Code, Date, Value),
Value > 1000,
values2(Code,Percent)),
Set),
member([Code,Percent],Set).
Note that the reuse of variables of Code
and Percent
inside setof/3
and in the call to member/2
s well is actually ok: These are not the same variables.
And so:
?- gimme(Code,Percent).
Code = 'AAA',
Percent = '0.2' ;
Code = 'BBB',
Percent = '0.25' ;
Code = 'CCC',
Percent = '0.55' ;
Code = 'DDD',
Percent = '0.98'.