:- module(meld_interpreter, [ live/0, delete/1, push/1, first/2, min/3, max/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 ]). :- 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 \= neighbor/2, % P \= root/1, listing(meld_program:P), fail. done. delete(Fact) :- nb_getval(meld_queue, Queue), retract(meld_program:Fact), nb_queue_enqueue(Queue, deleted(Fact)), live. 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). % 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). 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)). 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) ).