/*----------------------------------------------------------*/
/*  Attribute-Value Learning by LGG (Sicstus Prolog V2+)    */
/*----------------------------------------------------------*/
/*  (C) 1997 Zdravko Markov                                 */
/*----------------------------------------------------------*/
lrn(E,R) :-
    del([C|A],E,E1),
    del([C|B],E1,E2),
    lgg(A,B,LGG),
    \+((member([C1|LGG],E2),\+(C=C1))),
    lrn([[C|LGG]|E2],R).
lrn(R,R).

lgg([],[],[]).
lgg([X|T],[Y|L],[X|V]) :-
    X==Y, !,
    lgg(T,L,V).
lgg([_|T],[_|L],[_|V]) :-
    lgg(T,L,V).

del(X,[X|T],T).
del(X,[Y|T],[Y|V]) :-
    del(X,T,V).

member(X,[X|_]).
member(X,[_|T]) :-
    member(X,T).

/*----------------------------------------------------------*/
/*    Testing                                               */
/*----------------------------------------------------------*/
test(SampleSize,PredictedAccuracy) :-
    examples(Set),
    sample(SampleSize,Set,Sample),
    lrn(Sample,Hypothesis),
    test(Set,Hypothesis,PredictedAccuracy), !.

examples(L) :-
    findall([C|Vs],(example(_,C,AVs),remove_names(AVs,Vs)),L).

remove_names([],[]).
remove_names([_=V|T],[V|R]) :-
    remove_names(T,R).

test(E,R,Accuracy) :-
    check(E,R,Correct,All),
    Accuracy is Correct/All.

check([],_,0,0).
check([[C|V]|T],R,Correct,All) :-
    \+(\+(member([C|V],R))),
    \+((member([C1|V],R),\+(C=C1))), !,
    check(T,R,Correct1,All1),
    Correct is Correct1 + 1,
    All is All1 + 1.
check([_|T],R,Correct,All) :-
    check(T,R,Correct,All1),
    All is All1 + 1.

sample(Percent,Set,Sample) :-
    length(Set,N),
    SampleSize is (Percent*N) // 100,
    generate_sample(SampleSize,Set,Sample).

generate_sample(0,_,[]) :- !.
generate_sample(N,Set,[E|Sample]) :-
    length(Set,S),
    S1 is S+1,
    random(1,S1,R),
    efface_n(R,E,Set,Rest),
    M is N-1,
    generate_sample(M,Rest,Sample).

efface_n(1,E,[E|T],T) :- !.
efface_n(N,E,[X|T],[X|R]) :-
    M is N-1,
    efface_n(M,E,T,R).

random(A,B,V) :-
   retract(seed(X)), !,
   Y is (25173*X+13849) mod 65536,
   asserta(seed(Y)),
   V is integer(Y*(B-A)/65536)+1.
random(A,B,V) :-
   statistics(runtime,[T,_]),
   Y is T mod 65536,
   assertz(seed(Y)),
   V is integer(Y*(B-A)/65536)+1.

