1% File: /opt/PrologMUD/pack/logicmoo_base/prolog/logicmoo/util/logicmoo_util_no_repeats.pl
    2:- module(no_repeats,
    3          [ /*memberchk_pred/3,
    4            memberchk_pred_rev/3,
    5            memberchk_same/2,
    6            memberchk_same0/2,
    7            memberchk_same1/2,
    8            memberchk_same2/2,
    9            memberchk_same3/2,
   10            memberchk_cmp/3,
   11            memb_r/2,*/
   12            must_not_repeat/1,
   13            no_repeats/1,
   14            no_repeats/2,
   15/*
   16            no_repeats_av/0,
   17            no_repeats_findall5/5,
   18            no_repeats_findall_r/5,
   19            no_repeats_old/1,         
   20            no_repeats_old/2,
   21            no_repeats_cmp/3,
   22            no_repeats_save/2,
   23            no_repeats_save/4,
   24            no_repeats_u/2,
   25            
   26            succeeds_n_times/2,
   27            nr_test/2,
   28            */
   29            subtract_eq/3,
   30            no_repeats_var/1
   31%            loop_check_nr/1
   32          ]).

Utility LOGICMOO NO REPEATS

No repeats allows each indiv answer returned by prolog to be unique. Removes duplicate answers.

   39:- meta_predicate
   40        memberchk_pred(2, ?, ?),
   41        memberchk_pred_rev(2, ?, ?),
   42        must_not_repeat(0),
   43        no_repeats(0),
   44        no_repeats(+, 0),
   45        no_repeats_findall5(+, 0, -, -, -),
   46        no_repeats_findall_r(+, 0, -, -, -),
   47        no_repeats_old(0),
   48        no_repeats_old(+, 0),
   49        no_repeats_cmp(2, +, 0),
   50        no_repeats_save(+, 0),
   51        no_repeats_save(+, 0, -, -),
   52        no_repeats_u(+, 0),
   53        loop_check_nr(0),
   54        succeeds_n_times(0, -).   55:- module_transparent
   56        memberchk_same/2,
   57        no_repeats_av/0,
   58        no_repeats_cmp/3,
   59        subtract_eq/3,
   60        nr_test/2.   61
   62      
   63:- set_module(class(library)).   64
   65%:- prolog_load_context(directory,Dir),add_file_search_path_safe(library,Dir).
   66% % % OFF :- system:use_module(library(logicmoo/misc_terms)).
 loop_check_nr(?CL) is semidet
Loop Check Nr.
   72loop_check_nr(CL):- loop_check(no_repeats(CL)).
   73
   74
   75% ===================================================================
   76
   77:- thread_local  tlbugger:attributedVars/0.   78
   79%  tlbugger:attributedVars.
   80
   81:- export(must_not_repeat/1).   82% = :- meta_predicate(must_not_repeat(0)).
 must_not_repeat(:GoalC) is semidet
Must Be Successfull Not Repeat.
   90must_not_repeat(C):-call(C).
   91
   92% ===================================================
   93%
   94% no_repeats(:Call)
   95%
   96% Like call/1 but ony succeeds only unique variabes
   97%
   98% logicmoo_mud:  ?- no_repeats(member(X,[3,1,1,1,3,2])).
   99% X = 3 ;
  100% X = 1 ;
  101% X = 2.
  102% ===================================================
 no_repeats_av is semidet
No Repeats Attributed Variables.
  114no_repeats_av:-tlbugger:attributedVars.
  115
  116:- export(no_repeats/1).  117:- meta_predicate no_repeats(0).  118
  119% no_repeats(Call):- tlbugger:old_no_repeats,!, no_repeats_old(Call).
  120%no_repeats(Call):- no_repeats_av,!,no_repeats_av(Call).
 no_repeats(:Goal) is semidet
No Repeats.
  128no_repeats(Call):- no_repeats_old(Call).
  129
  130
  131:- export(no_repeats/2).  132:- meta_predicate no_repeats(+,0).  133%no_repeats(Vs,Call):- tlbugger:old_no_repeats,!,no_repeats_old(Vs,Call).
  134%no_repeats(Vs,Call):- no_repeats_av,!,no_repeats_av(Vs,Call).
 no_repeats(+Vs, :Goal) is semidet
No Repeats.
  142no_repeats(Vs,Call):- no_repeats_old(Vs,Call).
  143
  144/*
  145no_repeats_dif(Vs,Call):- dif(Vs,_), get_attr(Vs,dif,vardif(CONS,_)),!,
  146  Call,copy_term_nat(Vs,C),nb_setarg(2, CONS, [_-C|CONS]).
  147
  148*/
  149
  150% ===================================================
  151%
  152% no_repeats_old([+Vars,]:Call)
  153%
  154% Like call/1 but ony succeeds on unique free variabes
  155%
  156% logicmoo_mud:  ?- no_repeats( X , member(X-Y,[3-2,1-4,1-5,2-1])).
  157% X = 3, Y = 2 ;
  158% X = 1, Y = 4 ;
  159% X = 2, Y = 1.
  160% ===================================================
  161:- export(no_repeats_old/1).  162:- meta_predicate no_repeats_old(0).
 no_repeats_old(:Goal) is semidet
No Repeats Old.
  170no_repeats_old(Call):- no_repeats_old(Call,Call).
  171
  172
  173% % % % OFF :- system:use_module(rec_lambda).
 memberchk_same(?X, :TermY0) is semidet
Memberchk Same.
  182memberchk_same(X, List) :- is_list(List),!, \+ atomic(List), C=..[v|List],(var(X)-> (arg(_,C,YY),X==YY) ; (arg(_,C,YY),X =@= YY)),!.
  183memberchk_same(X, Ys) :-  nonvar(Ys), var(X)->memberchk_same0(X, Ys);memberchk_same1(X,Ys).
  184memberchk_same0(X, [Y|Ys]) :-  X==Y  ; (nonvar(Ys),memberchk_same0(X, Ys)).
  185memberchk_same1(X, [Y|Ys]) :-  X =@= Y ; (nonvar(Ys),memberchk_same1(X, Ys)).
  186
  187memberchk_same2(X, List) :- Hold=hold(List), !,
  188        repeat, (arg(1,Hold,[Y0|Y0s]) ->
  189          ( X==Y0-> true; (nb_setarg(1,Hold,Y0s),fail)) ; (! , fail)).
  190
  191memberchk_same3(X, List) :- Hold=hold(List), !,
  192        repeat, (arg(1,Hold,[Y0|Y0s]) ->
  193          ( X=@=Y0-> true; (nb_setarg(1,Hold,Y0s),fail)) ; (! , fail)).
  194
  195memb_r(X, List) :- Hold=hold(List), !, trace_or_throw(broken_memb_r(X, List)),
  196         repeat,
  197          ((arg(1,Hold,[Y|Ys]),nb_setarg(1,Hold,Ys)) -> X=Y ; (! , fail)).
 memberchk_pred(:PRED2Pred, ?X, ?Y0) is semidet
Memberchk Predicate.
  210memberchk_pred(Pred, X, [Y0|Ys]) :- is_list(Ys),C=..[v,Y0|Ys],!, arg(_,C,Y), call(Pred,X,Y),!.
  211memberchk_pred(Pred, X, [Y|Ys]) :- (   call(Pred,X,Y) -> true ;   (nonvar(Ys),memberchk_pred(Pred, X, Ys) )).
 memberchk_pred_rev(:PRED2Pred, ?X, ?Y0) is semidet
Memberchk Predicate Rev.
  219memberchk_pred_rev(Pred, X, [Y0|Ys]) :- is_list(Ys),C=..[v,Y0|Ys],!, arg(_,C,Y), call(Pred,Y,X),!.
  220memberchk_pred_rev(Pred, X, [Y|Ys]) :- (   call(Pred,Y,X) -> true ;   (nonvar(Ys),memberchk_pred_rev(Pred,X, Ys) )).
  221
  222:- export(no_repeats_old/2).  223:- meta_predicate no_repeats_old(+,0).
 no_repeats_old(+Vs, :Goal) is semidet
No Repeats Old.
  231no_repeats_old(Vs,Call):- ground(Vs),!,Call,!.
  232no_repeats_old(Vs,Call):- CONS = [_], (Call), 
  233   quietly(( \+ memberchk_same(Vs,CONS), copy_term(Vs,CVs), CONS=[_|T], nb_setarg(2, CONS, [CVs|T]))).
  234
  235% mcs_t2(A,B) :- call(lambda(X, [Y|Ys], (   X =@= Y ->  (var(X) -> X==Y ; true) ;   (nonvar(Ys),reenter_lambda(X, Ys) ))),A,B).
  236% mcs_t(A,B) :- call(lambda(X, [Y|Ys], (   X =@= Y ->  (var(X) -> X==Y ; true) ;   (nonvar(Ys),reenter_lambda(X, Ys) ))),A,B).
  237
  238no_repeats_cmp(_,Vs,Call):- ground(Vs),!,Call,!.
  239no_repeats_cmp(Cmp,Vs,Call):- CONS = [zzzZZZZzzzzZZZ], (Call), 
  240   quietly(( \+ memberchk_cmp(Cmp,Vs,CONS), copy_term(Vs,CVs), CONS=[_|T], nb_setarg(2, CONS, [CVs|T]))).
  241:- export(no_repeats_cmp/3).  242memberchk_cmp(Cmp,Vs,CONS):-
  243   member(XY,CONS),call(Cmp,Vs,XY),!.
  244
  245/*
  246:- meta_predicate no_repeats_t(?,0).
  247no_repeats_t(Vs,Call):- CONS = [_], (Call), (( \+ call(lambda(X, [Y|Ys], (   X =@= Y ->  (var(X) -> X==Y ; true) ;   (nonvar(Ys),reenter_lambda(X, Ys) ))),Vs,CONS), copy_term(Vs,CVs), CONS=[_|T], nb_linkarg(2, CONS, [CVs|T]))).
  248*/
  249
  250%
  251
  252:- export(no_repeats_u/2).  253:- meta_predicate no_repeats_u(+,0).
 no_repeats_u(+Vs, :Goal) is semidet
No Repeats For User Code.
  261no_repeats_u(Vs,Call):- CONS = [_], (Call), /*quietly*/((  CONS=[_|T],
  262    \+ memberchk_pred_rev(subsumes_term,Vs,T), copy_term(Vs,CVs), nb_setarg(2, CONS, [CVs|T]))).
  263
  264
  265
  266% for dont-care vars
  267/*
  268:- export(no_repeats_dc/2).
  269:- meta_predicate no_repeats_dc(+,0).
  270no_repeats_dc(Vs,Call):- term_variables(Call,CV),term_variables(Vs,VsL),subtract_eq(CV,VsL,NewVs),no_repeats(NewVs,Call).
  271*/
 subtract_eq(+Set, +Delete, -Result) is det
Delete all elements in Delete from Set. Deletion is based on unification using ==/2. The complexity is |Delete|*|Set|.
 subtract_eq(:TermE, ?Delete, ?Result) is semidet
Subtract Using (==/2) (or =@=/2) ).
  283subtract_eq([],_,[]) :- !.
  284subtract_eq([E|Set], Delete, Result) :-
  285   subtract_eq(Set, Delete, Mid),
  286   (identical_memberchk(E,Delete)-> Result = Mid ; Result = [E|Mid]).
  287   
  288% ===================================================
  289%
  290%  no_repeats_av/1 - Filter repeats using coroutining
  291%
  292% Same as no_repeats(:Call) (so same as call/1 but fitered)
  293%
  294% (everytime we see new value.. we add it to was/2 in an attributed variable that we have a refernce in a compound)
  295% Cehcked via ?- was(AVar,Foo), get_attrs(AVar,ATTRS1), get_attrs(AVar,ATTRS2), ATTRS1==ATTRS2.
  296%
  297%  So the variable binding gerts rejected several frames below your code? ( are we nipping away futile bindings?)
  298%
  299% however ..
  300%     does that mess with anything in code that we are calling?
  301%  Could some peice of code been required to see some binding to make a side effect come about?
  302%
  303% logicmoo_mud:  ?- no_repeats_av(member(X,[3,1,1,1,3,2])).
  304% X = 3 ;
  305% X = 1 ;
  306% X = 2.
  307%
  308% attributed variable verson of getting filtered bindings
  309% ===================================================
  310/*
  311:- export(no_repeats_av/1).
  312% = :- meta_predicate(no_repeats_av(0)).
  313:- export(no_repeats_av/2).
  314% = :- meta_predicate(no_repeats_av(+,0)).
  315:- export(no_repeats_av_l/2).
  316% = :- meta_predicate(no_repeats_av_l(+,0)).
  317
  318no_repeats_av(AVar,Call):- var(AVar),!,
  319   Call):-term_variables(Call,Vs),!,no_repeats_av_l(Vs,Call).
  320
  321no_repeats_av_l([],Call):-!,Call,!.
  322no_repeats_av_l([AVar],Call):-!,
  323   no_repeats_av(AVar,Call).
  324no_repeats_av_l([AVar|List],Call):-   each_call_cleanup(
  325       (was(AVar,iNEVER),asserta(tlbugger:cannot_save_table,Ref),get_attr(AVar,waz,varwaz(CONS,_))),
  326        (Call,copy_term_nat(AVar,C),nb_linkarg(2, CONS, [_-C|CONS])),
  327        (del_attr(AVar,was),erase_safe(tlbugger:cannot_save_table,Ref))).
  328no_repeats_av(List,Call):- is_list(List),!,no_repeats_av_l(List,Call).
  329no_repeats_av(Term,Call):-term_variables(Term,List),!,no_repeats_av_l(List,Call).
  330
  331
  332
  333*/
  334
  335% =========================================================================
  336:- meta_predicate succeeds_n_times(0, -).  337% =========================================================================
 succeeds_n_times(:Goal, -Times) is semidet
Succeeds N Times.
  346succeeds_n_times(Goal, Times) :-
  347        Counter = counter(0),
  348        (   Goal,
  349            arg(1, Counter, N0),
  350            N is N0 + 1,
  351            nb_setarg(1, Counter, N),
  352            fail
  353        ;   arg(1, Counter, Times)
  354        ).
  355
  356
  357
  358:- export(no_repeats_findall5/5).  359:- meta_predicate no_repeats_findall5(+,0,-,-,-).
 no_repeats_findall5(+Vs, :Goal, -ExitDET, -USE, -NEW) is semidet
No Repeats Findall5.
  367no_repeats_findall5(Vs,Call,ExitDET,USE,NEW):-
  368   (((HOLDER = fa([]),
  369   Call,arg(1,HOLDER,CONS),
  370   ((
  371   (( \+ memberchk_same(Vs,CONS),
  372   copy_term(Vs,CVs),
  373   append(CONS,[CVs],NEW),
  374    nb_setarg(1, HOLDER, NEW)))
  375      ->
  376       USE=true;
  377       ((USE=(false),CONS=NEW))
  378       )),
  379   deterministic(ExitDET),true))
  380    *-> true;
  381     (NEW=[],ExitDET=true,USE=(false))).
  382
  383:- export(no_repeats_save/4).  384:- meta_predicate no_repeats_save(+,0,-,-).
 no_repeats_save(+Vs, :Goal, -Saved, -USE) is semidet
No Repeats Save.
  392no_repeats_save(Vs,Call,Saved,USE):-
  393 SavedHolder = saved(_),
  394  no_repeats_findall5(Vs,Call,ExitDET,USE,NEW),
  395  ( ExitDET==true -> (nb_linkarg(1,SavedHolder,NEW),!) ; true),
  396  arg(1,SavedHolder,Saved).
  397
  398:- export(no_repeats_save/2).  399:- meta_predicate no_repeats_save(+,0).
 no_repeats_save(+Vs, :Goal) is semidet
No Repeats Save.
  407no_repeats_save(Vs,Call):-
  408  call_cleanup(
  409   (( no_repeats_save(Vs,Call,SavedList,USE),
  410      (USE==true -> true ; fail))),
  411   (is_list(SavedList) -> writeln(saving(SavedList)) ; writeln(givingup_on(Call)))).
  412
  413
  414:- export(no_repeats_findall_r/5).  415:- meta_predicate no_repeats_findall_r(+,0,-,-,-).
 no_repeats_findall_r(+Vs, :Goal, -CONS, -ExitDET, -List) is semidet
No Repeats Findall R.
  423no_repeats_findall_r(Vs,Call,CONS,ExitDET,List):-
  424   CONS = [ExitDET],
  425   (Call,once(( \+ memberchk_same(Vs,CONS), copy_term(Vs,CVs), CONS=[_|T],List=[CVs|T], nb_linkarg(2, CONS, List)))),
  426   deterministic(ExitDET).
 no_repeats_var(+Var) is det
Attribute a varaible to never be bound to the same value twice
?- no_repeats_var(X),member(X,[1,2,3,3,3,1,2,3]).
X = 1;
X = 2;
X = 3;
No.
  439no_repeats_var(Var):- nonvar(Var) ->true; 
  440 (get_attr(Var,nr,_)->true;put_attr(Var,nr,old_vals(Var,same_forms,[]))).
  441no_repeats_var(Cmp,Var):- nonvar(Var) ->true; (get_attr(Var,nr,_)->true;put_attr(Var,nr,old_vals(Var,Cmp,[]))).
  442
  443nr:attr_unify_hook(AttValue,VarValue):- 
  444  AttValue=old_vals(_Var,Cmp,Waz),
  445  \+ memberchk_pred(Cmp,VarValue,Waz),nb_setarg(3,AttValue,[VarValue|Waz]).
  446/*
  447nr:attr_unify_hook(AttValue,VarValue):- 
  448  AttValue=old_vals(_Var,Cmp,Waz),
  449  \+ (member(E,Waz), call(Cmp,VarValue,E)),
  450  nb_setarg(3,AttValue,[VarValue|Waz]).
  451*/
  452
  453same_forms(F1,F2):- get_attrs(F1,A1),!,get_attrs(F2,A2),A1=@=A2.
  454same_forms(F1,F2):- get_attrs(F2,A1),!,fail,get_attrs(F1,A2),A1=@=A2.
  455same_forms(F1,F2):- var(F1),!,F2==F1.
  456same_forms(F1,F2):- var(F2),!,fail,F2==F1.
  457same_forms(F1,F2):- F1=@=F2.
  458% WAS OFF  :- system:use_module(library(logicmoo_startup)).
  459
  460:- if(current_predicate(fixup_exports/0)).  461:- fixup_exports.  462:- endif.
Term.
  468nr_test((-7), 3).
  469nr_test(2,10).
  470nr_test((-8), 5).
  471nr_test((-8), 2).
  472nr_test(42,11).
  473nr_test(42,14).
  474nr_test(1,3).
  475nr_test(77,2).
  476nr_test(80,10).
  477nr_test(80,0).
  478nr_test((-3),12).
  479nr_test((-4), 14).
  480nr_test((-4), 0).
  481nr_test(45,0).
  482nr_test(45,9).
  483nr_test((-1),1)