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            no_repeats_av/0,
   16            no_repeats_findall5/5,
   17            no_repeats_findall_r/5,
   18            no_repeats_old/1,         
   19            no_repeats_old/2,
   20            no_repeats_cmp/3,
   21            no_repeats_save/2,
   22            no_repeats_save/4,
   23            no_repeats_u/2,
   24            subtract_eq/3,
   25            succeeds_n_times/2,
   26            nr_test/2,
   27            no_repeats_var/1,
   28            loop_check_nr/1
   29          ]).   30:- meta_predicate
   31        memberchk_pred(2, ?, ?),
   32        memberchk_pred_rev(2, ?, ?),
   33        must_not_repeat(0),
   34        no_repeats(0),
   35        no_repeats(+, 0),
   36        no_repeats_findall5(+, 0, -, -, -),
   37        no_repeats_findall_r(+, 0, -, -, -),
   38        no_repeats_old(0),
   39        no_repeats_old(+, 0),
   40        no_repeats_cmp(2, +, 0),
   41        no_repeats_save(+, 0),
   42        no_repeats_save(+, 0, -, -),
   43        no_repeats_u(+, 0),
   44        loop_check_nr(0),
   45        succeeds_n_times(0, -).   46:- module_transparent
   47        memberchk_same/2,
   48        no_repeats_av/0,
   49        no_repeats_cmp/3,
   50        subtract_eq/3,
   51        nr_test/2.   52
   53      
   54:- set_module(class(library)).
 loop_check_nr(?CL) is semidet
Loop Check Nr.
   60loop_check_nr(CL):- loop_check(no_repeats(CL)).
   61
   62
   63% ===================================================================
   64
   65:- thread_local  tlbugger:attributedVars.   66
   67%  tlbugger:attributedVars.
   68
   69:- export(must_not_repeat/1).   70% = :- meta_predicate(must_not_repeat(0)).
 must_not_repeat(:GoalC) is semidet
Must Be Successfull Not Repeat.
   78must_not_repeat(C):-call(C).
   79
   80% ===================================================
   81%
   82% no_repeats(:Call)
   83%
   84% Like call/1 but ony succeeds only unique variabes
   85%
   86% logicmoo_mud:  ?- no_repeats(member(X,[3,1,1,1,3,2])).
   87% X = 3 ;
   88% X = 1 ;
   89% X = 2.
   90% ===================================================
 no_repeats_av is semidet
No Repeats Attributed Variables.
  102no_repeats_av:-tlbugger:attributedVars.
  103
  104:- export(no_repeats/1).  105:- meta_predicate no_repeats(0).  106
  107% no_repeats(Call):- tlbugger:old_no_repeats,!, no_repeats_old(Call).
  108%no_repeats(Call):- no_repeats_av,!,no_repeats_av(Call).
 no_repeats(:Goal) is semidet
No Repeats.
  116no_repeats(Call):- no_repeats_old(Call).
  117
  118
  119:- export(no_repeats/2).  120:- meta_predicate no_repeats(+,0).  121%no_repeats(Vs,Call):- tlbugger:old_no_repeats,!,no_repeats_old(Vs,Call).
  122%no_repeats(Vs,Call):- no_repeats_av,!,no_repeats_av(Vs,Call).
 no_repeats(+Vs, :Goal) is semidet
No Repeats.
  130no_repeats(Vs,Call):- no_repeats_old(Vs,Call).
  131
  132/*
  133no_repeats_dif(Vs,Call):- dif(Vs,_), get_attr(Vs,dif,vardif(CONS,_)),!,
  134  Call,copy_term_nat(Vs,C),nb_setarg(2, CONS, [_-C|CONS]).
  135
  136*/
  137
  138% ===================================================
  139%
  140% no_repeats_old([+Vars,]:Call)
  141%
  142% Like call/1 but ony succeeds on unique free variabes
  143%
  144% logicmoo_mud:  ?- no_repeats( X , member(X-Y,[3-2,1-4,1-5,2-1])).
  145% X = 3, Y = 2 ;
  146% X = 1, Y = 4 ;
  147% X = 2, Y = 1.
  148% ===================================================
  149:- export(no_repeats_old/1).  150:- meta_predicate no_repeats_old(0).
 no_repeats_old(:Goal) is semidet
No Repeats Old.
  158no_repeats_old(Call):- no_repeats_old(Call,Call).
  159
  160
  161% :- use_module(rec_lambda).
 memberchk_same(?X, :TermY0) is semidet
Memberchk Same.
  170memberchk_same(X, List) :- is_list(List),!, \+ atomic(List), C=..[v|List],(var(X)-> (arg(_,C,YY),X==YY) ; (arg(_,C,YY),X =@= YY)),!.
  171memberchk_same(X, Ys) :-  nonvar(Ys), var(X)->memberchk_same0(X, Ys);memberchk_same1(X,Ys).
  172memberchk_same0(X, [Y|Ys]) :-  X==Y  ; (nonvar(Ys),memberchk_same0(X, Ys)).
  173memberchk_same1(X, [Y|Ys]) :-  X =@= Y ; (nonvar(Ys),memberchk_same1(X, Ys)).
  174
  175memberchk_same2(X, List) :- Hold=hold(List), !,
  176        repeat, (arg(1,Hold,[Y0|Y0s]) ->
  177          ( X==Y0-> true; (nb_setarg(1,Hold,Y0s),fail)) ; (! , fail)).
  178
  179memberchk_same3(X, List) :- Hold=hold(List), !,
  180        repeat, (arg(1,Hold,[Y0|Y0s]) ->
  181          ( X=@=Y0-> true; (nb_setarg(1,Hold,Y0s),fail)) ; (! , fail)).
  182
  183memb_r(X, List) :- Hold=hold(List), !, trace_or_throw(broken_memb_r(X, List)),
  184         repeat,
  185          ((arg(1,Hold,[Y|Ys]),nb_setarg(1,Hold,Ys)) -> X=Y ; (! , fail)).
 memberchk_pred(:PRED2Pred, ?X, ?Y0) is semidet
Memberchk Predicate.
  198memberchk_pred(Pred, X, [Y0|Ys]) :- is_list(Ys),C=..[v,Y0|Ys],!, arg(_,C,Y), call(Pred,X,Y),!.
  199memberchk_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.
  207memberchk_pred_rev(Pred, X, [Y0|Ys]) :- is_list(Ys),C=..[v,Y0|Ys],!, arg(_,C,Y), call(Pred,Y,X),!.
  208memberchk_pred_rev(Pred, X, [Y|Ys]) :- (   call(Pred,Y,X) -> true ;   (nonvar(Ys),memberchk_pred_rev(Pred,X, Ys) )).
  209
  210:- export(no_repeats_old/2).  211:- meta_predicate no_repeats_old(+,0).
 no_repeats_old(+Vs, :Goal) is semidet
No Repeats Old.
  219no_repeats_old(Vs,Call):- ground(Vs),!,Call,!.
  220no_repeats_old(Vs,Call):- CONS = [_], (Call), 
  221   quietly(( \+ memberchk_same(Vs,CONS), copy_term(Vs,CVs), CONS=[_|T], nb_setarg(2, CONS, [CVs|T]))).
  222
  223% mcs_t2(A,B) :- call(lambda(X, [Y|Ys], (   X =@= Y ->  (var(X) -> X==Y ; true) ;   (nonvar(Ys),reenter_lambda(X, Ys) ))),A,B).
  224% mcs_t(A,B) :- call(lambda(X, [Y|Ys], (   X =@= Y ->  (var(X) -> X==Y ; true) ;   (nonvar(Ys),reenter_lambda(X, Ys) ))),A,B).
  225
  226no_repeats_cmp(_,Vs,Call):- ground(Vs),!,Call,!.
  227no_repeats_cmp(Cmp,Vs,Call):- CONS = [zzzZZZZzzzzZZZ], (Call), 
  228   quietly(( \+ memberchk_cmp(Cmp,Vs,CONS), copy_term(Vs,CVs), CONS=[_|T], nb_setarg(2, CONS, [CVs|T]))).
  229
  230memberchk_cmp(Cmp,Vs,CONS):-
  231   member(XY,CONS),call(Cmp,Vs,XY),!.
  232
  233/*
  234:- meta_predicate no_repeats_t(?,0).
  235no_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]))).
  236*/
  237
  238%
  239
  240:- export(no_repeats_u/2).  241:- meta_predicate no_repeats_u(+,0).
 no_repeats_u(+Vs, :Goal) is semidet
No Repeats For User Code.
  249no_repeats_u(Vs,Call):- CONS = [_], (Call), /*quietly*/((  CONS=[_|T],
  250    \+ memberchk_pred_rev(subsumes_term,Vs,T), copy_term(Vs,CVs), nb_setarg(2, CONS, [CVs|T]))).
  251
  252
  253
  254% for dont-care vars
  255/*
  256:- export(no_repeats_dc/2).
  257:- meta_predicate no_repeats_dc(+,0).
  258no_repeats_dc(Vs,Call):- term_variables(Call,CV),term_variables(Vs,VsL),subtract_eq(CV,VsL,NewVs),no_repeats(NewVs,Call).
  259*/
 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) ).
  271subtract_eq([],_,[]) :- !.
  272subtract_eq([E|Set], Delete, Result) :-
  273   subtract_eq(Set, Delete, Mid),
  274   (identical_memberchk(E,Delete)-> Result = Mid ; Result = [E|Mid]).
  275   
  276% ===================================================
  277%
  278%  no_repeats_av/1 - Filter repeats using coroutining
  279%
  280% Same as no_repeats(:Call) (so same as call/1 but fitered)
  281%
  282% (everytime we see new value.. we add it to was/2 in an attributed variable that we have a refernce in a compound)
  283% Cehcked via ?- was(AVar,Foo), get_attrs(AVar,ATTRS1), get_attrs(AVar,ATTRS2), ATTRS1==ATTRS2.
  284%
  285%  So the variable binding gerts rejected several frames below your code? ( are we nipping away futile bindings?)
  286%
  287% however ..
  288%     does that mess with anything in code that we are calling?
  289%  Could some peice of code been required to see some binding to make a side effect come about?
  290%
  291% logicmoo_mud:  ?- no_repeats_av(member(X,[3,1,1,1,3,2])).
  292% X = 3 ;
  293% X = 1 ;
  294% X = 2.
  295%
  296% attributed variable verson of getting filtered bindings
  297% ===================================================
  298/*
  299:- export(no_repeats_av/1).
  300% = :- meta_predicate(no_repeats_av(0)).
  301:- export(no_repeats_av/2).
  302% = :- meta_predicate(no_repeats_av(+,0)).
  303:- export(no_repeats_av_l/2).
  304% = :- meta_predicate(no_repeats_av_l(+,0)).
  305
  306no_repeats_av(AVar,Call):- var(AVar),!,
  307   Call):-term_variables(Call,Vs),!,no_repeats_av_l(Vs,Call).
  308
  309no_repeats_av_l([],Call):-!,Call,!.
  310no_repeats_av_l([AVar],Call):-!,
  311   no_repeats_av(AVar,Call).
  312no_repeats_av_l([AVar|List],Call):-   each_call_cleanup(
  313       (was(AVar,iNEVER),asserta(tlbugger:cannot_save_table,Ref),get_attr(AVar,waz,varwaz(CONS,_))),
  314        (Call,copy_term_nat(AVar,C),nb_linkarg(2, CONS, [_-C|CONS])),
  315        (del_attr(AVar,was),erase_safe(tlbugger:cannot_save_table,Ref))).
  316no_repeats_av(List,Call):- is_list(List),!,no_repeats_av_l(List,Call).
  317no_repeats_av(Term,Call):-term_variables(Term,List),!,no_repeats_av_l(List,Call).
  318
  319
  320
  321*/
  322
  323% =========================================================================
  324:- meta_predicate succeeds_n_times(0, -).  325% =========================================================================
 succeeds_n_times(:Goal, -Times) is semidet
Succeeds N Times.
  334succeeds_n_times(Goal, Times) :-
  335        Counter = counter(0),
  336        (   Goal,
  337            arg(1, Counter, N0),
  338            N is N0 + 1,
  339            nb_setarg(1, Counter, N),
  340            fail
  341        ;   arg(1, Counter, Times)
  342        ).
  343
  344
  345
  346:- export(no_repeats_findall5/5).  347:- meta_predicate no_repeats_findall5(+,0,-,-,-).
 no_repeats_findall5(+Vs, :Goal, -ExitDET, -USE, -NEW) is semidet
No Repeats Findall5.
  355no_repeats_findall5(Vs,Call,ExitDET,USE,NEW):-
  356   (((HOLDER = fa([]),
  357   Call,arg(1,HOLDER,CONS),
  358   ((
  359   (( \+ memberchk_same(Vs,CONS),
  360   copy_term(Vs,CVs),
  361   append(CONS,[CVs],NEW),
  362    nb_setarg(1, HOLDER, NEW)))
  363      ->
  364       USE=true;
  365       ((USE=false,CONS=NEW))
  366       )),
  367   deterministic(ExitDET),true))
  368    *-> true;
  369     (NEW=[],ExitDET=true,USE=false)).
  370
  371:- export(no_repeats_save/4).  372:- meta_predicate no_repeats_save(+,0,-,-).
 no_repeats_save(+Vs, :Goal, -Saved, -USE) is semidet
No Repeats Save.
  380no_repeats_save(Vs,Call,Saved,USE):-
  381 SavedHolder = saved(_),
  382  no_repeats_findall5(Vs,Call,ExitDET,USE,NEW),
  383  ( ExitDET==true -> (nb_linkarg(1,SavedHolder,NEW),!) ; true),
  384  arg(1,SavedHolder,Saved).
  385
  386:- export(no_repeats_save/2).  387:- meta_predicate no_repeats_save(+,0).
 no_repeats_save(+Vs, :Goal) is semidet
No Repeats Save.
  395no_repeats_save(Vs,Call):-
  396  call_cleanup(
  397   (( no_repeats_save(Vs,Call,SavedList,USE),
  398      (USE==true -> true ; fail))),
  399   (is_list(SavedList) -> writeln(saving(SavedList)) ; writeln(givingup_on(Call)))).
  400
  401
  402:- export(no_repeats_findall_r/5).  403:- meta_predicate no_repeats_findall_r(+,0,-,-,-).
 no_repeats_findall_r(+Vs, :Goal, -CONS, -ExitDET, -List) is semidet
No Repeats Findall R.
  411no_repeats_findall_r(Vs,Call,CONS,ExitDET,List):-
  412   CONS = [ExitDET],
  413   (Call,once(( \+ memberchk_same(Vs,CONS), copy_term(Vs,CVs), CONS=[_|T],List=[CVs|T], nb_linkarg(2, CONS, List)))),
  414   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.
  427no_repeats_var(Var):- nonvar(Var) ->true; (get_attr(Var,nr,_)->true;put_attr(Var,nr,old_vals(Var,same_forms,[]))).
  428no_repeats_var(Cmp,Var):- nonvar(Var) ->true; (get_attr(Var,nr,_)->true;put_attr(Var,nr,old_vals(Var,Cmp,[]))).
  429nr:attr_unify_hook(AttValue,VarValue):- AttValue=old_vals(_Var,Cmp,Waz), \+ memberchk_pred(Cmp,VarValue,Waz),nb_setarg(1,AttValue,[VarValue|Waz]).
  430
  431same_forms(F1,F2):- get_attrs(F1,A1),!,get_attrs(F2,A2),A1=@=A2.
  432same_forms(F1,F2):- get_attrs(F2,A1),!,get_attrs(F1,A2),A1=@=A2.
  433same_forms(F1,F2):- var(F1),!,F2==F1.
  434same_forms(F1,F2):- var(F2),!,F2==F1.
  435same_forms(F1,F2):- F1=@=F2.
  436
  437%:- use_module(library(logicmoo_util_startup)).
  438
  439:- if(current_predicate(fixup_exports/0)).  440:- fixup_exports.  441:- endif.
Term.
  447nr_test((-7), 3).
  448nr_test(2,10).
  449nr_test((-8), 5).
  450nr_test((-8), 2).
  451nr_test(42,11).
  452nr_test(42,14).
  453nr_test(1,3).
  454nr_test(77,2).
  455nr_test(80,10).
  456nr_test(80,0).
  457nr_test((-3),12).
  458nr_test((-4), 14).
  459nr_test((-4), 0).
  460nr_test(45,0).
  461nr_test(45,9).
  462nr_test((-1),1)