diff --git a/library/gecode/Makefile.in b/library/gecode/Makefile.in index a770a413c..047553535 100644 --- a/library/gecode/Makefile.in +++ b/library/gecode/Makefile.in @@ -72,5 +72,7 @@ clean: install: all mkdir -p $(DESTDIR)$(YAPLIBDIR) mkdir -p $(DESTDIR)$(SHAREDIR)/Yap + mkdir -p $(DESTDIR)$(SHAREDIR)/Yap/gecode $(INSTALL_PROGRAM) $(SOBJS) $(DESTDIR)$(YAPLIBDIR) $(INSTALL) gecode.yap $(DESTDIR)$(SHAREDIR)/Yap + $(INSTALL) $(srcdir)/clpfd.yap $(DESTDIR)$(SHAREDIR)/Yap/gecode diff --git a/library/gecode/clp_examples/photo.yap b/library/gecode/clp_examples/photo.yap new file mode 100644 index 000000000..dd97c5c68 --- /dev/null +++ b/library/gecode/clp_examples/photo.yap @@ -0,0 +1,68 @@ +%% -*- prolog -*- +%%============================================================================= +%% Copyright (C) 2011 by Denys Duchier +%% +%% This program is free software: you can redistribute it and/or modify it +%% under the terms of the GNU Lesser General Public License as published by the +%% Free Software Foundation, either version 3 of the License, or (at your +%% option) any later version. +%% +%% This program is distributed in the hope that it will be useful, but WITHOUT +%% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +%% FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +%% more details. +%% +%% You should have received a copy of the GNU Lesser General Public License +%% along with this program. If not, see . +%%============================================================================= + +:- use_module(library(gecode/clpfd)). +:- use_module(library(maplist)). + +% 5 people want to have a photograph together, but they have preferences. +photo(Ex, Solution,Amount) :- + db(Ex, People, Preferences), + length(People, Len), + Len0 is Len-1, + People ins 0..Len0, + all_distinct(People), + % Bools are the satisfied constraints + maplist(preferences, Preferences, Bools), + length(Preferences, PLen), + Sum in 0..PLen, + Bools #= Sum, + % add all satisfied constraints + maximize(Sum), + labeling([], People). + +%reification, use with care +preferences(X-Y, B) :- + abs(X - Y) #= 1 #<==> B. + +db(s,[Alice,Bob,Carl,Deb,Evan], [Alice-Carl, + Carl-Deb, + Deb-Alice, + Evan-Alice, + Bob-Evan, + Carl-Evan, + Deb-Evan, + Evan-Bob]). + +db(l,[Betty,Chris,Donald,Fred,Gary,Mary,Paul,Peter,Susan], + [Betty-Donald, + Betty-Gary, + Betty-Peter, + Chris-Gary, + Chris-Susan, + Donald-Fred, + Donald-Gary, + Fred-Betty, + Fred-Gary, + Gary-Mary, + Gary-Betty, + Mary-Betty, + Mary-Susan, + Paul-Donald, + Paul-Peter, + Peter-Susan, + Peter-Paul]). diff --git a/library/gecode/clp_examples/queens.yap b/library/gecode/clp_examples/queens.yap index c9fed83a2..4131a68f5 100644 --- a/library/gecode/clp_examples/queens.yap +++ b/library/gecode/clp_examples/queens.yap @@ -1,12 +1,28 @@ +:- use_module(library(gecode/clpfd)). :- use_module(library(maplist)). -:- [ge_clpfd]. queens(N, Queens) :- length(Queens, N), - Queens ins 1..9, + Queens ins 1..N, all_distinct(Queens), - lconstrain( Queens, 0), + foldl(inc, Queens, Inc, 0, _), % [0, 1, 2, .... ] + foldl(dec, Queens, Dec, 0, _), % [0, -1, -2, ... ] + all_distinct(Inc,Queens), + all_distinct(Dec,Queens), + labeling([], Queens). + +inc(_, I0, I0, I) :- + I is I0+1. + +dec(_, I0, I0, I) :- + I is I0-1. + +lqueens(N, Queens) :- + length(Queens, N), + Queens ins 1..N, + all_distinct(Queens), + lconstrain( Queens, 0 ), labeling([], Queens). lconstrain([], _). @@ -19,3 +35,4 @@ constrain(Q, I, R, J, J1) :- J1 is J+1, Q + I #\= R + J, Q - I #\= R - J. + diff --git a/library/gecode/clpfd.yap b/library/gecode/clpfd.yap index 98b03aa04..8ee9a603c 100644 --- a/library/gecode/clpfd.yap +++ b/library/gecode/clpfd.yap @@ -1,4 +1,4 @@ -:- module(ge_clpfd, [ +:- module(clpfd, [ op(760, yfx, #<==>), op(750, xfy, #==>), op(750, yfx, #<==), @@ -21,16 +21,17 @@ (#=<)/2, (#=)/2, (#\=)/2, -/* (#\)/1, (#<==>)/2, (#==>)/2, (#<==)/2, + (#\)/1, (#\/)/2, - (#/\)/2, */ + (#/\)/2, in/2 , ins/2, all_different/1, - all_distinct/1, /* + all_distinct/1, + all_distinct/2, /* sum/3, scalar_product/4, tuples_in/2, */ @@ -74,6 +75,7 @@ constraint( in(_, _) ). %2, constraint( ins(_, _) ). %2, constraint( all_different(_) ). %1, constraint( all_distinct(_) ). %1, +constraint( all_distinct(_,_) ). %1, constraint( sum(_, _, _) ). %3, constraint( scalar_product(_, _, _, _) ). %4, constraint( tuples_in(_, _) ). %2, @@ -108,35 +110,62 @@ process_constraints(B, B, _Env). % process_constraint(B, NB, Space). ( A #= B) :- - get_home(Space-Map), - linear(A, 1, As, Bs, CAs, CBs, 0, A0, Space-Map), - linear(B, -1, Bs, [], CBs, [], A0, B0, Space-Map), - Space += linear(CAs, As, 'IRT_EQ', B0). + get_home(Env), + post( (A #= B), Env, _). ( A #\= B) :- - get_home(Space-Map), - linear(A, 1, As, Bs, CAs, CBs, 0, A0, Space-Map), - linear(B, -1, Bs, [], CBs, [], A0, B0, Space-Map), - Space += linear(CAs, As, 'IRT_NQ', B0). + get_home(Env), + post( (A #\= B), Env, _). ( A #< B) :- - get_home(Space-Map), - linear(A, 1, As, Bs, CAs, CBs, 0, A0, Space-Map), - linear(B, -1, Bs, [], CBs, [], A0, B0, Space-Map), - Space += linear(CAs, As, 'IRT_LE', B0). + get_home(Env), + post( (A #< B), Env, _). ( A #> B) :- - get_home(Space-Map), - linear(A, 1, As, Bs, CAs, CBs, 0, A0, Space-Map), - linear(B, -1, Bs, [], CBs, [], A0, B0, Space-Map), - Space += linear(CAs, As, 'IRT_GT', B0). + get_home(Env), + post( (A #< B), Env, _). ( A #=< B) :- - get_home(Space-Map), - linear(A, 1, As, Bs, CAs, CBs, 0, A0, Space-Map), - linear(B, -1, Bs, [], CBs, [], A0, B0, Space-Map), - Space += linear(CAs, As, 'IRT_LQ', B0). + get_home(Env), + post( (A #=< B), Env, _). ( A #>= B) :- + get_home(Env), + post( (A #> B), Env, _). +( A #<==> Bool) :- get_home(Space-Map), - linear(A, 1, As, Bs, CAs, CBs, 0, A0, Space-Map), - linear(B, -1, Bs, [], CBs, [], A0, B0, Space-Map), - Space += linear(CAs, As, 'IRT_GQ', B0). + Bool := boolvar(Space), + Space += reify(Bool, 'RM_EQV', R), + post(A, Space-Map, R). +( A #==> Bool) :- + get_home(Space-Map), + Bool := boolvar(Space), + Space += reify(Bool, 'RM_IMP', R), + post(A, Space-Map, R). +( A #<== Bool) :- + get_home(Space-Map), + Bool := boolvar(Space), + Space += reify(Bool, 'RM_PMI', R), + post(A, Space-Map, R). +'#\\'(A) :- + get_home(Space-Map), + B := boolvar(Space), + Space += reify(B, 'RM_EQV', R), + Space += rel(B, 'BOT_EQV', 0), + post(A, Space-Map, R). +( A1 #\/ A2 ) :- + get_home(Space-Map), + B1 := boolvar(Space), + B2 := boolvar(Space), + Space += reify(B1, 'RM_EQV', R1), + Space += reify(B2, 'RM_EQV', R2), + post(A1, Space-Map, R1), + post(A2, Space-Map, R2), + Space += rel(B1, B2, 'BOT_OR', 1). +( A1 #/\ A2 ) :- + get_home(Space-Map), + B1 := boolvar(Space), + B2 := boolvar(Space), + Space += reify(B1, 'RM_EQV', R1), + Space += reify(B2, 'RM_EQV', R2), + post(A1, Space-Map, R1), + post(A2, Space-Map, R2), + Space += rel(B1, B2, 'BOT_AND', 1). ( X in A..B) :- get_home(Space-Map), m(X, NX, A, B, Map), @@ -147,28 +176,95 @@ process_constraints(B, B, _Env). length(Xs, N), NXs := intvars(Space, N, A, B). all_different( Xs ) :- - get_home(Space-Map), - maplist(ll(Map), Xs, NXs), - Space += distinct(NXs). + get_home(Env), + post( all_different( Xs ), Env, _ ). all_distinct( Xs ) :- - get_home(Space-Map), - maplist(ll(Map), Xs, NXs), - Space += distinct(NXs). + get_home(Env), + post( all_distinct( Xs ), Env, _ ). +all_distinct( Cs, Xs ) :- + get_home(Env), + post( all_distinct( Cs, Xs ), Env, _ ). labeling(_Opts, Xs) :- get_home(Space-Map), maplist(ll(Map), Xs, NXs), Space += branch(NXs, 'INT_VAR_SIZE_MIN', 'INT_VAL_MIN'). + +post( (A #= B), Space-Map, Reify):- + linear(A, 1, As, Bs, CAs, CBs, 0, A0, Space-Map), + linear(B, -1, Bs, [], CBs, [], A0, B0, Space-Map), + (var(Reify) -> + Space += linear(CAs, As, 'IRT_EQ', B0); + Space += linear(CAs, As, 'IRT_EQ', B0, Reify) + ). +post( (A #\= B), Space-Map, Reify):- + linear(A, 1, As, Bs, CAs, CBs, 0, A0, Space-Map), + linear(B, -1, Bs, [], CBs, [], A0, B0, Space-Map), + (var(Reify) -> + Space += linear(CAs, As, 'IRT_NQ', B0); + Space += linear(CAs, As, 'IRT_NQ', B0, Reify) + ). +post( (A #>B), Space-Map, Reify):- + linear(A, 1, As, Bs, CAs, CBs, 0, A0, Space-Map), + linear(B, -1, Bs, [], CBs, [], A0, B0, Space-Map), + (var(Reify) -> + Space += linear(CAs, As, 'IRT_NQ', B0); + Space += linear(CAs, As, 'IRT_NQ', B0, Reify) + ). +post( (A #>=B), Space-Map, Reify):- + linear(A, 1, As, Bs, CAs, CBs, 0, A0, Space-Map), + linear(B, -1, Bs, [], CBs, [], A0, B0, Space-Map), + (var(Reify) -> + Space += linear(CAs, As, 'IRT_GQ', B0); + Space += linear(CAs, As, 'IRT_GQ', B0, Reify) + ). +post( (A # + Space += linear(CAs, As, 'IRT_LE', B0); + Space += linear(CAs, As, 'IRT_LE', B0, Reify) + ). +post( (A #= + Space += linear(CAs, As, 'IRT_LQ', B0); + Space += linear(CAs, As, 'IRT_LQ', B0, Reify) + ). +post( all_different( Xs ), Space-Map, Reify) :- + maplist(ll(Map), Xs, NXs), + (var(Reify) -> + Space += distinct(NXs) + ; + throw(error(domain(not_reifiable),all_different( Xs ))) + ). +post( all_distinct( Xs ), Space-Map, Reify) :- + maplist(ll(Map), Xs, NXs), + (var(Reify) -> + Space += distinct(NXs) + ; + throw(error(domain(not_reifiable),all_distinct( Xs ))) + ). +post( all_distinct( Cs , Xs ), Space-Map, Reify) :- + maplist(ll(Map), Xs, NXs), + (var(Reify) -> + Space += distinct(Cs,NXs) + ; + throw(error(domain(not_reifiable),all_distinct( Cs , Xs ))) + ). + + linear(V, C, [A|As], As, [C|CAs], CAs, I, I, _-Map) :- var(V), !, l(V, A, Map). -linear(A+B, C, As, Bs, CAs, CBs, I, IF, Space) :- - linear(A, C, As, A1s, CAs, CA1s, I, I1, Space), - linear(B, C, A1s, Bs, CA1s, CBs, I1, IF, Space). -linear(A-B, C, As, Bs, CAs, CBs, I, IF, Space) :- +linear(A+B, C, As, Bs, CAs, CBs, I, IF, Env) :- + linear(A, C, As, A1s, CAs, CA1s, I, I1, Env), + linear(B, C, A1s, Bs, CA1s, CBs, I1, IF, Env). +linear(A-B, C, As, Bs, CAs, CBs, I, IF, Env) :- NC is -C, - linear(A, C, As, A1s, CAs, CA1s, I, I1, Space), - linear(B, NC, A1s, Bs, CA1s, CBs, I1, IF, Space). + linear(A, C, As, A1s, CAs, CA1s, I, I1, Env), + linear(B, NC, A1s, Bs, CA1s, CBs, I1, IF, Env). linear(A, C, As, As, CAs, CAs, I, IF, _) :- integer(A), !, IF is I-C*A. @@ -176,16 +272,63 @@ linear(A, C, As, As, CAs, CAs, I, IF, _) :- ground(A), catch( (B is eval(A)), _, fail ), !, IF is I-C*B. -linear(C1*B, C, As, Bs, CAs, CBs, I, IF, Space) :- +linear(C1*B, C, As, Bs, CAs, CBs, I, IF, Env) :- integer(C1), !, NC is C*C1, - linear(B, NC, As, Bs, CAs, CBs, I, IF, Space). -linear(B*C1, C, As, Bs, CAs, CBs, I, IF, Space) :- + linear(B, NC, As, Bs, CAs, CBs, I, IF, Env). +linear(B*C1, C, As, Bs, CAs, CBs, I, IF, Env) :- integer(C1), !, NC is C*C1, - linear(B, NC, As, Bs, CAs, CBs, I, IF, Space). + linear(B, NC, As, Bs, CAs, CBs, I, IF, Env). +linear(AC, C, [V|Bs], Bs, [C|CBs], CBs, I, I, Env) :- + arith(AC), + equality(AC, V, Env). -user:term_expansion( ( H :- B), (H :- (ge_clpfd:init_gecode(Space, Me), NB, ge_clpfd:close_gecode(Space, Vs, Me)) ) ) :- +equality(abs(V), NV, Env) :- + ( var(V) -> VA = V ; equality(V, VA, Env) ), + new_abs(VA, NV, Env). +equality(V1+V2, NV, Env) :- + ( var(V1) -> V1A = V1 ; equality(V1, V1A, Env) ), + ( var(V2) -> V2A = V2 ; equality(V2, V2A, Env) ), + new_plus(V1A, V2A, NV, ENV). +equality(V1-V2, NV, Env) :- + ( var(V1) -> V1A = V1 ; equality(V1, V1A, Env) ), + ( var(V2) -> V2A = V2 ; equality(V2, V2A, Env) ), + new_minus(V1A, V2A, NV, ENV). + +new_abs( V, NV, Space-Map) :- + l(V, X, Min0, Max0, Map), + ( Min0 < 0 -> + ( Max0 < 0 -> Min is -Max0, Max is -Min0 ; + Min = 0 , Max is max( -Min, Max ) ) + ; + Min = Min0, Max = Max0 + ), + NX := intvar(Space, Min, Max), + m(NV, NX, Min, Max, Map), + Space += abs(X, NX). + +new_minus( V1, V2, NV, Space-Map) :- + l(V1, X1, Min1, Max1, Map), + l(V2, X2, Min2, Max2, Map), + Min is Min1-Max2, + Max is Max1-Min2, + NX := intvar(Space, Min, Max), + m(NV, NX, Min, Max, Map), + Space += linear([1,-1], [X1,X2], NX). + +new_plus( V1, V2, NV, Space-Map) :- + l(V1, X1, Min1, Max1, Map), + l(V2, X2, Min2, Max2, Map), + Min is Min1+Min2, + Max is Max1+Max2, + NX := intvar(Space, Min, Max), + m(NV, NX, Min, Max, Map), + Space += linear([1,1], [X1,X2], NX). + + + +user:term_expansion( ( H :- B), (H :- (clpfd:init_gecode(Space, Me), NB, clpfd:close_gecode(Space, Vs, Me)) ) ) :- process_constraints(B, NB, Env), term_variables(H, Vs), nonvar( Env ), !, @@ -231,3 +374,11 @@ l(NV, OV, [_|Vs]) :- ll(Map, X, Y) :- l(X, Y, Map). +l(NV, OV, _, _, Vs) :- + var(Vs), !, + fail. +l(NV, OV, A, B, [v(V, OV, A, B)|_Vs]) :- + V == NV, !. +l(NV, O, A, BV, [_|Vs]) :- + l(NV, OV, A, B, Vs). + diff --git a/library/gecode/gecode3_yap.cc b/library/gecode/gecode3_yap.cc index 02283d31a..9cd3c67a8 100644 --- a/library/gecode/gecode3_yap.cc +++ b/library/gecode/gecode3_yap.cc @@ -16,7 +16,7 @@ // along with this program. If not, see . //============================================================================= -#include "gecode-common.icc" +#include "gecode3-common.icc" #include using namespace std; using namespace generic_gecode;