Question

I have a problem in which I have a list of elements and I have to cycle through all instances of a particular /2 predicate to find which one has he highest number of matching elements in its list. In terms of implementation I can't seem to figure out how I should be updating the highest match so far and then stopping when there are no more.

findAnswer(MyList, HighMatchNum,_):-
    answer(X,Y),
    myIntersection(MyList, Y, NUM), //handles a single instance check and returns how many elements match.
    NUM > HighMatchNum,
    findAnswer(MyList, NUM, answer(X,Y)).

//Knowledge base
 answer(sample1, [a,b,c,d]).
 answer(sample2, [d,c,e]).
Was it helpful?

Solution

there is library(aggregate):

findAnswer(MyList, HighMatchNum, K) :-
    aggregate_all(max(N, Key),
              (   answer(Key, List),
                  myIntersection(MyList, List, N)
              ),
              max(HighMatchNum, K)).

myIntersection(MyList, List, N) :-
    intersection(MyList, List, L),
    length(L, N).

% Knowledge base
answer(sample1, [a,b,c,d]).
answer(sample2, [d,c,e]).

yields

?- findAnswer([a], C, K).
C = 1,
K = sample1.

?- findAnswer([d,e], C, K).
C = 2,
K = sample2.

OTHER TIPS

To find the best, we have to search through the whole list, to its end. We will maintain the best so far and its score as additional arguments:

best_match(MyList,R-RN):-
  findall(X, (answer(A,L), X=A-L), ALL),
  ALL = [A-L|T],
  myIntersection(MyList, L, N),
  find_best(MyList,T,A,N,R,RN).

find_best(_,[],A,N,A,N).
find_best(MyList,[B-H|T],A,N,R,RN):-
  myIntersection(MyList, H, K),
  ( K>N -> find_best( MyList, T, B, K, R, RN)
    ;      find_best( MyList, T, A, N, R, RN ).

this produces the name and score of the best match.

Simply assert it, I can not see how you can propagate the max value in your solution.

:- dynamic maxval/1
:- maxval(0).

findAnswer(MyList, HighMatchNum) :-
    answer(X,Y),
    myIntersection(MyList, Y, NUM), %handles a single instance check and returns how many   elements match.
    NUM > HighMatchNum,             %If this fails, try other answer
    retract(maxval(_), assert(maxval(X)),!, %else retract the previous value and assert the new one
    findAnswer(MyList, NUM).

Finally check the value of maxval/1 as maxval(X). This algorithm will always fail so you will get the solution in the user database, the problem is with your implementation, you may check your logic. However it will assert the proper answer. You must remember to always implement a base case for any recursive procedure.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top