:- module(meld_interpreter, [ live/0, delete/1, push/1, first/2, min/3, max/3, sum/3, minval/3, maxval/3 ]). :- use_module(meldp, [ run/1 ]). :- use_module(library(nb), [ nb_queue/1, nb_queue_enqueue/2, nb_queue_dequeue/2, nb_queue_replace/3 ]). :- initialization init_meld_queue. :- dynamic speculative_delete/3. live :- repeat, ( pop(Goal) -> % format('<- ~w~n',[Goal]), run(Goal), fail ; !, done ). done :- speculative_delete(_, _, _), !, push_residuals, live. done :- current_predicate(meld_program:P), P \= run/1, P \= trace/2, % P \= neighbor/2, % P \= root/1, listing(meld_program:P), fail. done. delete(Fact) :- once(retract(meld_program:Fact)), nb_getval(meld_queue, Queue), ( % nb:nb_queue_show(Queue, L ), writeln(show:Fact:L), nb_queue_replace(Queue, Fact, [] ), % format('R ~w~n', [Fact]), deleted(Fact) -> true ; nb_queue_enqueue(Queue, deleted(Fact)) ). pop(Goal) :- nb_getval(meld_queue, Queue), nb_queue_dequeue(Queue, Goal). push(Goal) :- clause(meld_program:Goal,_,Ref), !, increase_reference_count(Ref), fail. push(Goal) :- % format('-> ~w~n',[Goal]), nb_getval(meld_queue, Queue), !, assert(meld_program:Goal), nb_queue_enqueue(Queue, Goal), % nb:nb_queue_show(Queue, L ), writeln(show:Goal:L), fail. % create a queue init_meld_queue :- nb_queue(Queue), nb_setval(meld_queue, Queue). first(Skel,Goal) :- meld_program:Skel, !, cache(Goal). first(_,Goal) :- cache(Goal), push(Goal). max(Skel,Arg,Goal) :- meld_program:Skel, arg(Arg, Skel, A0), arg(Arg, Goal, AN), AN =< A0, !, delete(Skel), cache(Goal). max(Skel,_,Goal) :- clean(Skel), cache(Goal), push(Goal). min(Skel,Arg,Goal) :- meld_program:Skel, arg(Arg, Skel, A0), arg(Arg, Goal, AN), AN >= A0, !, delete(Skel), cache(Goal). min(Skel,_,Goal) :- clean(Skel), cache(Goal), push(Goal). sum(Skel,Arg,Goal) :- copy_term(Skel, NGoal), meld_program:Skel, !, arg(Arg, Skel, A0), arg(Arg, Goal, A), AN is A0+A, AN \= A0, delete(Skel), arg(Arg, NGoal, AN), % format('S ~w~n',[NGoal-Skel]), push(NGoal). sum(_Skel,_Arg,Goal) :- % format('S ~w~n',[Goal]), push(Goal). clean(Skel) :- % format('D~w~n',[Skel]), retractall(meld_program:Skel). cache(Goal) :- clause(meld_cache:Goal,_,Ref), !, increase_reference_count(Ref). cache(Goal) :- assert(meld_cache:Goal). deleted(Goal) :- clause(meld_program:Goal,_,Ref), decrease_reference_count(Ref), !, force_delete(Goal, Ref), complete_delete(Goal). deleted(Goal) :- retract(speculative_delete(Goal, Ref, Count)), !, NCount is Count-1, ( NCount > 0 -> assert(speculative_delete(Goal, Ref, Count)) ; true ). deleted(Goal) :- % format('-~w~n',[Goal]), complete_delete(Goal). complete_delete(Goal) :- nb_getval(meld_queue, Queue), !, retract(meld_program:Goal), nb_queue_enqueue(Queue, deleted(Goal)). force_delete(Goal, Ref) :- current_reference_count(Ref, Count), assert(speculative_delete(Goal, Ref, Count)). push_residuals :- retract(speculative_delete(Goal, _, _)), push(Goal), fail. push_residuals. % % first, cleanup cache % delete_from_first(_,Goal) :- clause(meld_program:Goal,_,Ref), !, ( decrease_reference_count(Ref) -> true ; force_delete(Goal, Ref) ), erase(Ref), retract(meld_cache:Goal), retract(meld_program:Goal), push(deleted(Goal)), once(meld_cache:VGoal), push(VGoal). delete_from_first(Goal) :- retract(speculative_delete(Goal, Ref, Count)), !, NCount is Count-1, ( NCount > 0 -> assert(speculative_delete(Goal, Ref, Count)) ; true ). delete_from_first(Goal) :- retract(meld_cache:Goal), push(deleted(Goal)). delete_from_max(VGoal,Arg,Goal) :- clause(meld_program:Goal,_,Ref), !, ( decrease_reference_count(Ref) -> true ; force_delete(Goal, Ref) ), erase(Ref), retract(meld_cache:Goal), push(deleted(Goal)), new_max(VGoal, Arg). delete_from_max(Goal) :- retract(speculative_delete(Goal, Ref, Count)), !, NCount is Count-1, ( NCount > 0 -> assert(speculative_delete(Goal, Ref, Count)) ; true ). delete_from_max(Goal) :- retract(meld_cache:Goal), push(deleted(Goal)). delete_from_sum(Skel,Arg,Goal) :- copy_term(Skel, NGoal), once(meld_program:Skel), arg(Arg, Skel, A0), arg(Arg, Goal, A), AN is A0-A, AN \= A0, delete(Skel), arg(Arg, NGoal, AN), push(NGoal). new_max(VGoal,Arg) :- arg(Arg, VGoal, A), maxval(A, meld_cache:VGoal, VGoal), push(VGoal). delete_from_min(VGoal,Arg,Goal) :- clause(meld_program:Goal,_,Ref), !, ( decrease_reference_count(Ref) -> true ; force_delete(Goal, Ref) ), erase(Ref), retract(meld_cache:Goal), push(deleted(Goal)), new_min(VGoal, Arg). delete_from_min(Goal) :- !, retract(speculative_delete(Goal, Ref, Count)), NCount is Count-1, ( NCount > 0 -> assert(speculative_delete(Goal, Ref, Count)) ; true ). delete_from_min(Goal) :- retract(meld_cache:Goal), push(deleted(Goal)). new_min(VGoal,Arg) :- arg(Arg, VGoal, A), minval(A, meld_cache:VGoal, VGoal), push(VGoal). :- meta_predicate minval(+,:,-), maxval(+,:,-). maxval(V,G,GMax) :- Memory = f(-inf,[]), ( call(G), arg(1, Memory, V0), V > V0, nb_setarg(1, Memory, V), nb_setarg(2, Memory, V.GMax), fail ; arg(2, Memory, V.GMax) ). minval(V,G,GMin) :- Memory = f(+inf,[]), ( call(G), arg(1, Memory, V0), V < V0, nb_setarg(1, Memory, V), nb_setarg(2, Memory, V.GMin), fail ; arg(2, Memory, V.GMin) ).