]> Repositorios git - scryer-prolog.git/commitdiff
ENHANCED: CLP(ℤ): Reduce redundant propagator invocations during all_distinct/1 filtering
authorMarkus Triska <[email protected]>
Mon, 25 Jul 2022 18:08:54 +0000 (20:08 +0200)
committerMark Thom <[email protected]>
Thu, 27 Oct 2022 05:36:07 +0000 (23:36 -0600)
First, the current propagator is now logged and not re-triggered
during filtering. Second, and more significantly, all neq_num/2
constraints are scheduled and processed before more global constraints
are invoked. In this way, all the distilled information can be taken
into account by subsequently invoked global constraints.

These changes yield a 3-fold improvement in several Sudoku instances,
and a significant runtime reduction in social golfer instance 8-4-9.

src/lib/clpz.pl

index 94930932683a0739fe5d9792e69a565ea6a59061..6575a32dc85e2137cb056031bdb2fe6cb740980e 100644 (file)
 :- use_module(library(si)).
 :- use_module(library(freeze)).
 :- use_module(library(arithmetic)).
+:- use_module(library(debug)).
+:- use_module(library(format)).
 
 % :- use_module(library(types)).
 
@@ -2241,8 +2243,8 @@ all_distinct(Ls) :-
         fd_must_be_list(Ls, all_distinct(Ls)-1),
         maplist(fd_variable, Ls),
         make_propagator(pdistinct(Ls), Prop),
-        distinct_attach(Ls, Prop, []),
-        trigger_once(Prop).
+        new_queue(Q0),
+        phrase((distinct_attach(Ls, Prop, []),trigger_prop(Prop),do_queue), [Q0], _).
 
 %% nvalue(?N, +Vars).
 %
@@ -4050,12 +4052,13 @@ trigger_props(fd_props(Gs,Bs,Os)) -->
 trigger_props_([]) --> [].
 trigger_props_([P|Ps]) --> trigger_prop(P), trigger_props_(Ps).
 
-trigger_prop(_P) :- true. % TODO: What to do?
+trigger_prop(P) :- trigger_once(P).
 
 trigger_prop(Propagator) -->
         { propagator_state(Propagator, State) },
         (   { State == dead } -> []
         ;   { get_attr(State, clpz_aux, queued) } -> []
+        ;   { bb_get('$clpz_current_propagator', C), C == State } -> []
         ;   % passive
             %{ format("triggering: ~w\n", [Propagator]) },
             { put_attr(State, clpz_aux, queued) },
@@ -4148,12 +4151,13 @@ no_reactivation(pgcc_single(_,_)).
 %no_reactivation(scalar_product(_,_,_,_)).
 
 activate_propagator(propagator(P,State)) -->
+        % { portray_clause(running(P)) },
         (   State == dead -> []
         ;   { del_attr(State, clpz_aux) },
             (   { no_reactivation(P) } ->
-                %b_setval('$clpz_current_propagator', State), TODO
-                run_propagator(P, State)
-                %b_setval('$clpz_current_propagator', [])
+                { bb_b_put('$clpz_current_propagator', State) },
+                run_propagator(P, State),
+                { bb_b_put('$clpz_current_propagator', []) }
             ;   run_propagator(P, State)
             )
         ).
@@ -4199,7 +4203,8 @@ queue_get_arg_(Queue, Which, Element) :-
         ).
 
 queue_enabled --> state(queue(_,_,_,Aux)), { \+ get_atts(Aux, +enabled(false)) }.
-
+disable_queue --> state(queue(_,_,_,Aux)), { put_atts(Aux, +enabled(false)) }.
+enable_queue --> state(queue(_,_,_,Aux)), { put_atts(Aux, +enabled(true)) }.
 
 portray_propagator(propagator(P,_), F) :- functor(P, F, _).
 
@@ -4394,14 +4399,14 @@ run_propagator(pdifferent(Left,Right,X,_), MState) -->
         run_propagator(pexclude(Left,Right,X), MState).
 
 run_propagator(pexclude(Left,Right,X), _) -->
-        (   ground(X) ->
-              disable_queue,
-              exclude_fire(Left, Right, X),
-              enable_queue
-          ;   true
-          ) }.
+        (   ground(X) ->
+            disable_queue,
+            exclude_fire(Left, Right, X),
+            enable_queue
+        ;   true
+        ).
 
-run_propagator(pdistinct(Ls), _MState) --> { distinct(Ls) }.
+run_propagator(pdistinct(Ls), _MState) --> distinct(Ls).
 
 run_propagator(pnvalue(N, Vars), _MState) --> { propagate_nvalue(N, Vars) }.
 
@@ -4435,8 +4440,8 @@ run_propagator(pgcc(Vs, _, Pairs), _) --> { gcc_global(Vs, Pairs) }.
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 run_propagator(pcircuit(Vs), _MState) -->
-        distinct(Vs),
-          propagate_circuit(Vs) }.
+        distinct(Vs),
+        { propagate_circuit(Vs) }.
 
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -5933,12 +5938,12 @@ max_factor(L1, U1, L2, U2, Max) :-
    CSPs", AAAI-94, Seattle, WA, USA, pp 362--367, 1994
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-distinct_attach([], _, _).
-distinct_attach([X|Xs], Prop, Right) :-
+distinct_attach([], _, _) --> [].
+distinct_attach([X|Xs], Prop, Right) -->
         (   var(X) ->
-            init_propagator(X, Prop),
-            make_propagator(pexclude(Xs,Right,X), P1),
-            init_propagator(X, P1),
+            init_propagator(X, Prop),
+              make_propagator(pexclude(Xs,Right,X), P1),
+              init_propagator(X, P1) },
             trigger_prop(P1)
         ;   exclude_fire(Xs, Right, X)
         ),
@@ -6158,8 +6163,8 @@ with_local_attributes(Vars, Goal, Result) :-
               local_attributes(Result,Vars),
               true).
 
-distinct(Vars) :-
-        with_local_attributes(Vars,
+distinct(Vars) -->
+        with_local_attributes(Vars,
            (   difference_arcs(Vars, FreeLeft, FreeRight0),
                length(FreeLeft, LFL),
                length(FreeRight0, LFR),
@@ -6170,11 +6175,16 @@ distinct(Vars) :-
                maplist(g_g0, FreeLeft),
                scc(FreeLeft, g0_successors),
                maplist(dfs_used, FreeRight),
-               phrase(distinct_goals(FreeLeft), Gs)), Gs),
+               phrase(distinct_goals(FreeLeft), Gs)), Gs) },
         disable_queue,
-        maplist(call, Gs),
+        neq_nums(Gs),
         enable_queue.
 
+neq_nums([]) --> [].
+neq_nums([neq_num(V,N)|VNs]) -->
+        % { portray_clause(neq_num(V, N)) },
+        neq_num(V, N), neq_nums(VNs).
+
 distinct_goals([]) --> [].
 distinct_goals([V|Vs]) -->
         { get_attr(V, edges, Es) },
@@ -6189,7 +6199,7 @@ distinct_goals_([flow_to(F,To)|Es], V) -->
               get_attr(To, lowlink, L2),
               L1 =\= L2 } ->
             { get_attr(To, value, N) },
-            [clpz:neq_num(V, N)]
+            [neq_num(V, N)]
         ;   []
         ),
         distinct_goals_(Es, V).
@@ -6381,6 +6391,10 @@ exclude_fire(Left, Right, E) :-
         all_neq(Left, E),
         all_neq(Right, E).
 
+exclude_fire(Left, Right, E) -->
+        all_neq(Left, E),
+        all_neq(Right, E).
+
 list_contains([X|Xs], Y) :-
         (   X == Y -> true
         ;   list_contains(Xs, Y)
@@ -6942,6 +6956,11 @@ vs_key_min_others([V|Vs], Key, Min0, Min, Others) :-
             )
         ).
 
+all_neq([], _) --> [].
+all_neq([X|Xs], C) -->
+        neq_num(X, C),
+        all_neq(Xs, C).
+
 all_neq([], _).
 all_neq([X|Xs], C) :-
         neq_num(X, C),
@@ -6973,8 +6992,8 @@ circuit(Vs) :-
         (   L =:= 1 -> true
         ;   neq_index(Vs, 1),
             make_propagator(pcircuit(Vs), Prop),
-            distinct_attach(Vs, Prop, []),
-            trigger_once(Prop)
+            new_queue(Q0),
+            phrase((distinct_attach(Vs, Prop, []),trigger_prop(Prop),do_queue), [Q0], _)
         ).
 
 neq_index([], _).